using System; using EinSoftworks.Camera; using EinSoftworks.Events; using EinSoftworks.Input; using EinSoftworks.StateManagement; using EinSoftworks.Utilities; using Godot; namespace Voider; public partial class LibraryTest : Node { private StateMachine _stateMachine; private HierarchicalStateMachine _hierarchicalSM; private EventBus _eventBus; private int _frameCount = 0; private IdlePlayerState _idleState; private RunningPlayerState _runningState; private JumpingPlayerState _jumpingState; // Camera test fields private FirstPersonCamera _fpCamera; private OrbitCamera _orbitCamera; private Node3D _cameraTarget; private CameraController _activeCamera; public override void _Ready() { GD.Print("=== EinSoftworks Library Integration Test ===\n"); TestUtilities(); TestEvents(); TestInput(); TestStateMachine(); TestHierarchicalStateMachine(); TestCamera(); GD.Print("\n=== All Tests Initialized Successfully ==="); GD.Print("Watch console for runtime behavior...\n"); } public override void _Process(double delta) { _frameCount++; // Update state machines _stateMachine?.Update((float)delta); _hierarchicalSM?.Update((float)delta); // Test transitions every 60 frames if (_frameCount == 60) { GD.Print("\n[Frame 60] Testing state transitions..."); _stateMachine?.ChangeState(_runningState); } else if (_frameCount == 120) { GD.Print("\n[Frame 120] Testing event-triggered transition..."); _stateMachine?.TriggerEvent("jump"); } else if (_frameCount == 180) { GD.Print("\n[Frame 180] Testing hierarchical state change..."); _hierarchicalSM?.ChangeState("Combat"); } else if (_frameCount == 240) { GD.Print("\n[Frame 240] Testing camera mode switch to Orbit..."); if (_orbitCamera != null && _activeCamera != null) { _activeCamera.SetCameraMode(CameraController.CameraMode.Orbit, 1.5f); _orbitCamera.Visible = true; _fpCamera.Visible = false; _activeCamera = _orbitCamera; } } else if (_frameCount == 360) { GD.Print("\n[Frame 360] Testing camera shake effect..."); _activeCamera?.Shake(0.3f, 0.5f); } else if (_frameCount == 420) { GD.Print("\n[Frame 420] Testing camera zoom effect..."); _activeCamera?.Zoom(60f, 1.0f); } } private void TestUtilities() { GD.Print("--- Testing EinSoftworks.Utilities ---"); // Test MathUtils float angle = 90f; float radians = MathUtils.DegreesToRadians(angle); GD.Print($"✓ DegreesToRadians: {angle}° = {radians} rad"); float backToDegrees = MathUtils.RadiansToDegrees(radians); GD.Print($"✓ RadiansToDegrees: {radians} rad = {backToDegrees}°"); float value = 1.5f; float clamped = MathUtils.Clamp01(value); GD.Print($"✓ Clamp01: {value} clamped to {clamped}"); bool approx = MathUtils.Approximately(0.1f + 0.2f, 0.3f); GD.Print($"✓ Approximately: 0.1 + 0.2 ≈ 0.3 = {approx}"); GD.Print(""); } private void TestEvents() { GD.Print("--- Testing EinSoftworks.Events ---"); _eventBus = new EventBus(); // Subscribe to events _eventBus.Subscribe(OnTestEvent); GD.Print($"✓ EventBus created with {_eventBus.SubscriberCount} subscriber"); // Publish an event _eventBus.Publish(new TestEvent("Initialization", 42)); GD.Print(""); } private void TestInput() { GD.Print("--- Testing EinSoftworks.Input ---"); // Create input contexts var gameplayContext = new InputContext( "Gameplay", 10, InputContext.ContextMode.AllowList, false ); gameplayContext.AllowAction("move_left"); gameplayContext.AllowAction("move_right"); gameplayContext.AllowAction("jump"); var menuContext = new InputContext("Menu", 20, InputContext.ContextMode.BlockList, true); menuContext.BlockAction("move_left"); menuContext.BlockAction("move_right"); GD.Print( $"✓ Created InputContext: {gameplayContext.Name} (Priority: {gameplayContext.Priority})" ); GD.Print($"✓ Created InputContext: {menuContext.Name} (Priority: {menuContext.Priority})"); GD.Print(" (InputManager is a Node singleton - add to scene tree for full functionality)"); // Test InputBuffer var inputBuffer = new InputBuffer(0.15f); inputBuffer.BufferInput("jump"); bool hasJump = inputBuffer.IsInputBuffered("jump"); GD.Print($"✓ InputBuffer: Buffered 'jump' action, has buffered = {hasJump}"); GD.Print(""); } private void TestStateMachine() { GD.Print("--- Testing EinSoftworks.StateManagement (Basic) ---"); _stateMachine = new StateMachine(); // Create states _idleState = new IdlePlayerState(); _runningState = new RunningPlayerState(); _jumpingState = new JumpingPlayerState(); // Subscribe to state changes _stateMachine.StateChanged += (from, to) => { GD.Print( $" → State changed: {from?.GetType().Name ?? "null"} → {to?.GetType().Name ?? "null"}" ); }; // Add transitions _stateMachine.AddTransition(_idleState, _runningState, () => false); // Won't trigger automatically _stateMachine.AddTransition(_runningState, _jumpingState, "jump"); // Set initial state _stateMachine.ChangeState(_idleState); GD.Print( $"✓ StateMachine created with initial state: {_stateMachine.CurrentState?.GetType().Name}" ); GD.Print(""); } private void TestHierarchicalStateMachine() { GD.Print("--- Testing EinSoftworks.StateManagement (Hierarchical) ---"); _hierarchicalSM = new HierarchicalStateMachine(); // Create parent states var exploration = "Exploration"; var combat = "Combat"; // Create sub-state machine for combat var combatSubStates = new StateMachine(); combatSubStates.ChangeState("Attacking"); _hierarchicalSM.AddSubStateMachine(combat, combatSubStates); // Subscribe to state changes _hierarchicalSM.StateChanged += (from, to) => { GD.Print($" → Hierarchical state changed: {from ?? "null"} → {to ?? "null"}"); }; // Set initial state _hierarchicalSM.ChangeState(exploration); GD.Print($"✓ HierarchicalStateMachine created with state: {_hierarchicalSM.CurrentState}"); GD.Print(""); } private void TestCamera() { GD.Print("--- Testing EinSoftworks.Camera ---"); // Create a target node for cameras to follow _cameraTarget = new Node3D(); _cameraTarget.Name = "CameraTarget"; _cameraTarget.Position = new Vector3(0, 1, 0); AddChild(_cameraTarget); // Create FirstPersonCamera _fpCamera = new FirstPersonCamera(); _fpCamera.Name = "FirstPersonCamera"; _fpCamera.Target = _cameraTarget; _fpCamera.MouseSensitivity = 0.15f; _fpCamera.MinPitch = -85f; _fpCamera.MaxPitch = 85f; _fpCamera.Position = new Vector3(0, 1.6f, 0); AddChild(_fpCamera); _fpCamera.Camera.MakeCurrent(); _activeCamera = _fpCamera; GD.Print($"✓ Created FirstPersonCamera (Active)"); GD.Print($" - Target: {_fpCamera.Target?.Name}"); GD.Print($" - Mouse Sensitivity: {_fpCamera.MouseSensitivity}"); GD.Print($" - Pitch Range: {_fpCamera.MinPitch}° to {_fpCamera.MaxPitch}°"); // Create OrbitCamera (initially hidden) _orbitCamera = new OrbitCamera(); _orbitCamera.Name = "OrbitCamera"; _orbitCamera.Target = _cameraTarget; _orbitCamera.MinDistance = 3f; _orbitCamera.MaxDistance = 10f; _orbitCamera.ZoomSpeed = 1f; _orbitCamera.EnableCollisionAvoidance = true; _orbitCamera.Visible = false; AddChild(_orbitCamera); GD.Print($"✓ Created OrbitCamera (Standby)"); GD.Print($" - Distance Range: {_orbitCamera.MinDistance} to {_orbitCamera.MaxDistance}"); GD.Print($" - Collision Avoidance: {_orbitCamera.EnableCollisionAvoidance}"); // Subscribe to camera events _fpCamera.EventBus.Subscribe(evt => { GD.Print( $" → Camera event: {evt.OldMode} → {evt.NewMode} (Transition: {evt.TransitionTime}s)" ); }); _fpCamera.CameraModeChanged += (oldMode, newMode) => { GD.Print($" → Camera signal: Mode changed from {oldMode} to {newMode}"); }; GD.Print("✓ Subscribed to camera events and signals"); GD.Print(" (Camera will switch modes and demonstrate effects during runtime)"); GD.Print(""); } private void OnTestEvent(TestEvent evt) { GD.Print($" → Event received: {evt.Message} (Value: {evt.Value})"); } public override void _ExitTree() { // Cleanup _eventBus?.Unsubscribe(OnTestEvent); _stateMachine?.Clear(); _hierarchicalSM?.Clear(); // Camera cleanup happens automatically _fpCamera?.QueueFree(); _orbitCamera?.QueueFree(); _cameraTarget?.QueueFree(); } } // Test event class public class TestEvent { public string Message { get; } public int Value { get; } public TestEvent(string message, int value) { Message = message; Value = value; } } // Player state classes for testing public abstract class PlayerState : State { protected string StateName; public override void Enter() { GD.Print($" → Entering {StateName}"); } public override void Update(float delta) { } public override void FixedUpdate(float fixedDelta) { } public override void Exit() { GD.Print($" → Exiting {StateName}"); } } public class IdlePlayerState : PlayerState { public IdlePlayerState() { StateName = "Idle"; } } public class RunningPlayerState : PlayerState { public RunningPlayerState() { StateName = "Running"; } } public class JumpingPlayerState : PlayerState { public JumpingPlayerState() { StateName = "Jumping"; } }