From 0df34ef0ec603ce9183b69f615caacd3749592f5 Mon Sep 17 00:00:00 2001 From: lionarius Date: Tue, 7 Jan 2025 00:48:37 +0300 Subject: [PATCH] reformat --- DoomDeathmatch/DoomDeathmatch.csproj | 2 +- .../src/Component/ConsumableComponent.cs | 14 +- .../Component/MVC/Enemy/EnemyController.cs | 23 +- .../src/Component/MVC/GameController.cs | 10 +- .../src/Component/MVC/Health/HealthView.cs | 2 + .../src/Component/MVC/MovementController.cs | 2 +- .../src/Component/MVC/PlayerController.cs | 46 ++-- .../Component/MVC/Timer/TimerController.cs | 1 + .../Component/MVC/Weapon/WeaponController.cs | 19 +- .../src/Component/MVC/Weapon/WeaponView.cs | 3 +- .../Collision/ColliderForceFieldComponent.cs | 6 +- .../Collision/CollisionManagerComponent.cs | 28 ++- .../src/Component/Physics/DragComponent.cs | 2 +- .../src/Component/Physics/GravityComponent.cs | 9 +- .../Component/Physics/RigidbodyComponent.cs | 41 ++-- .../src/Component/UI/SelectorComponent.cs | 24 ++- .../src/Component/UI/StackComponent.cs | 10 +- .../src/Component/UI/TextAlignComponent.cs | 5 +- .../src/Component/UI/TextInputComponent.cs | 21 +- .../src/Component/UI/UiComponent.cs | 10 +- .../src/Component/UI/UiContainerComponent.cs | 4 +- .../src/Component/Util/BillboardComponent.cs | 4 + .../src/Component/Util/CopySizeComponent.cs | 10 +- .../Component/Util/PlayerMovementComponent.cs | 17 ++ .../src/Scene/GameOver/GameOverScene.cs | 2 + DoomDeathmatch/src/Scene/Main/MainScene.cs | 4 +- DoomDeathmatch/src/Scene/Play/PlayScene.cs | 4 +- .../src/Scene/Play/Prefab/EnemyPrefab.cs | 4 +- .../src/Scene/Play/Prefab/PlayerPrefab.cs | 2 +- DoomDeathmatch/src/Script/AnimationPlayer.cs | 26 +-- .../src/Script/Collision/AABBCollider.cs | 12 +- .../src/Script/Collision/RaycastResult.cs | 1 + .../Condition/TickableTimerCondition.cs | 1 + .../Enemy/Attack/CooldownAttackBehavior.cs | 2 + .../src/Script/Model/Enemy/EnemyData.cs | 3 + .../Movement/FollowPlayerMovementBehavior.cs | 2 +- .../src/Script/Model/HealthModel.cs | 34 +-- .../Weapon/RandomFlatSpreadShootPattern.cs | 2 +- .../src/Script/Model/Weapon/WeaponData.cs | 28 ++- .../src/Script/Model/WeaponModel.cs | 6 +- .../Provider/WeightedRandomValueProvider.cs | 6 +- DoomDeathmatch/src/Script/Score/ScoreTable.cs | 10 +- DoomDeathmatch/src/UiUtil.cs | 2 + Engine/Engine.csproj | 5 +- Engine/src/Asset/Font/Font.cs | 29 ++- Engine/src/Asset/Font/FontIterator.cs | 73 +++---- Engine/src/Asset/Image.cs | 4 +- Engine/src/Asset/Mesh/Loader/ObjMeshLoader.cs | 8 +- Engine/src/Asset/Mesh/Loader/StlMeshLoader.cs | 8 +- Engine/src/Asset/Mesh/Mesh.cs | 8 +- Engine/src/Engine.cs | 35 ++-- Engine/src/EngineBuilder.cs | 22 +- Engine/src/Graphics/Buffer/VertexArray.cs | 6 +- Engine/src/Graphics/Debug.cs | 2 +- .../src/Graphics/Framebuffer/Framebuffer.cs | 1 + Engine/src/Graphics/GenericRenderer.cs | 10 +- Engine/src/Graphics/IPresenter.cs | 12 +- Engine/src/Graphics/Pipeline/RenderLayer.cs | 12 +- .../src/Graphics/Pipeline/RenderPipeline.cs | 6 - .../src/Graphics/Render/InstancedRenderer.cs | 19 +- .../Graphics/Render/Mesh/AnyMeshRenderer.cs | 2 + .../src/Graphics/Render/Quad/QuadRenderer.cs | 3 +- .../src/Graphics/Render/Text/TextRenderer.cs | 30 +-- Engine/src/Graphics/Renderer.cs | 60 +++--- Engine/src/Graphics/Texture/IConstTexture.cs | 2 - Engine/src/Graphics/Texture/Texture.cs | 3 - Engine/src/Input/KeyboardButtonCode.cs | 12 +- Engine/src/Input/WindowInputHandler.cs | 5 +- Engine/src/Resource/Loader/ImageLoader.cs | 5 +- Engine/src/Resource/Loader/ProgramLoader.cs | 6 +- Engine/src/Resource/ResourceHandle.cs | 36 ---- Engine/src/Resource/ResourceManager.cs | 17 +- Engine/src/Resource/ShaderResource.resx | 5 +- .../Component/BuiltIn/OrthographicCamera.cs | 23 +- .../Component/BuiltIn/PerspectiveCamera.cs | 8 +- .../BuiltIn/Renderer/Box2DRenderer.cs | 2 +- .../BuiltIn/Renderer/TextRenderer.cs | 5 +- .../src/Scene/Component/BuiltIn/Transform.cs | 34 +-- Engine/src/Scene/GameObject.cs | 75 ++++--- Engine/src/Scene/Hierarchy.cs | 3 +- Engine/src/Scene/Scene.cs | 95 +++++---- Engine/src/Scene/SceneManager.cs | 25 +-- Engine/src/Util/TickableTimer.cs | 43 ++-- Engine/src/Window.cs | 26 +-- PresenterConsole/PresenterConsole.csproj | 2 +- PresenterConsole/src/ConsoleFastOutput.cs | 14 +- PresenterConsole/src/ConsoleInputHandler.cs | 13 +- PresenterConsole/src/ConsolePresenter.cs | 69 +++--- PresenterConsole/src/Program.cs | 5 +- .../src/Resource/ShaderResource.resx | 5 +- PresenterNative/PresenterNative.csproj | 2 +- PresenterWpf/PresenterWpf.csproj | 2 +- PresenterWpf/src/App.xaml | 3 +- PresenterWpf/src/App.xaml.cs | 49 ++--- PresenterWpf/src/MainWindow.xaml | 1 - PresenterWpf/src/MainWindow.xaml.cs | 20 +- PresenterWpf/src/WPFInputHandler.cs | 196 +++++++++--------- 97 files changed, 866 insertions(+), 764 deletions(-) delete mode 100644 Engine/src/Graphics/Pipeline/RenderPipeline.cs delete mode 100644 Engine/src/Resource/ResourceHandle.cs diff --git a/DoomDeathmatch/DoomDeathmatch.csproj b/DoomDeathmatch/DoomDeathmatch.csproj index e1baa34..7763b52 100644 --- a/DoomDeathmatch/DoomDeathmatch.csproj +++ b/DoomDeathmatch/DoomDeathmatch.csproj @@ -7,7 +7,7 @@ - + diff --git a/DoomDeathmatch/src/Component/ConsumableComponent.cs b/DoomDeathmatch/src/Component/ConsumableComponent.cs index e7ae114..9a06378 100644 --- a/DoomDeathmatch/src/Component/ConsumableComponent.cs +++ b/DoomDeathmatch/src/Component/ConsumableComponent.cs @@ -39,16 +39,22 @@ public class ConsumableComponent : Engine.Scene.Component.Component private void OnCollision(AABBColliderComponent parCollider) { if (parCollider.ColliderGroups.Contains("player")) + { TryConsume(parCollider); + } else if (parCollider.ColliderGroups.Contains("consumable")) + { MoveAway(parCollider); + } } private void TryConsume(AABBColliderComponent parCollider) { var playerController = parCollider.GameObject.GetComponent(); if (playerController == null) + { return; + } _consumable.Consume(playerController); @@ -61,17 +67,21 @@ public class ConsumableComponent : Engine.Scene.Component.Component parCollider.GameObject.Transform.GetFullTranslation(); if (direction.LengthSquared <= float.Epsilon) + { direction = GetRandomDirection(); + } else + { direction.Normalize(); + } _movementController.ApplyMovement(direction); } private Vector3 GetRandomDirection() { - var x = _random.NextSingle() * 2 - 1; - var y = _random.NextSingle() * 2 - 1; + var x = (_random.NextSingle() * 2) - 1; + var y = (_random.NextSingle() * 2) - 1; return new Vector3(x, y, 0).Normalized(); } diff --git a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs index 34561ce..a95526e 100644 --- a/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs +++ b/DoomDeathmatch/src/Component/MVC/Enemy/EnemyController.cs @@ -8,16 +8,15 @@ namespace DoomDeathmatch.Component.MVC.Enemy; public class EnemyController : Engine.Scene.Component.Component { - public HealthController HealthController => _healthController; - - private GameController _gameController = null!; - private HealthController _healthController = null!; - private EnemyView _enemyView = null!; - private MovementController _movementController = null!; - private AttackBehavior _attackBehavior = null!; + public HealthController HealthController { get; private set; } = null!; private readonly EnemyData _enemyData; + private GameController _gameController = null!; + private MovementController _movementController = null!; + private AttackBehavior _attackBehavior = null!; + private EnemyView _enemyView = null!; + public EnemyController(EnemyData parEnemyData) { _enemyData = parEnemyData; @@ -26,19 +25,19 @@ public class EnemyController : Engine.Scene.Component.Component public override void Awake() { _gameController = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent()!; - _healthController = GameObject.GetComponent()!; + HealthController = GameObject.GetComponent()!; _enemyView = GameObject.GetComponent()!; _movementController = GameObject.GetComponent()!; ArgumentNullException.ThrowIfNull(_gameController); - ArgumentNullException.ThrowIfNull(_healthController); + ArgumentNullException.ThrowIfNull(HealthController); ArgumentNullException.ThrowIfNull(_enemyView); ArgumentNullException.ThrowIfNull(_movementController); _attackBehavior = _enemyData.AttackBehaviorCreator.Create(this, _gameController.PlayerController.HealthController); - _healthController.SetMaxHealth(_enemyData.BaseHealth); - _healthController.OnDeath += OnDeath; + HealthController.SetMaxHealth(_enemyData.BaseHealth); + HealthController.OnDeath += OnDeath; _enemyView.UpdateView(_enemyData); _movementController.Speed = _enemyData.BaseSpeed; } @@ -47,7 +46,9 @@ public class EnemyController : Engine.Scene.Component.Component { var billboardComponent = GameObject.GetComponentInChildren(); if (billboardComponent == null) + { return; + } billboardComponent.Target = _gameController.PlayerController.Camera.GameObject.Transform; } diff --git a/DoomDeathmatch/src/Component/MVC/GameController.cs b/DoomDeathmatch/src/Component/MVC/GameController.cs index 4d17983..8418a59 100644 --- a/DoomDeathmatch/src/Component/MVC/GameController.cs +++ b/DoomDeathmatch/src/Component/MVC/GameController.cs @@ -9,16 +9,16 @@ namespace DoomDeathmatch.Component.MVC; public class GameController : Engine.Scene.Component.Component { - public bool IsPaused { get; private set; } = false; - public bool IsGameOver { get; private set; } = false; + public bool IsPaused { get; private set; } + public bool IsGameOver { get; private set; } public PlayerController PlayerController { get; private set; } = null!; public ScoreController ScoreController { get; private set; } = null!; - private TimerController _timerController = null!; - - private readonly MenuControllerComponent _menuController; private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; + private readonly MenuControllerComponent _menuController; + + private TimerController _timerController = null!; public GameController(MenuControllerComponent parMenuController) { diff --git a/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs b/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs index b05fa38..9141eae 100644 --- a/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs +++ b/DoomDeathmatch/src/Component/MVC/Health/HealthView.cs @@ -16,7 +16,9 @@ public class HealthView : Engine.Scene.Component.Component { var percentage = parHealthModel.Health / parHealthModel.MaxHealth * 100; if (parHealthModel.Health != 0) + { percentage = Math.Max(1, percentage); + } _healthTextRenderer.Text = $"Здоровье: {percentage:000}"; } diff --git a/DoomDeathmatch/src/Component/MVC/MovementController.cs b/DoomDeathmatch/src/Component/MVC/MovementController.cs index fbc34bd..a23498c 100644 --- a/DoomDeathmatch/src/Component/MVC/MovementController.cs +++ b/DoomDeathmatch/src/Component/MVC/MovementController.cs @@ -21,6 +21,6 @@ public class MovementController : Engine.Scene.Component.Component public void ApplyMovement(Vector3 parDirection) { - _rigidbody.AddForce(_dragComponent.Drag * Speed * parDirection.Normalized()); + _rigidbody.Force += _dragComponent.Drag * Speed * parDirection.Normalized(); } } \ No newline at end of file diff --git a/DoomDeathmatch/src/Component/MVC/PlayerController.cs b/DoomDeathmatch/src/Component/MVC/PlayerController.cs index eed9590..36c4736 100644 --- a/DoomDeathmatch/src/Component/MVC/PlayerController.cs +++ b/DoomDeathmatch/src/Component/MVC/PlayerController.cs @@ -12,71 +12,77 @@ namespace DoomDeathmatch.Component.MVC; public class PlayerController : Engine.Scene.Component.Component { public event Action? OnDeath; - public bool IsAlive => _healthController.IsAlive; - public HealthController HealthController => _healthController; - public WeaponController WeaponController => _weaponController; - public PerspectiveCamera Camera => _camera; + public bool IsAlive => HealthController.IsAlive; + public HealthController HealthController { get; private set; } = null!; + public WeaponController WeaponController { get; private set; } = null!; + public PerspectiveCamera Camera { get; } private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; - private HealthController _healthController = null!; - private WeaponController _weaponController = null!; - private readonly PerspectiveCamera _camera; - public PlayerController(PerspectiveCamera parCamera) { - _camera = parCamera; + Camera = parCamera; } public override void Awake() { - _healthController = GameObject.GetComponent()!; - _weaponController = GameObject.GetComponent()!; + HealthController = GameObject.GetComponent()!; + WeaponController = GameObject.GetComponent()!; - ArgumentNullException.ThrowIfNull(_healthController); - ArgumentNullException.ThrowIfNull(_weaponController); + ArgumentNullException.ThrowIfNull(HealthController); + ArgumentNullException.ThrowIfNull(WeaponController); - _healthController.OnDeath += () => OnDeath?.Invoke(); + HealthController.OnDeath += () => OnDeath?.Invoke(); } public override void Update(double parDeltaTime) { if (!IsAlive || parDeltaTime == 0) + { return; + } for (var i = 0; i < 10; i++) { if (KeyboardButtonCode.D1 + i > KeyboardButtonCode.D0) + { break; + } if (!_inputHandler.IsKeyJustPressed(KeyboardButtonCode.D1 + i)) + { continue; + } - _weaponController.SelectWeapon(i); + WeaponController.SelectWeapon(i); break; } if (_inputHandler.IsKeyJustPressed(KeyboardButtonCode.Space)) { - if (!_weaponController.TryShoot()) + if (!WeaponController.TryShoot()) + { return; + } - var position = _camera.GameObject.Transform.GetFullTranslation(); - var forward = (_camera.Forward - position).Normalized(); + var position = Camera.GameObject.Transform.GetFullTranslation(); + var forward = (Camera.Forward - position).Normalized(); var right = Vector3.Cross(forward, Vector3.UnitZ).Normalized(); var collisionManager = EngineUtil.SceneManager.CurrentScene!.FindFirstComponent(); - var offsets = _weaponController.WeaponData.ShootPattern.GetShootPattern(forward, Vector3.UnitZ, right); + var offsets = WeaponController.WeaponData.ShootPattern.GetShootPattern(forward, Vector3.UnitZ, right); foreach (var offset in offsets) { var direction = forward + offset; if (!collisionManager!.Raycast(position, direction, ["enemy", "wall"], out var result)) + { continue; + } var enemyController = result.HitObject.GetComponent(); - enemyController?.HealthController.TakeDamage(_weaponController.WeaponData.Damage); + enemyController?.HealthController.TakeDamage(WeaponController.WeaponData.Damage); } } } diff --git a/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs b/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs index 6c4ce5a..77b9b95 100644 --- a/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs +++ b/DoomDeathmatch/src/Component/MVC/Timer/TimerController.cs @@ -7,6 +7,7 @@ public class TimerController : Engine.Scene.Component.Component public event Action? OnFinished; private readonly TickableTimer _tickableTimer = new(60 + 10); + private TimerView _timerView = null!; public override void Awake() diff --git a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs index a2e9574..174f9ae 100644 --- a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs +++ b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponController.cs @@ -23,7 +23,9 @@ public class WeaponController : Engine.Scene.Component.Component public bool TryShoot() { if (_weaponModel.SelectedWeapon.Ammo <= 0) + { return false; + } _weaponModel.SelectedWeapon.Ammo--; @@ -41,7 +43,9 @@ public class WeaponController : Engine.Scene.Component.Component public void AddWeapon(WeaponData parWeaponData) { if (_weaponModel.Weapons.Contains(parWeaponData)) + { return; + } _weaponModel.Weapons.Add(parWeaponData); } @@ -49,15 +53,21 @@ public class WeaponController : Engine.Scene.Component.Component public void AddOrMergeWeapon(WeaponData parWeaponData) { if (!_weaponModel.Weapons.Contains(parWeaponData)) + { _weaponModel.Weapons.Add(parWeaponData); + } else + { _weaponModel.Weapons.First(parData => parData.Id == parWeaponData.Id).Ammo += parWeaponData.Ammo; + } } public void RemoveWeapon(int parIndex) { if (parIndex <= 0 || parIndex >= _weaponModel.Weapons.Count) + { return; + } var newSelectedIndex = parIndex >= _weaponModel.SelectedWeaponIndex ? _weaponModel.SelectedWeaponIndex : 0; @@ -68,20 +78,19 @@ public class WeaponController : Engine.Scene.Component.Component public void SelectWeapon(int parIndex) { if (parIndex >= _weaponModel.Weapons.Count) + { return; + } _weaponModel.SelectedWeaponIndex = parIndex; } - // public WeaponData? FindWeapon(string parId) - // { - // return _weaponModel.Weapons.FirstOrDefault(parData => parData.Id == parId); - // } - private void WeaponSelected(WeaponData? parOldWeapon, WeaponData parNewWeapon) { if (parOldWeapon != null) + { parOldWeapon.OnAmmoChanged -= _weaponView.UpdateAmmoView; + } parNewWeapon.OnAmmoChanged += _weaponView.UpdateAmmoView; _weaponView.UpdateView(parNewWeapon); diff --git a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs index 0d9c6d2..dd2c446 100644 --- a/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs +++ b/DoomDeathmatch/src/Component/MVC/Weapon/WeaponView.cs @@ -12,9 +12,10 @@ public class WeaponView : Engine.Scene.Component.Component private readonly TextRenderer _weaponAmmo; private readonly Box2DRenderer _weaponSprite; - private AnimationPlayer? _weaponFireAnimation; private Texture? _idleTexture; + private AnimationPlayer? _weaponFireAnimation; + public WeaponView(TextRenderer parWeaponName, TextRenderer parWeaponAmmo, Box2DRenderer parWeaponSprite) { _weaponName = parWeaponName; diff --git a/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs b/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs index e3ca97f..6e08e47 100644 --- a/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs +++ b/DoomDeathmatch/src/Component/Physics/Collision/ColliderForceFieldComponent.cs @@ -16,13 +16,17 @@ public class ColliderForceFieldComponent : Engine.Scene.Component.Component { var rigidbody = parCollider.GameObject.GetComponent(); if (rigidbody == null) + { return; + } var normal = _collider.Collider.GetCollisionNormal(parCollider.Collider); var speedAlongNormal = Vector3.Dot(rigidbody.Velocity, normal); if (speedAlongNormal > 0) + { return; + } - rigidbody.AddVelocity(-normal * (speedAlongNormal * 1.75f)); + rigidbody.Velocity -= normal * (speedAlongNormal * 1.75f); } } \ No newline at end of file diff --git a/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs b/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs index 55c6dbd..e82021e 100644 --- a/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs +++ b/DoomDeathmatch/src/Component/Physics/Collision/CollisionManagerComponent.cs @@ -30,16 +30,24 @@ public class CollisionManagerComponent : Engine.Scene.Component.Component !colliderA.ColliderGroups.Overlaps(colliderB.ExcludeColliderCollideGroups); if (!canCollideAB && !canCollideBA) + { continue; + } if (!colliderA.Collider.Intersects(colliderB.Collider)) + { continue; + } if (canCollideAB) + { colliderA.CollideWith(colliderB); + } if (canCollideBA) + { colliderB.CollideWith(colliderA); + } } } } @@ -56,14 +64,20 @@ public class CollisionManagerComponent : Engine.Scene.Component.Component foreach (var collider in _colliders) { if (!collider.ColliderGroups.Overlaps(parColliderGroups)) + { continue; + } if (!RaycastAABB(start, direction, collider.Collider, out var hitPoint, out var normal)) + { continue; + } var distance = (start - hitPoint).Length; if (distance > closestDistance) + { continue; + } closestDistance = distance; @@ -128,9 +142,13 @@ public class CollisionManagerComponent : Engine.Scene.Component.Component for (var i = 0; i < 3; i++) { if (quadrant[i] != MIDDLE && parDirection[i] != 0.0f) + { maxT[i] = (candidatePlane[i] - parOrigin[i]) / parDirection[i]; + } else + { maxT[i] = -1.0f; + } } // Get largest of the maxT's for final choice of intersection @@ -138,26 +156,32 @@ public class CollisionManagerComponent : Engine.Scene.Component.Component for (var i = 1; i < 3; i++) { if (maxT[whichPlane] < maxT[i]) + { whichPlane = i; + } } // Check final candidate actually inside box if (maxT[whichPlane] < 0.0f) + { return false; + } for (var i = 0; i < 3; i++) { if (whichPlane != i) { - parHitPoint[i] = parOrigin[i] + maxT[whichPlane] * parDirection[i]; + parHitPoint[i] = parOrigin[i] + (maxT[whichPlane] * parDirection[i]); if (parHitPoint[i] < minB[i] || parHitPoint[i] > maxB[i]) + { return false; + } } else { parHitPoint[i] = candidatePlane[i]; // Calculate normal for the intersection plane - parHitNormal[i] = (quadrant[i] == LEFT) ? -1.0f : 1.0f; + parHitNormal[i] = quadrant[i] == LEFT ? -1.0f : 1.0f; } } diff --git a/DoomDeathmatch/src/Component/Physics/DragComponent.cs b/DoomDeathmatch/src/Component/Physics/DragComponent.cs index 9b2889c..f9fa47b 100644 --- a/DoomDeathmatch/src/Component/Physics/DragComponent.cs +++ b/DoomDeathmatch/src/Component/Physics/DragComponent.cs @@ -18,6 +18,6 @@ public class DragComponent : Engine.Scene.Component.Component public override void Update(double parDeltaTime) { - _rigidbody.AddForce(-Drag * (_rigidbody.Velocity * Multiplier)); + _rigidbody.Force -= Drag * (_rigidbody.Velocity * Multiplier); } } \ No newline at end of file diff --git a/DoomDeathmatch/src/Component/Physics/GravityComponent.cs b/DoomDeathmatch/src/Component/Physics/GravityComponent.cs index 335197d..fa9d6d3 100644 --- a/DoomDeathmatch/src/Component/Physics/GravityComponent.cs +++ b/DoomDeathmatch/src/Component/Physics/GravityComponent.cs @@ -4,6 +4,8 @@ namespace DoomDeathmatch.Component.Physics; public class GravityComponent : Engine.Scene.Component.Component { + public bool IsInAir { get; private set; } + public float Strength { get; set; } = 10.0f; public Vector3 Direction @@ -14,7 +16,6 @@ public class GravityComponent : Engine.Scene.Component.Component public float Floor { get; set; } = 5.0f; - public bool IsInAir { get; private set; } = false; private RigidbodyComponent _rigidbody = null!; private Vector3 _direction = -Vector3.UnitZ; @@ -34,13 +35,15 @@ public class GravityComponent : Engine.Scene.Component.Component IsInAir = false; var velocityAlongDirection = Vector3.Dot(_rigidbody.Velocity, Direction); if (velocityAlongDirection > 0) - _rigidbody.AddVelocity(-velocityAlongDirection * Direction); + { + _rigidbody.Velocity -= velocityAlongDirection * Direction; + } return; } IsInAir = true; var gravity = Strength * Direction; - _rigidbody.AddForce(gravity); + _rigidbody.Force += gravity; } } \ No newline at end of file diff --git a/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs b/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs index 9a6730b..dcceded 100644 --- a/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs +++ b/DoomDeathmatch/src/Component/Physics/RigidbodyComponent.cs @@ -4,35 +4,50 @@ namespace DoomDeathmatch.Component.Physics; public class RigidbodyComponent : Engine.Scene.Component.Component { - public Vector3 Velocity { get; private set; } = Vector3.Zero; - public Vector3 Acceleration { get; private set; } = Vector3.Zero; - public Vector3 Force { get; private set; } = Vector3.Zero; public float Mass { get; set; } = 1.0f; public bool IsStatic { get; set; } = false; - public void AddForce(Vector3 parForce) + public Vector3 Force { - if (IsStatic) - return; + get => _force; + set + { + if (IsStatic) + { + return; + } - Force += parForce; + _force = value; + } } - public void AddVelocity(Vector3 parVelocity) + public Vector3 Velocity { - if (IsStatic) - return; + get => _velocity; + set + { + if (IsStatic) + { + return; + } - Velocity += parVelocity; + _velocity = value; + } } + private Vector3 _force = Vector3.Zero; + private Vector3 _velocity = Vector3.Zero; + private Vector3 _acceleration = Vector3.Zero; + public override void Update(double parDeltaTime) { if (IsStatic) + { return; + } - Acceleration = Force / Mass; - Velocity += Acceleration * (float)parDeltaTime; + _acceleration = Force / Mass; + Velocity += _acceleration * (float)parDeltaTime; GameObject.Transform.Translation += Velocity * (float)parDeltaTime; Force = Vector3.Zero; diff --git a/DoomDeathmatch/src/Component/UI/SelectorComponent.cs b/DoomDeathmatch/src/Component/UI/SelectorComponent.cs index b7c1f73..44614f0 100644 --- a/DoomDeathmatch/src/Component/UI/SelectorComponent.cs +++ b/DoomDeathmatch/src/Component/UI/SelectorComponent.cs @@ -5,18 +5,16 @@ namespace DoomDeathmatch.Component.UI; public class SelectorComponent : Engine.Scene.Component.Component { - public List Children => _children; - public KeyboardButtonCode SelectKey { get; set; } = KeyboardButtonCode.Space; + public event Action? OnSelect; + + public List Children { get; } = []; public KeyboardButtonCode NextKey { get; set; } = KeyboardButtonCode.Down; public KeyboardButtonCode PrevKey { get; set; } = KeyboardButtonCode.Up; - - public event Action? OnSelect; + public KeyboardButtonCode SelectKey { get; set; } = KeyboardButtonCode.Space; private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; - private readonly List _children = []; - - private int _selectedIndex = 0; + private int _selectedIndex; public override void Start() { @@ -31,13 +29,17 @@ public class SelectorComponent : Engine.Scene.Component.Component public override void Update(double parDeltaTime) { if (_inputHandler.IsKeyJustPressed(SelectKey)) - _children[_selectedIndex].InvokeClick(); + { + Children[_selectedIndex].InvokeClick(); + } if (_inputHandler.IsKeyJustPressed(NextKey)) { _selectedIndex++; if (_selectedIndex >= Children.Count) + { _selectedIndex = 0; + } SelectionChanged(); } @@ -46,7 +48,9 @@ public class SelectorComponent : Engine.Scene.Component.Component { _selectedIndex--; if (_selectedIndex < 0) + { _selectedIndex = Children.Count - 1; + } SelectionChanged(); } @@ -77,10 +81,14 @@ public class SelectorComponent : Engine.Scene.Component.Component { var index = Children.IndexOf(parComponent); if (index < 0) + { index = 0; + } if (index == _selectedIndex) + { return; + } _selectedIndex = index; diff --git a/DoomDeathmatch/src/Component/UI/StackComponent.cs b/DoomDeathmatch/src/Component/UI/StackComponent.cs index 7297e8e..29e92f8 100644 --- a/DoomDeathmatch/src/Component/UI/StackComponent.cs +++ b/DoomDeathmatch/src/Component/UI/StackComponent.cs @@ -5,25 +5,23 @@ namespace DoomDeathmatch.Component.UI; public class StackComponent : UiContainerComponent { - public List Children => _children; + public List Children { get; } = []; public Orientation Orientation { get; set; } = Orientation.Vertical; - private readonly List _children = []; - public override void Update(double parDeltaTime) { base.Update(parDeltaTime); var size = GameObject.Transform.Size.Xy; - var count = _children.Count; + var count = Children.Count; size *= Orientation == Orientation.Horizontal ? new Vector2(1, 0) : new Vector2(0, 1); - var offset = new Vector2(-size.X / 2 + size.X / count / 2, -size.Y / 2 + size.Y / count / 2); + var offset = new Vector2((-size.X / 2) + (size.X / count / 2), (-size.Y / 2) + (size.Y / count / 2)); for (var i = count - 1; i >= 0; i--) { - var child = _children[i]; + var child = Children[i]; child.Offset = offset; offset += size / count; diff --git a/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs b/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs index 29f39b4..4ef9b4a 100644 --- a/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs +++ b/DoomDeathmatch/src/Component/UI/TextAlignComponent.cs @@ -9,7 +9,6 @@ public class TextAlignComponent : Engine.Scene.Component.Component public Align Alignment { get; set; } = Align.Left; private TextRenderer _textRenderer = null!; - private string? _cachedText; public override void Awake() @@ -20,10 +19,14 @@ public class TextAlignComponent : Engine.Scene.Component.Component public override void Update(double parDeltaTime) { if (_textRenderer.Text == null) + { return; + } if (_cachedText == _textRenderer.Text) + { return; + } _cachedText = _textRenderer.Text; var font = _textRenderer.Font; diff --git a/DoomDeathmatch/src/Component/UI/TextInputComponent.cs b/DoomDeathmatch/src/Component/UI/TextInputComponent.cs index 44df59b..0984de6 100644 --- a/DoomDeathmatch/src/Component/UI/TextInputComponent.cs +++ b/DoomDeathmatch/src/Component/UI/TextInputComponent.cs @@ -12,40 +12,37 @@ public class TextInputComponent : Engine.Scene.Component.Component public float InputDelay { - get => _inputDelay; - set - { - _inputDelay = value; - _inputTimer.TotalTime = value; - } + get => (float)_inputTimer.TotalTime; + set => _inputTimer.TotalTime = value; } - private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; - private readonly KeyboardButtonCode[] _acceptedKeys = KeyboardButtonCodeHelper.GetAllPrintableKeys().Append(KeyboardButtonCode.Backspace).ToArray(); + private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; private readonly TickableTimer _inputTimer; - private float _inputDelay = 0; private readonly HashSet _lastKeys = []; public TextInputComponent(float parInputDelay = 0.2f) { - _inputDelay = parInputDelay; - _inputTimer = new TickableTimer(_inputDelay) { CurrentTime = 0 }; + _inputTimer = new TickableTimer(parInputDelay) { CurrentTime = 0 }; } public override void Update(double parDeltaTime) { if (!IsActive) + { return; + } _inputTimer.Update(parDeltaTime); foreach (var key in _acceptedKeys) { if (_lastKeys.Contains(key) && !_inputTimer.IsFinished) + { continue; + } if (_inputHandler.IsKeyPressed(key)) { @@ -69,7 +66,9 @@ public class TextInputComponent : Engine.Scene.Component.Component } if (invoke) + { OnInput?.Invoke(Input); + } _lastKeys.Add(key); diff --git a/DoomDeathmatch/src/Component/UI/UiComponent.cs b/DoomDeathmatch/src/Component/UI/UiComponent.cs index 562aff8..f349c8b 100644 --- a/DoomDeathmatch/src/Component/UI/UiComponent.cs +++ b/DoomDeathmatch/src/Component/UI/UiComponent.cs @@ -8,14 +8,14 @@ namespace DoomDeathmatch.Component.UI; public class UiComponent : Engine.Scene.Component.Component { - public UiContainerComponent? Container { get; set; } - public Anchor Anchor { get; set; } = Anchor.Center; - public Vector2 Offset { get; set; } = Vector2.Zero; - public Anchor Center { get; set; } = Anchor.Center; - public event Action? OnClick; public event Action? OnMouseOver; + public UiContainerComponent? Container { get; set; } + public Anchor Center { get; set; } = Anchor.Center; + public Anchor Anchor { get; set; } = Anchor.Center; + public Vector2 Offset { get; set; } = Vector2.Zero; + private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; public override void Update(double parDeltaTime) diff --git a/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs b/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs index ad9c6e3..31ba59d 100644 --- a/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs +++ b/DoomDeathmatch/src/Component/UI/UiContainerComponent.cs @@ -7,11 +7,11 @@ namespace DoomDeathmatch.Component.UI; public class UiContainerComponent : UiComponent { - private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; - public Camera? Camera { get; set; } public Vector3 MousePosition { get; private set; } + private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; + public override void Update(double parDeltaTime) { base.Update(parDeltaTime); diff --git a/DoomDeathmatch/src/Component/Util/BillboardComponent.cs b/DoomDeathmatch/src/Component/Util/BillboardComponent.cs index ec1e6d6..80e7108 100644 --- a/DoomDeathmatch/src/Component/Util/BillboardComponent.cs +++ b/DoomDeathmatch/src/Component/Util/BillboardComponent.cs @@ -21,11 +21,15 @@ public class BillboardComponent : Engine.Scene.Component.Component var forward = targetPosition - currentPosition; forward -= Vector3.Dot(forward, Up) * Up; if (forward.LengthSquared > 0) + { forward.Normalize(); + } var right = Vector3.Cross(Up, forward); if (right.LengthSquared > 0) + { right.Normalize(); + } var recalculatedUp = Vector3.Cross(forward, right).Normalized(); diff --git a/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs b/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs index 1d142b3..7313929 100644 --- a/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs +++ b/DoomDeathmatch/src/Component/Util/CopySizeComponent.cs @@ -5,21 +5,29 @@ namespace DoomDeathmatch.Component.Util; public class CopySizeComponent : Engine.Scene.Component.Component { - public Vector3 Multiplier { get; set; } = Vector3.One; public Transform? Target { get; set; } + public Vector3 Multiplier { get; set; } = Vector3.One; public override void Update(double parDeltaTime) { if (Target == null) + { return; + } if (Multiplier.X != 0) + { GameObject.Transform.Size.X = Target.Size.X * Multiplier.X; + } if (Multiplier.Y != 0) + { GameObject.Transform.Size.Y = Target.Size.Y * Multiplier.Y; + } if (Multiplier.Z != 0) + { GameObject.Transform.Size.Z = Target.Size.Z * Multiplier.Z; + } } } \ No newline at end of file diff --git a/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs b/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs index 8ac7ee6..77e2bdb 100644 --- a/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs +++ b/DoomDeathmatch/src/Component/Util/PlayerMovementComponent.cs @@ -10,6 +10,7 @@ public class PlayerMovementComponent : Engine.Scene.Component.Component public float RotationSpeed { get; set; } = 110.0f; private readonly IInputHandler _inputHandler = EngineUtil.InputHandler; + private MovementController _movementController = null!; public override void Awake() @@ -25,18 +26,34 @@ public class PlayerMovementComponent : Engine.Scene.Component.Component var rotation = 0.0f; if (_inputHandler.IsKeyPressed(KeyboardButtonCode.W)) + { movement.Y += 1; + } + if (_inputHandler.IsKeyPressed(KeyboardButtonCode.S)) + { movement.Y -= 1; + } + if (_inputHandler.IsKeyPressed(KeyboardButtonCode.D)) + { movement.X += 1; + } + if (_inputHandler.IsKeyPressed(KeyboardButtonCode.A)) + { movement.X -= 1; + } if (_inputHandler.IsKeyPressed(KeyboardButtonCode.Q)) + { rotation += RotationSpeed; + } + if (_inputHandler.IsKeyPressed(KeyboardButtonCode.E)) + { rotation -= RotationSpeed; + } if (movement.LengthSquared > 0) { diff --git a/DoomDeathmatch/src/Scene/GameOver/GameOverScene.cs b/DoomDeathmatch/src/Scene/GameOver/GameOverScene.cs index aba74d3..b1727be 100644 --- a/DoomDeathmatch/src/Scene/GameOver/GameOverScene.cs +++ b/DoomDeathmatch/src/Scene/GameOver/GameOverScene.cs @@ -41,7 +41,9 @@ public static class GameOverScene nextUi.OnClick += _ => { if (string.IsNullOrEmpty(nameInputComponent.Input)) + { return; + } SubmitScore(nameInputComponent.Input, parScore); EngineUtil.SceneManager.TransitionTo(MainScene.Create); diff --git a/DoomDeathmatch/src/Scene/Main/MainScene.cs b/DoomDeathmatch/src/Scene/Main/MainScene.cs index 503c751..17df75c 100644 --- a/DoomDeathmatch/src/Scene/Main/MainScene.cs +++ b/DoomDeathmatch/src/Scene/Main/MainScene.cs @@ -100,7 +100,7 @@ public static class MainScene backUi.OnClick += _ => parMenuController.SelectMenuItem("main"); var (stackObject, stack) = UiUtil.CreateStackUi(parScene, - new StackComponent { Offset = new Vector2(0, -1.5f), Container = parUiContainer, Children = { } }); + new StackComponent { Offset = new Vector2(0, -1.5f), Container = parUiContainer }); stackObject.Transform.Size.Xy = new Vector2(1f, 6f); var leadersTable = CreateLeadersTable(parScene, parUiContainer, EngineUtil.DataFolder); @@ -134,7 +134,9 @@ public static class MainScene { leadersTableList.Add(CreateLeadersRow(parScene, parUiContainer, row.Name, row.Score.ToString())); if (++rows >= 5) + { break; + } } return leadersTableList; diff --git a/DoomDeathmatch/src/Scene/Play/PlayScene.cs b/DoomDeathmatch/src/Scene/Play/PlayScene.cs index 508d3a0..e208c26 100644 --- a/DoomDeathmatch/src/Scene/Play/PlayScene.cs +++ b/DoomDeathmatch/src/Scene/Play/PlayScene.cs @@ -63,7 +63,7 @@ public static class PlayScene new ScoreController(), playScoreView, - new CollisionManagerComponent(), + new CollisionManagerComponent() ]); @@ -186,7 +186,7 @@ public static class PlayScene } var size = max - min; - var offset = min + size / 2; + var offset = min + (size / 2); var colliderObject = GameObjectUtil.CreateColliderForceField( parScene, diff --git a/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs b/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs index 5180163..b783ffb 100644 --- a/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs +++ b/DoomDeathmatch/src/Scene/Play/Prefab/EnemyPrefab.cs @@ -57,7 +57,7 @@ public static class EnemyPrefab var enemyVisualObject = GameObjectUtil.CreateGameObject(parScene, new Transform { Translation = new Vector3(0, 0f, 1f), Size = new Vector3(1, 2, 1) }, [ enemyBox2DRenderer, - new BillboardComponent(), + new BillboardComponent() ] ); @@ -72,7 +72,7 @@ public static class EnemyPrefab Vector3 parVelocity, float parDamage, Transform? parBillboardTarget = null) { var rigidbodyComponent = new RigidbodyComponent(); - rigidbodyComponent.AddVelocity(parVelocity); + rigidbodyComponent.Velocity += parVelocity; var fireballObject = GameObjectUtil.CreateGameObject(parScene, new Transform { Translation = parPosition, Size = new Vector3(0.5f) }, diff --git a/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs b/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs index e54b849..c47def2 100644 --- a/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs +++ b/DoomDeathmatch/src/Scene/Play/Prefab/PlayerPrefab.cs @@ -37,7 +37,7 @@ public static class PlayerPrefab parWeaponView, new HealthController(), - parHealthView, + parHealthView ]); parScene.AddChild(playerObject, perspectiveCameraObject); diff --git a/DoomDeathmatch/src/Script/AnimationPlayer.cs b/DoomDeathmatch/src/Script/AnimationPlayer.cs index 57896bf..754c62c 100644 --- a/DoomDeathmatch/src/Script/AnimationPlayer.cs +++ b/DoomDeathmatch/src/Script/AnimationPlayer.cs @@ -5,29 +5,25 @@ namespace DoomDeathmatch.Script; public class AnimationPlayer(float parInterval) : IUpdate { - public List Frames { get; init; } = []; - public bool IsPlaying { get; private set; } = false; - public int NextFrame { get; private set; } = 0; - - public event Action? OnFrameChanged; public event Action? OnFinish; + public event Action? OnFrameChanged; + + public bool IsPlaying { get; private set; } + public List Frames { get; init; } = []; + public int NextFrame { get; private set; } private readonly TickableTimer _timer = new(parInterval); - public void Start() - { - Reset(); - IsPlaying = true; - } - public void Update(double parDeltaTime) { if (!IsPlaying) + { return; + } _timer.Update(parDeltaTime); - if (_timer.CurrentTime < _timer.TotalTime * (1.0f - 1.0f / Frames.Count * NextFrame)) + if (_timer.CurrentTime < _timer.TotalTime * (1.0f - (1.0f / Frames.Count * NextFrame))) { OnFrameChanged?.Invoke(Frames[NextFrame]); NextFrame++; @@ -41,6 +37,12 @@ public class AnimationPlayer(float parInterval) : IUpdate } } + public void Start() + { + Reset(); + IsPlaying = true; + } + public void Reset() { _timer.Reset(); diff --git a/DoomDeathmatch/src/Script/Collision/AABBCollider.cs b/DoomDeathmatch/src/Script/Collision/AABBCollider.cs index 982fbe6..e72390c 100644 --- a/DoomDeathmatch/src/Script/Collision/AABBCollider.cs +++ b/DoomDeathmatch/src/Script/Collision/AABBCollider.cs @@ -4,11 +4,11 @@ namespace DoomDeathmatch.Script.Collision; public class AABBCollider { - public Vector3 Size { get; set; } public Vector3 Position { get; set; } + public Vector3 Size { get; set; } - public Vector3 Max => Position + Size / 2; - public Vector3 Min => Position - Size / 2; + public Vector3 Min => Position - (Size / 2); + public Vector3 Max => Position + (Size / 2); public bool Intersects(AABBCollider parCollider) { @@ -27,9 +27,9 @@ public class AABBCollider var diff = parOther.Position - Position; // Calculate penetration depths for each axis - var penX = (Size.X / 2 + parOther.Size.X / 2) - Math.Abs(diff.X); - var penY = (Size.Y / 2 + parOther.Size.Y / 2) - Math.Abs(diff.Y); - var penZ = (Size.Z / 2 + parOther.Size.Z / 2) - Math.Abs(diff.Z); + var penX = (Size.X / 2) + (parOther.Size.X / 2) - Math.Abs(diff.X); + var penY = (Size.Y / 2) + (parOther.Size.Y / 2) - Math.Abs(diff.Y); + var penZ = (Size.Z / 2) + (parOther.Size.Z / 2) - Math.Abs(diff.Z); // Use the axis with the smallest penetration if (penX < penY && penX < penZ) diff --git a/DoomDeathmatch/src/Script/Collision/RaycastResult.cs b/DoomDeathmatch/src/Script/Collision/RaycastResult.cs index 96bddc5..437d38f 100644 --- a/DoomDeathmatch/src/Script/Collision/RaycastResult.cs +++ b/DoomDeathmatch/src/Script/Collision/RaycastResult.cs @@ -8,5 +8,6 @@ public class RaycastResult public float Distance { get; init; } public Vector3 HitPoint { get; init; } public Vector3 Normal { get; init; } + public GameObject HitObject { get; init; } } \ No newline at end of file diff --git a/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs b/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs index ef085db..6ca051f 100644 --- a/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs +++ b/DoomDeathmatch/src/Script/Condition/TickableTimerCondition.cs @@ -5,6 +5,7 @@ namespace DoomDeathmatch.Script.Condition; public class TickableTimerCondition : ICondition { public event Action? OnTrue; + public bool IsTrue => _timer.IsFinished; private readonly TickableTimer _timer; diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs index 25afcb9..b803b09 100644 --- a/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs +++ b/DoomDeathmatch/src/Script/Model/Enemy/Attack/CooldownAttackBehavior.cs @@ -19,7 +19,9 @@ public abstract class CooldownAttackBehavior( if (CanAttack()) { if (!_tickableTimer.IsFinished) + { return false; + } var result = ActivateAttack(); diff --git a/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs b/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs index 94728a5..1f7bf55 100644 --- a/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs +++ b/DoomDeathmatch/src/Script/Model/Enemy/EnemyData.cs @@ -63,10 +63,13 @@ public class EnemyData public string Id { get; private init; } = ""; public string Name { get; private init; } = ""; + public string Texture { get; private init; } = ""; + public float BaseHealth { get; private init; } public int BaseScore { get; private init; } public float BaseSpeed { get; private init; } + public IMovementBehavior MovementBehavior { get; private init; } public IAttackBehaviorCreator AttackBehaviorCreator { get; private init; } diff --git a/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs b/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs index d2d9a7e..74bb2f2 100644 --- a/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs +++ b/DoomDeathmatch/src/Script/Model/Enemy/Movement/FollowPlayerMovementBehavior.cs @@ -7,6 +7,6 @@ public class FollowPlayerMovementBehavior(float parRadius) : IMovementBehavior public Vector3 GetNextPosition(Vector3 parPosition, Vector3 parPlayerPosition) { var direction = (parPosition - parPlayerPosition).Normalized(); - return parPlayerPosition + parRadius * direction; + return parPlayerPosition + (parRadius * direction); } } \ No newline at end of file diff --git a/DoomDeathmatch/src/Script/Model/HealthModel.cs b/DoomDeathmatch/src/Script/Model/HealthModel.cs index 13c48f5..6e64d4a 100644 --- a/DoomDeathmatch/src/Script/Model/HealthModel.cs +++ b/DoomDeathmatch/src/Script/Model/HealthModel.cs @@ -2,6 +2,24 @@ public class HealthModel { + public event Action? HealthChanged; + + public float Health + { + get => _health; + set + { + value = Math.Clamp(value, 0, MaxHealth); + if (Math.Abs(_health - value) < float.Epsilon) + { + return; + } + + _health = value; + HealthChanged?.Invoke(this); + } + } + public float MaxHealth { get => _maxHealth; @@ -13,22 +31,6 @@ public class HealthModel } } - public float Health - { - get => _health; - set - { - value = Math.Clamp(value, 0, MaxHealth); - if (Math.Abs(_health - value) < float.Epsilon) - return; - - _health = value; - HealthChanged?.Invoke(this); - } - } - - public event Action? HealthChanged; - private float _health; private float _maxHealth; diff --git a/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs b/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs index c8daff5..147ca26 100644 --- a/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs +++ b/DoomDeathmatch/src/Script/Model/Weapon/RandomFlatSpreadShootPattern.cs @@ -10,7 +10,7 @@ public class RandomFlatSpreadShootPattern(float parAngle, uint parCount) : IShoo { for (var i = 0; i < parCount; i++) { - var angle = parAngle * ((float)_random.NextDouble() * 2 - 1); + var angle = parAngle * (((float)_random.NextDouble() * 2) - 1); var delta = MathF.Tan(angle); var offset = parRight * delta; diff --git a/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs b/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs index bb73893..3137bbf 100644 --- a/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs +++ b/DoomDeathmatch/src/Script/Model/Weapon/WeaponData.cs @@ -13,7 +13,7 @@ public class WeaponData FireAnimationDuration = 0.25f, FireAnimation = { - "texture/pistol/fire1.png", "texture/pistol/fire2.png", "texture/pistol/fire3.png", "texture/pistol/fire4.png", + "texture/pistol/fire1.png", "texture/pistol/fire2.png", "texture/pistol/fire3.png", "texture/pistol/fire4.png" }, Damage = 30, ShootPattern = new LineShootPattern() @@ -31,14 +31,11 @@ public class WeaponData ShootPattern = new RandomFlatSpreadShootPattern(MathHelper.DegreesToRadians(10), 40) }; + public event Action? OnAmmoChanged; + + public string Id { get; private init; } = ""; public string Name { get; private init; } = ""; - public string IdleTexture { get; private init; } = ""; - public float FireAnimationDuration { get; private init; } = 0; - public List FireAnimation { get; private init; } = []; - public int Damage { get; private init; } - public int MaxAmmo { get; } - public IShootPattern ShootPattern { get; private init; } public int Ammo { @@ -46,19 +43,34 @@ public class WeaponData set { if (value < 0) + { value = 0; + } + if (value > MaxAmmo) + { value = MaxAmmo; + } if (_ammo == value) + { return; + } _ammo = value; OnAmmoChanged?.Invoke(this); } } - public event Action? OnAmmoChanged; + public int MaxAmmo { get; } + + public int Damage { get; private init; } + + public string IdleTexture { get; private init; } = ""; + public float FireAnimationDuration { get; private init; } + public List FireAnimation { get; } = []; + + public IShootPattern ShootPattern { get; private init; } private int _ammo; diff --git a/DoomDeathmatch/src/Script/Model/WeaponModel.cs b/DoomDeathmatch/src/Script/Model/WeaponModel.cs index fd9c4ed..f8917c1 100644 --- a/DoomDeathmatch/src/Script/Model/WeaponModel.cs +++ b/DoomDeathmatch/src/Script/Model/WeaponModel.cs @@ -7,7 +7,6 @@ public class WeaponModel public event Action? OnWeaponSelected; public IList Weapons => _weapons; - public WeaponData SelectedWeapon => _weapons[_selectedWeaponIndex]; public int SelectedWeaponIndex @@ -18,7 +17,9 @@ public class WeaponModel value = Math.Clamp(value, 0, _weapons.Count - 1); if (_selectedWeaponIndex == value) + { return; + } var oldSelectedWeapon = SelectedWeapon; _selectedWeaponIndex = value; @@ -27,5 +28,6 @@ public class WeaponModel } private readonly List _weapons = [WeaponData.Pistol]; - private int _selectedWeaponIndex = 0; + + private int _selectedWeaponIndex; } \ No newline at end of file diff --git a/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs b/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs index 9568264..baf56c4 100644 --- a/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs +++ b/DoomDeathmatch/src/Script/Provider/WeightedRandomValueProvider.cs @@ -4,7 +4,7 @@ public class WeightedRandomValueProvider : IValueProvider { private readonly List<(int, IValueProvider)> _providers = []; private readonly Random _random = new(); - private readonly int _totalWeight = 0; + private readonly int _totalWeight; public WeightedRandomValueProvider(IEnumerable<(int, IValueProvider)> parProviders) { @@ -15,7 +15,9 @@ public class WeightedRandomValueProvider : IValueProvider } if (_totalWeight <= 0) + { throw new InvalidOperationException($"{nameof(WeightedRandomValueProvider)} is empty"); + } } public T GetValue() @@ -25,7 +27,9 @@ public class WeightedRandomValueProvider : IValueProvider foreach (var (weight, provider) in _providers) { if (random < weight) + { return provider.GetValue(); + } random -= weight; } diff --git a/DoomDeathmatch/src/Script/Score/ScoreTable.cs b/DoomDeathmatch/src/Script/Score/ScoreTable.cs index f498fef..f09d0ce 100644 --- a/DoomDeathmatch/src/Script/Score/ScoreTable.cs +++ b/DoomDeathmatch/src/Script/Score/ScoreTable.cs @@ -7,10 +7,10 @@ namespace DoomDeathmatch.Script.Score; [JsonSerializable(typeof(ScoreTable))] public class ScoreTable { - private static readonly JsonSerializerOptions OPTIONS = new() { Converters = { new ScoreTableJsonConverter() } }; - public List Rows { get; } = new(); + private static readonly JsonSerializerOptions OPTIONS = new() { Converters = { new ScoreTableJsonConverter() } }; + public static ScoreTable LoadOrCreate(string parPath) { ScoreTable? table = null; @@ -26,10 +26,12 @@ public class ScoreTable } if (table != null) + { return table; + } table = new ScoreTable(); - ScoreTable.Save(table, parPath); + Save(table, parPath); return table; } @@ -51,7 +53,9 @@ public class ScoreTableJsonConverter : JsonConverter { var rows = JsonSerializer.Deserialize(ref parReader, parOptions); if (rows == null) + { return null; + } var scoreTable = new ScoreTable(); foreach (var row in rows) diff --git a/DoomDeathmatch/src/UiUtil.cs b/DoomDeathmatch/src/UiUtil.cs index 2cc989c..1a0dda2 100644 --- a/DoomDeathmatch/src/UiUtil.cs +++ b/DoomDeathmatch/src/UiUtil.cs @@ -138,7 +138,9 @@ public static class UiUtil StackComponent parStackComponent, RenderLayer? parRenderLayer = null) { foreach (var child in parStackComponent.Children) + { child.Container = parStackComponent; + } var stackObject = new GameObject { Transform = { Translation = new Vector3(0, 0, -1) } }; stackObject.AddComponent(parStackComponent); diff --git a/Engine/Engine.csproj b/Engine/Engine.csproj index 1160411..bbbded8 100644 --- a/Engine/Engine.csproj +++ b/Engine/Engine.csproj @@ -19,14 +19,14 @@ - + - + @@ -43,6 +43,7 @@ True ShaderResource.resx + diff --git a/Engine/src/Asset/Font/Font.cs b/Engine/src/Asset/Font/Font.cs index 443a31a..99c7d7f 100644 --- a/Engine/src/Asset/Font/Font.cs +++ b/Engine/src/Asset/Font/Font.cs @@ -6,24 +6,20 @@ namespace Engine.Asset.Font; public class Font { - public StaticTexture AtlasTexture => _atlasTexture; - public Metadata.Metadata Metadata => _metadata; - public Vector2 UnitRange => _unitRange; - - private readonly StaticTexture _atlasTexture; - private readonly Metadata.Metadata _metadata; + public StaticTexture AtlasTexture { get; } + public Metadata.Metadata Metadata { get; } + public Vector2 UnitRange { get; } private readonly Dictionary _glyphs = new(); private readonly Dictionary _glyphData = new(); private readonly Dictionary<(int, int), Kerning> _kernings = new(); - private readonly Vector2 _unitRange; public Font(StaticTexture parAtlasTexture, Metadata.Metadata parMetadata) { - _atlasTexture = parAtlasTexture; - _metadata = parMetadata; - _unitRange = new Vector2(_metadata.Atlas.DistanceRange / _metadata.Atlas.Width, - _metadata.Atlas.DistanceRange / _metadata.Atlas.Height); + AtlasTexture = parAtlasTexture; + Metadata = parMetadata; + UnitRange = new Vector2(Metadata.Atlas.DistanceRange / Metadata.Atlas.Width, + Metadata.Atlas.DistanceRange / Metadata.Atlas.Height); LoadGlyphs(); LoadKernings(); @@ -59,7 +55,7 @@ public class Font private void LoadGlyphs() { - foreach (var glyph in _metadata.Glyphs) + foreach (var glyph in Metadata.Glyphs) { _glyphs.Add(glyph.Unicode, glyph); @@ -68,13 +64,13 @@ public class Font continue; } - _glyphData.Add(glyph.Unicode, new GlyphData(_metadata, glyph)); + _glyphData.Add(glyph.Unicode, new GlyphData(Metadata, glyph)); } } private void LoadKernings() { - foreach (var kerning in _metadata.Kerning) + foreach (var kerning in Metadata.Kerning) { _kernings.Add((kerning.Unicode1, kerning.Unicode2), kerning); } @@ -93,7 +89,7 @@ public class Font new Vector2(parGlyph.PlaneBounds!.Left, parGlyph.PlaneBounds.Bottom), new Vector2(parGlyph.PlaneBounds.Left, parGlyph.PlaneBounds.Top), new Vector2(parGlyph.PlaneBounds.Right, parGlyph.PlaneBounds.Bottom), - new Vector2(parGlyph.PlaneBounds.Right, parGlyph.PlaneBounds.Top), + new Vector2(parGlyph.PlaneBounds.Right, parGlyph.PlaneBounds.Top) ]; UVs = @@ -101,8 +97,7 @@ public class Font new Vector2(parGlyph.AtlasBounds!.Left, parGlyph.AtlasBounds.Bottom) / size, new Vector2(parGlyph.AtlasBounds.Left, parGlyph.AtlasBounds.Top) / size, new Vector2(parGlyph.AtlasBounds.Right, parGlyph.AtlasBounds.Bottom) / size, - - new Vector2(parGlyph.AtlasBounds.Right, parGlyph.AtlasBounds.Top) / size, + new Vector2(parGlyph.AtlasBounds.Right, parGlyph.AtlasBounds.Top) / size ]; } } diff --git a/Engine/src/Asset/Font/FontIterator.cs b/Engine/src/Asset/Font/FontIterator.cs index 1f722d9..002eda6 100644 --- a/Engine/src/Asset/Font/FontIterator.cs +++ b/Engine/src/Asset/Font/FontIterator.cs @@ -5,8 +5,8 @@ namespace Engine.Asset.Font; public class FontIterator : IEnumerable { - public float MaxWidth => _maxWidth; - public float MaxHeight => _maxHeight; + public float MaxWidth { get; private set; } + public float MaxHeight { get; private set; } private readonly Font _font; private readonly string _text; @@ -17,44 +17,12 @@ public class FontIterator : IEnumerable private Vector2 _cursor = Vector2.Zero; private Vector2 _kerning = Vector2.Zero; - private float _maxWidth; - private float _maxHeight; - public FontIterator(Font parFont, string parText) { _font = parFont; _text = parText; } - private static bool IsLineBreak(int parCodepoint) - { - return parCodepoint == '\n'; - } - - private static bool IsTab(int parCodepoint) - { - return parCodepoint == '\t'; - } - - private void Tab() - { - var spaceGlyph = _font.GetGlyph(' '); - if (spaceGlyph == null) - return; - - var missingSpaces = 4 - _lineCharCount % 4; - _cursor.X += missingSpaces * spaceGlyph.Advance; - } - - private void LineBreak() - { - _kerning = Vector2.Zero; - _cursor.X = 0; - _cursor.Y += _font.Metadata.Metrics.LineHeight; - _lineCharCount = 0; - _previousCodepoint = -1; - } - public IEnumerator GetEnumerator() { while (_currentIndex < _text.Length) @@ -97,11 +65,13 @@ public class FontIterator : IEnumerable var glyphData = _font.GetGlyphData(glyph.Unicode); - _maxWidth = Math.Max(_maxWidth, _cursor.X + glyph.Advance); - _maxHeight = Math.Max(_maxHeight, _cursor.Y + _font.Metadata.Metrics.Ascender); + MaxWidth = Math.Max(MaxWidth, _cursor.X + glyph.Advance); + MaxHeight = Math.Max(MaxHeight, _cursor.Y + _font.Metadata.Metrics.Ascender); if (glyphData != null) + { yield return new NextGlyphData(glyphData.Positions, glyphData.UVs, (_cursor + _kerning) * new Vector2(1, -1)); + } _cursor.X += glyph.Advance; _lineCharCount++; @@ -115,5 +85,36 @@ public class FontIterator : IEnumerable return GetEnumerator(); } + private static bool IsLineBreak(int parCodepoint) + { + return parCodepoint == '\n'; + } + + private static bool IsTab(int parCodepoint) + { + return parCodepoint == '\t'; + } + + private void Tab() + { + var spaceGlyph = _font.GetGlyph(' '); + if (spaceGlyph == null) + { + return; + } + + var missingSpaces = 4 - (_lineCharCount % 4); + _cursor.X += missingSpaces * spaceGlyph.Advance; + } + + private void LineBreak() + { + _kerning = Vector2.Zero; + _cursor.X = 0; + _cursor.Y += _font.Metadata.Metrics.LineHeight; + _lineCharCount = 0; + _previousCodepoint = -1; + } + public record NextGlyphData(Vector2[] Positions, Vector2[] UVs, Vector2 Offset); } \ No newline at end of file diff --git a/Engine/src/Asset/Image.cs b/Engine/src/Asset/Image.cs index bdcf2d5..3678b8d 100644 --- a/Engine/src/Asset/Image.cs +++ b/Engine/src/Asset/Image.cs @@ -9,8 +9,6 @@ public class Image where T : struct, IPixel public int Height { get; } public T[,] Pixels { get; } - public T this[int parY, int parX] => Pixels[parY, parX]; - public Image(int parWidth, int parHeight) { Width = parWidth; @@ -18,6 +16,8 @@ public class Image where T : struct, IPixel Pixels = new T[parHeight, parWidth]; } + public T this[int parY, int parX] => Pixels[parY, parX]; + public DynamicTexture ToDynamicTexture() { var texture = DynamicTexture.Create(Width, Height); diff --git a/Engine/src/Asset/Mesh/Loader/ObjMeshLoader.cs b/Engine/src/Asset/Mesh/Loader/ObjMeshLoader.cs index 631aa97..727a98c 100644 --- a/Engine/src/Asset/Mesh/Loader/ObjMeshLoader.cs +++ b/Engine/src/Asset/Mesh/Loader/ObjMeshLoader.cs @@ -7,15 +7,15 @@ public class ObjMeshLoader : IMeshLoader { private static readonly ObjMeshLoader INSTANCE = new(); + private ObjMeshLoader() + { + } + public static Mesh Load(TextReader parReader, MeshLoaderParameters parParameters = MeshLoaderParameters.Default) { return INSTANCE.LoadMesh(parReader, parParameters); } - private ObjMeshLoader() - { - } - public Mesh LoadMesh(TextReader parReader, MeshLoaderParameters parParameters = MeshLoaderParameters.Default) { var mesh = new Mesh(); diff --git a/Engine/src/Asset/Mesh/Loader/StlMeshLoader.cs b/Engine/src/Asset/Mesh/Loader/StlMeshLoader.cs index 30c15fb..75683d7 100644 --- a/Engine/src/Asset/Mesh/Loader/StlMeshLoader.cs +++ b/Engine/src/Asset/Mesh/Loader/StlMeshLoader.cs @@ -7,15 +7,15 @@ public class StlMeshLoader : IMeshLoader { private static readonly StlMeshLoader INSTANCE = new(); + private StlMeshLoader() + { + } + public static Mesh Load(TextReader parReader, MeshLoaderParameters parParameters = MeshLoaderParameters.Default) { return INSTANCE.LoadMesh(parReader, parParameters); } - private StlMeshLoader() - { - } - public Mesh LoadMesh(TextReader parReader, MeshLoaderParameters parParameters = MeshLoaderParameters.Default) { var mesh = new Mesh(); diff --git a/Engine/src/Asset/Mesh/Mesh.cs b/Engine/src/Asset/Mesh/Mesh.cs index aa02542..de994b3 100644 --- a/Engine/src/Asset/Mesh/Mesh.cs +++ b/Engine/src/Asset/Mesh/Mesh.cs @@ -6,14 +6,14 @@ namespace Engine.Asset.Mesh; public class Mesh { - public IReadOnlyList Vertices => _vertices; public IReadOnlyList Indices => _indices; + public IReadOnlyList Vertices => _vertices; - internal IList VerticesInternal => _vertices; internal IList IndicesInternal => _indices; + internal IList VerticesInternal => _vertices; - private readonly List _vertices = []; private readonly List _indices = []; + private readonly List _vertices = []; public override int GetHashCode() { @@ -23,9 +23,7 @@ public class Mesh public record struct Vertex : IVertex { [Vertex(VertexAttribType.Float, 3)] public Vector3 _position; - [Vertex(VertexAttribType.Float, 3)] public Vector3 _normal; - [Vertex(VertexAttribType.Float, 2)] public Vector2 _uv; } } \ No newline at end of file diff --git a/Engine/src/Engine.cs b/Engine/src/Engine.cs index 5ce27c7..3f1a289 100644 --- a/Engine/src/Engine.cs +++ b/Engine/src/Engine.cs @@ -22,12 +22,14 @@ namespace Engine; public sealed class Engine { - internal static Engine Instance { get; private set; } = null!; - - public Renderer Renderer { get; } + public IInputHandler? InputHandler { get; internal set; } public SceneManager SceneManager { get; } = new(); + public IResourceManager AssetResourceManager { get; } + public string DataFolder { get; } - internal Window Window { get; } + internal static Engine Instance { get; private set; } = null!; + internal ResourceManager EngineResourceManager { get; } + internal Renderer Renderer { get; } internal IPresenter? Presenter { @@ -48,25 +50,12 @@ public sealed class Engine } } - public IInputHandler? InputHandler - { - get => _inputHandler; - internal set => _inputHandler = value; - } + internal Window Window { get; } private readonly ILogger _logger; + private readonly object _sceneLock = new(); - private IInputHandler? _inputHandler; private IPresenter? _presenter; - - internal ResourceManager EngineResourceManager => _engineResourceManager; - public IResourceManager AssetResourceManager => _assetResourceManager; - - public string DataFolder { get; } - - private readonly ResourceManager _engineResourceManager; - private readonly ResourceManager _assetResourceManager; - private Thread? _updateThread; public Engine(int parWidth, int parHeight, bool parHeadless, string parTitle, string parAssetFolder, @@ -94,8 +83,8 @@ public sealed class Engine StencilBits = 0 }; - _engineResourceManager = CreateEngineResourceManager(); - _assetResourceManager = CreateAssetResourceManager(parAssetFolder); + EngineResourceManager = CreateEngineResourceManager(); + AssetResourceManager = CreateAssetResourceManager(parAssetFolder); _logger.Information("Created asset resource manager in {AssetFolder}", parAssetFolder); @@ -139,8 +128,6 @@ public sealed class Engine parResourceManager.RegisterLoader(new FontLoader()); } - private readonly object _sceneLock = new(); - public void Run() { _updateThread = new Thread(RunUpdate) { Name = "UpdateThread" }; @@ -227,7 +214,9 @@ public sealed class Engine private void PresenterResize(ResizeEventArgs parEventArgs) { if (parEventArgs.Width == 0 || parEventArgs.Height == 0) + { return; + } Renderer.Resize(parEventArgs.Width, parEventArgs.Height); } diff --git a/Engine/src/EngineBuilder.cs b/Engine/src/EngineBuilder.cs index 54081b2..9661744 100644 --- a/Engine/src/EngineBuilder.cs +++ b/Engine/src/EngineBuilder.cs @@ -16,8 +16,8 @@ public sealed class EngineBuilder private string _assetFolder = "./asset"; private string _dataFolder = "./data"; - private Func? _presenterFunc; private Func? _inputHandlerFunc; + private Func? _presenterFunc; // Logging private bool _logToConsole; @@ -65,24 +65,18 @@ public sealed class EngineBuilder return this; } - public EngineBuilder Presenter(Func parPresenterFunc) - { - _presenterFunc = parPresenterFunc; - return this; - } - - public EngineBuilder InputHandler(IInputHandler parInputHandler) - { - _inputHandlerFunc = _ => parInputHandler; - return this; - } - public EngineBuilder InputHandler(Func parInputHandlerFunc) { _inputHandlerFunc = parInputHandlerFunc; return this; } + public EngineBuilder Presenter(Func parPresenterFunc) + { + _presenterFunc = parPresenterFunc; + return this; + } + public EngineBuilder LogToConsole(bool parLogToConsole = true) { _logToConsole = parLogToConsole; @@ -92,7 +86,9 @@ public sealed class EngineBuilder public EngineBuilder LogToFile(bool parLogToFile = true, string? parLogFilePath = null) { if (parLogToFile && parLogFilePath == null) + { throw new ArgumentNullException(nameof(parLogFilePath)); + } _logToFile = parLogToFile; _logFilePath = parLogFilePath; diff --git a/Engine/src/Graphics/Buffer/VertexArray.cs b/Engine/src/Graphics/Buffer/VertexArray.cs index bc96033..37aa18a 100644 --- a/Engine/src/Graphics/Buffer/VertexArray.cs +++ b/Engine/src/Graphics/Buffer/VertexArray.cs @@ -8,7 +8,7 @@ namespace Engine.Graphics.Buffer; public class VertexArray : OpenGlObject { - private int _enabledAttribs = 0; + private int _enabledAttributes; public VertexArray() { @@ -41,9 +41,9 @@ public class VertexArray : OpenGlObject var attribute = field.GetCustomAttribute()!; var offset = Marshal.OffsetOf(field.Name).ToInt32(); - SetupAttribute(attribute, _enabledAttribs, offset, parBindingIndex); + SetupAttribute(attribute, _enabledAttributes, offset, parBindingIndex); - _enabledAttribs += attribute.RepeatCount; + _enabledAttributes += attribute.RepeatCount; } GL.VertexArrayBindingDivisor(Handle, parBindingIndex, parDivisor); diff --git a/Engine/src/Graphics/Debug.cs b/Engine/src/Graphics/Debug.cs index 571f513..4fd7957 100644 --- a/Engine/src/Graphics/Debug.cs +++ b/Engine/src/Graphics/Debug.cs @@ -1,8 +1,8 @@ using System.Runtime.InteropServices; +using Evergine.Bindings.RenderDoc; using OpenTK.Graphics.OpenGL; using Serilog; using Serilog.Events; -using Evergine.Bindings.RenderDoc; namespace Engine.Graphics; diff --git a/Engine/src/Graphics/Framebuffer/Framebuffer.cs b/Engine/src/Graphics/Framebuffer/Framebuffer.cs index e89804a..be9563f 100644 --- a/Engine/src/Graphics/Framebuffer/Framebuffer.cs +++ b/Engine/src/Graphics/Framebuffer/Framebuffer.cs @@ -32,6 +32,7 @@ public class Framebuffer : OpenGlObject internal Texture.Texture? TextureInternal => GetAttachment(FramebufferAttachment.ColorAttachment0); private readonly IDictionary _attachments; + private int _width; private int _height; diff --git a/Engine/src/Graphics/GenericRenderer.cs b/Engine/src/Graphics/GenericRenderer.cs index 3e31621..8cdf3a2 100644 --- a/Engine/src/Graphics/GenericRenderer.cs +++ b/Engine/src/Graphics/GenericRenderer.cs @@ -13,13 +13,13 @@ public class GenericRenderer : IRenderer public AnyMeshRenderer AnyMeshRenderer => _anyMeshRenderer ??= new AnyMeshRenderer(_engine, 1024); public TextRenderer TextRenderer => _textRenderer ??= new TextRenderer(_engine, 1024 * 8); + internal readonly Framebuffer.Framebuffer _framebuffer; + + private readonly Engine _engine; + private QuadRenderer? _quadRenderer; private AnyMeshRenderer? _anyMeshRenderer; private TextRenderer? _textRenderer; - - private readonly Engine _engine; - internal readonly Framebuffer.Framebuffer _framebuffer; - private bool _frameStarted; public GenericRenderer(Engine parEngine, int parWidth, int parHeight) @@ -40,7 +40,9 @@ public class GenericRenderer : IRenderer public void EndFrame(in Matrix4 parProjectionMatrix, in Matrix4 parViewMatrix) { if (!_frameStarted) + { throw new InvalidOperationException("Frame not started"); + } _framebuffer.Bind(); diff --git a/Engine/src/Graphics/IPresenter.cs b/Engine/src/Graphics/IPresenter.cs index 52c7673..30e9a53 100644 --- a/Engine/src/Graphics/IPresenter.cs +++ b/Engine/src/Graphics/IPresenter.cs @@ -6,12 +6,12 @@ namespace Engine.Graphics; public interface IPresenter : IUpdate, IRender { - bool IsExiting { get; } - int Width { get; } - int Height { get; } + public event Action Resize; - event Action Resize; + public int Width { get; } + public int Height { get; } + public bool IsExiting { get; } - void Present(IConstTexture parTexture); - void Exit(); + public void Present(IConstTexture parTexture); + public void Exit(); } \ No newline at end of file diff --git a/Engine/src/Graphics/Pipeline/RenderLayer.cs b/Engine/src/Graphics/Pipeline/RenderLayer.cs index e8c2a3d..d70df6f 100644 --- a/Engine/src/Graphics/Pipeline/RenderLayer.cs +++ b/Engine/src/Graphics/Pipeline/RenderLayer.cs @@ -5,10 +5,10 @@ public class RenderLayer : IComparable public static readonly RenderLayer DEFAULT = new("default", 0); public static readonly RenderLayer OVERLAY = new("overlay", 1); public static readonly RenderLayer HUD = new("hud", 2); - public static readonly IReadOnlyList ALL = new List { DEFAULT, OVERLAY, HUD }.AsReadOnly(); public string Name { get; } + private readonly int _order; private RenderLayer(string parName, int parOrder) @@ -17,16 +17,16 @@ public class RenderLayer : IComparable _order = parOrder; } - public override string ToString() - { - return Name; - } - public int CompareTo(RenderLayer? parOther) { return parOther == null ? 1 : _order.CompareTo(parOther._order); } + public override string ToString() + { + return Name; + } + public override int GetHashCode() { return Name.GetHashCode(); diff --git a/Engine/src/Graphics/Pipeline/RenderPipeline.cs b/Engine/src/Graphics/Pipeline/RenderPipeline.cs deleted file mode 100644 index 0cf7f2c..0000000 --- a/Engine/src/Graphics/Pipeline/RenderPipeline.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Engine.Graphics.Pipeline; - -public class RenderPipeline -{ - -} \ No newline at end of file diff --git a/Engine/src/Graphics/Render/InstancedRenderer.cs b/Engine/src/Graphics/Render/InstancedRenderer.cs index ab6e888..c03e729 100644 --- a/Engine/src/Graphics/Render/InstancedRenderer.cs +++ b/Engine/src/Graphics/Render/InstancedRenderer.cs @@ -10,18 +10,18 @@ public abstract class InstancedRenderer where C : struct, IVertex where I : struct, IVertex { + protected readonly int _instanceCount; + protected readonly I[] _instanceVertices; + + protected int _queuedInstanceCount; + + private readonly PrimitiveType _primitiveType; + private readonly Program _program; private readonly IndexBuffer _indexBuffer; private readonly VertexBuffer _commonVertexBuffer; private readonly VertexBuffer _instanceVertexBuffer; private readonly VertexArray _vertexArray; - protected readonly int _instanceCount; - protected int _queuedInstanceCount; - protected readonly I[] _instanceVertices; - - private readonly PrimitiveType _primitiveType; - private readonly Program _program; - protected InstancedRenderer(PrimitiveType parPrimitiveType, int parInstanceCount, uint[] parIndexBuffer, C[] parInstanceBuffer, Program parProgram) @@ -39,7 +39,7 @@ public abstract class InstancedRenderer _vertexArray = new VertexArray(); _vertexArray.BindIndexBuffer(_indexBuffer); - _vertexArray.BindVertexBuffer(_commonVertexBuffer, 0, 0); + _vertexArray.BindVertexBuffer(_commonVertexBuffer); _vertexArray.BindVertexBuffer(_instanceVertexBuffer, 1, 1); } @@ -51,7 +51,10 @@ public abstract class InstancedRenderer } if (DataChanged()) + { _instanceVertexBuffer.UploadData(_instanceVertices, _queuedInstanceCount); + } + _vertexArray.Bind(); _program.Bind(); diff --git a/Engine/src/Graphics/Render/Mesh/AnyMeshRenderer.cs b/Engine/src/Graphics/Render/Mesh/AnyMeshRenderer.cs index 39e04a4..08075d7 100644 --- a/Engine/src/Graphics/Render/Mesh/AnyMeshRenderer.cs +++ b/Engine/src/Graphics/Render/Mesh/AnyMeshRenderer.cs @@ -46,7 +46,9 @@ public class AnyMeshRenderer(Engine parEngine, int parMaxInstanceCount) foreach (var mesh in meshes) { if (!_frameMeshes.Contains(mesh)) + { _meshRenderers.Remove(mesh); + } } _frameMeshes.Clear(); diff --git a/Engine/src/Graphics/Render/Quad/QuadRenderer.cs b/Engine/src/Graphics/Render/Quad/QuadRenderer.cs index 8ec0138..f646bad 100644 --- a/Engine/src/Graphics/Render/Quad/QuadRenderer.cs +++ b/Engine/src/Graphics/Render/Quad/QuadRenderer.cs @@ -8,7 +8,6 @@ namespace Engine.Graphics.Render.Quad; public class QuadRenderer : InstancedRenderer { private readonly TextureUnitMap _textureUnitMap = new(16); - private readonly int[] _textureUnitIndices = new int[16]; private int _frameHash; @@ -19,7 +18,7 @@ public class QuadRenderer : InstancedRenderer("shader/quad")) { diff --git a/Engine/src/Graphics/Render/Text/TextRenderer.cs b/Engine/src/Graphics/Render/Text/TextRenderer.cs index 6621e22..c5c538d 100644 --- a/Engine/src/Graphics/Render/Text/TextRenderer.cs +++ b/Engine/src/Graphics/Render/Text/TextRenderer.cs @@ -9,41 +9,34 @@ namespace Engine.Graphics.Render.Text; public class TextRenderer { + private readonly Program _program; private readonly IndexBuffer _indexBuffer; + private readonly VertexBuffer _glyphVertexBuffer; private readonly VertexArray _vertexArray; - private readonly VertexBuffer _glyphVertexBuffer; - // private readonly VertexBuffer _glyphCommonVertexBuffer; - - private readonly Program _program; private readonly int _characterCount; - private int _queuedCharacterCount; + private readonly GlyphVertex[] _glyphVertices; private readonly TextureUnitMap _textureUnitMap = new(16); private readonly int[] _textureUnitIndices = new int[16]; - private readonly GlyphVertex[] _glyphVertices; - // private readonly GlyphCommonVertex[] _glyphCommonVertices; + private int _queuedCharacterCount; public TextRenderer(Engine parEngine, int parCharacterCount) { _characterCount = parCharacterCount; _glyphVertices = new GlyphVertex[parCharacterCount * 4]; - // _glyphCommonVertices = new GlyphCommonVertex[parCharacterCount]; _program = parEngine.EngineResourceManager.Load("shader/text"); _indexBuffer = new IndexBuffer(CreateIndices(_characterCount)); _glyphVertexBuffer = new VertexBuffer(_characterCount * 4, BufferStorageFlags.DynamicStorageBit); - // _glyphCommonVertexBuffer = new VertexBuffer(_characterCount, - // BufferStorageFlags.DynamicStorageBit); _vertexArray = new VertexArray(); _vertexArray.BindIndexBuffer(_indexBuffer); - _vertexArray.BindVertexBuffer(_glyphVertexBuffer, 0, 0); - // _vertexArray.BindVertexBuffer(_glyphCommonVertexBuffer, 1, 1); + _vertexArray.BindVertexBuffer(_glyphVertexBuffer); } public void Commit(Font parFont, string parText, Vector4 parColor, in Matrix4 parModelMatrix) @@ -61,12 +54,12 @@ public class TextRenderer { for (var i = 0; i < 4; i++) { - _glyphVertices[_queuedCharacterCount * 4 + i]._position = glyphData.Positions[i] + glyphData.Offset; - _glyphVertices[_queuedCharacterCount * 4 + i]._uv = glyphData.UVs[i]; - _glyphVertices[_queuedCharacterCount * 4 + i]._color = parColor; - _glyphVertices[_queuedCharacterCount * 4 + i]._atlasId = textureId; - _glyphVertices[_queuedCharacterCount * 4 + i]._unitRange = parFont.UnitRange; - _glyphVertices[_queuedCharacterCount * 4 + i]._modelMatrix = parModelMatrix; + _glyphVertices[(_queuedCharacterCount * 4) + i]._position = glyphData.Positions[i] + glyphData.Offset; + _glyphVertices[(_queuedCharacterCount * 4) + i]._uv = glyphData.UVs[i]; + _glyphVertices[(_queuedCharacterCount * 4) + i]._color = parColor; + _glyphVertices[(_queuedCharacterCount * 4) + i]._atlasId = textureId; + _glyphVertices[(_queuedCharacterCount * 4) + i]._unitRange = parFont.UnitRange; + _glyphVertices[(_queuedCharacterCount * 4) + i]._modelMatrix = parModelMatrix; } _queuedCharacterCount++; @@ -81,7 +74,6 @@ public class TextRenderer } _glyphVertexBuffer.UploadData(_glyphVertices, _queuedCharacterCount * 4); - // _glyphCommonVertexBuffer.UploadData(_glyphCommonVertices, _queuedCharacterCount); _vertexArray.Bind(); _program.Bind(); diff --git a/Engine/src/Graphics/Renderer.cs b/Engine/src/Graphics/Renderer.cs index a0b6819..d7eb4d2 100644 --- a/Engine/src/Graphics/Renderer.cs +++ b/Engine/src/Graphics/Renderer.cs @@ -9,31 +9,18 @@ namespace Engine.Graphics; public class Renderer { - internal Framebuffer.Framebuffer RenderFramebuffer => _framebuffer; - internal Texture.Texture RenderTexture => _framebuffer.TextureInternal!; - - private QuadRenderer QuadRenderer { get; } - public int ViewportWidth => _framebuffer.Width; - public int ViewportHeight => _framebuffer.Height; - - private readonly SortedDictionary _renderers = new(); - - public GenericRenderer this[RenderLayer parRenderLayer] - { - get - { - if (_renderers.TryGetValue(parRenderLayer, out var renderer)) - return renderer; - - throw new InvalidOperationException($"Renderer for layer {parRenderLayer} not found"); - } - } + public int ViewportWidth => RenderFramebuffer.Width; + public int ViewportHeight => RenderFramebuffer.Height; + internal Framebuffer.Framebuffer RenderFramebuffer { get; } + internal Texture.Texture RenderTexture => RenderFramebuffer.TextureInternal!; internal NativeWindow NativeWindow { get; } - private readonly Framebuffer.Framebuffer _framebuffer; + private readonly SortedDictionary _renderers = new(); private readonly Thread _renderThread; + private QuadRenderer QuadRenderer { get; } + private readonly Queue _scheduleActions = new(); public Renderer(Engine parEngine, int parWidth, int parHeight, NativeWindowSettings parSettings) @@ -49,7 +36,7 @@ public class Renderer InitializeOpenGl(parWidth, parHeight); - _framebuffer = Framebuffer.Framebuffer.Builder(parWidth, parHeight) + RenderFramebuffer = Framebuffer.Framebuffer.Builder(parWidth, parHeight) .AddColorAttachment() .Build(); @@ -61,6 +48,19 @@ public class Renderer } } + public GenericRenderer this[RenderLayer parRenderLayer] + { + get + { + if (_renderers.TryGetValue(parRenderLayer, out var renderer)) + { + return renderer; + } + + throw new InvalidOperationException($"Renderer for layer {parRenderLayer} not found"); + } + } + private void InitializeOpenGl(int parWidth, int parHeight) { #if DEBUG @@ -129,15 +129,16 @@ public class Renderer foreach (var (renderLayer, renderer) in _renderers) { if (!parMatrices.TryGetValue(renderLayer, out var matrices)) + { renderer.EndFrame(Matrix4.Identity, Matrix4.Identity); + } else + { renderer.EndFrame(in matrices.Item1, in matrices.Item2); + } } - _framebuffer.Bind(); - - // GL.Disable(EnableCap.DepthTest); - // GL.Disable(EnableCap.CullFace); + RenderFramebuffer.Bind(); GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit); @@ -145,22 +146,21 @@ public class Renderer foreach (var (renderLayer, renderer) in _renderers) { if (!parMatrices.ContainsKey(renderLayer)) + { continue; + } QuadRenderer.Commit(Matrix4.CreateScale(2f, -2f, 1f), Vector4.One, renderer._framebuffer.TextureInternal); QuadRenderer.Render(Matrix4.Identity, Matrix4.Identity); QuadRenderer.Reset(); } - // GL.Enable(EnableCap.DepthTest); - // GL.Enable(EnableCap.CullFace); - - _framebuffer.Unbind(); + RenderFramebuffer.Unbind(); } internal void Resize(int parWidth, int parHeight) { - _framebuffer.Resize(parWidth, parHeight); + RenderFramebuffer.Resize(parWidth, parHeight); GL.Viewport(0, 0, parWidth, parHeight); foreach (var renderer in _renderers.Values) diff --git a/Engine/src/Graphics/Texture/IConstTexture.cs b/Engine/src/Graphics/Texture/IConstTexture.cs index 0317b91..cef2575 100644 --- a/Engine/src/Graphics/Texture/IConstTexture.cs +++ b/Engine/src/Graphics/Texture/IConstTexture.cs @@ -1,12 +1,10 @@ using Engine.Asset; using Engine.Graphics.Pixel; -using OpenTK.Mathematics; namespace Engine.Graphics.Texture; public interface IConstTexture { - public Vector2i Size { get; } public int Width { get; } public int Height { get; } diff --git a/Engine/src/Graphics/Texture/Texture.cs b/Engine/src/Graphics/Texture/Texture.cs index 354c2b6..9599f4e 100644 --- a/Engine/src/Graphics/Texture/Texture.cs +++ b/Engine/src/Graphics/Texture/Texture.cs @@ -1,15 +1,12 @@ using System.Runtime.InteropServices; using Engine.Graphics.Pixel; using OpenTK.Graphics.OpenGL; -using OpenTK.Mathematics; using Serilog; namespace Engine.Graphics.Texture; public abstract class Texture : OpenGlObject, ITexture { - public Vector2i Size => new(Width, Height); - public int Width { get => _width; diff --git a/Engine/src/Input/KeyboardButtonCode.cs b/Engine/src/Input/KeyboardButtonCode.cs index 2823b5d..a15a2e3 100644 --- a/Engine/src/Input/KeyboardButtonCode.cs +++ b/Engine/src/Input/KeyboardButtonCode.cs @@ -66,12 +66,16 @@ public enum KeyboardButtonCode public static class KeyboardButtonCodeHelper { - public static List GetAllPrintableKeys() => - Enum.GetValues().Where(parX => parX.IsPrintableKey()).ToList(); + public static List GetAllPrintableKeys() + { + return Enum.GetValues().Where(parX => parX.IsPrintableKey()).ToList(); + } - public static bool IsPrintableKey(this KeyboardButtonCode parKey) => - parKey is >= KeyboardButtonCode.A and <= KeyboardButtonCode.Z + public static bool IsPrintableKey(this KeyboardButtonCode parKey) + { + return parKey is >= KeyboardButtonCode.A and <= KeyboardButtonCode.Z or >= KeyboardButtonCode.D1 and <= KeyboardButtonCode.D0 or KeyboardButtonCode.Space; + } public static char GetChar(this KeyboardButtonCode parKey) { diff --git a/Engine/src/Input/WindowInputHandler.cs b/Engine/src/Input/WindowInputHandler.cs index 7f0d737..8a50f08 100644 --- a/Engine/src/Input/WindowInputHandler.cs +++ b/Engine/src/Input/WindowInputHandler.cs @@ -9,11 +9,10 @@ public class WindowInputHandler(Window parWindow) : IInputHandler public CultureInfo CurrentInputLanguage => new(1033); public Vector2 MousePosition => parWindow.NativeWindow.MouseState.Position; - private KeyboardState _previousKeyboardState = parWindow.NativeWindow.KeyboardState.GetSnapshot(); private KeyboardState _keyboardState = parWindow.NativeWindow.KeyboardState.GetSnapshot(); - - private MouseState _previousMouseState = parWindow.NativeWindow.MouseState.GetSnapshot(); + private KeyboardState _previousKeyboardState = parWindow.NativeWindow.KeyboardState.GetSnapshot(); private MouseState _mouseState = parWindow.NativeWindow.MouseState.GetSnapshot(); + private MouseState _previousMouseState = parWindow.NativeWindow.MouseState.GetSnapshot(); public void Update(double parDeltaTime) { diff --git a/Engine/src/Resource/Loader/ImageLoader.cs b/Engine/src/Resource/Loader/ImageLoader.cs index 068a6d1..6d204f9 100644 --- a/Engine/src/Resource/Loader/ImageLoader.cs +++ b/Engine/src/Resource/Loader/ImageLoader.cs @@ -1,5 +1,6 @@ using System.Runtime.InteropServices; using Engine.Graphics.Pixel; +using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; @@ -15,10 +16,10 @@ public class ImageLoader : IResourceLoader internal static Asset.Image Load(Stream parStream) { - var sharpImage = SixLabors.ImageSharp.Image.Load(parStream); + var sharpImage = Image.Load(parStream); if (sharpImage == null) { - throw new InvalidOperationException($"Failed to load image from stream"); + throw new InvalidOperationException("Failed to load image from stream"); } sharpImage.Mutate(parImageContext => parImageContext.Flip(FlipMode.Vertical)); diff --git a/Engine/src/Resource/Loader/ProgramLoader.cs b/Engine/src/Resource/Loader/ProgramLoader.cs index b382afc..d216546 100644 --- a/Engine/src/Resource/Loader/ProgramLoader.cs +++ b/Engine/src/Resource/Loader/ProgramLoader.cs @@ -6,9 +6,6 @@ namespace Engine.Resource.Loader; public partial class ProgramLoader : IResourceLoader { - [GeneratedRegex(@"^//\s+#type\s+(?[a-z]+)$", RegexOptions.Compiled)] - private static partial Regex TypeRegex(); - public object Load(string parPath, IResourceStreamProvider parStreamProvider) { var textReader = new StreamReader(parStreamProvider.GetStream(parPath)); @@ -38,4 +35,7 @@ public partial class ProgramLoader : IResourceLoader return new Program(vertexSource.ToString(), fragmentSource.ToString()); } + + [GeneratedRegex(@"^//\s+#type\s+(?[a-z]+)$", RegexOptions.Compiled)] + private static partial Regex TypeRegex(); } \ No newline at end of file diff --git a/Engine/src/Resource/ResourceHandle.cs b/Engine/src/Resource/ResourceHandle.cs deleted file mode 100644 index 0af4c85..0000000 --- a/Engine/src/Resource/ResourceHandle.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Engine.Resource; - -public class ResourceHandle -{ - public T? Value - { - get - { - if (_isLoaded) - { - return _value!; - } - - if (!_task.IsCompleted) - { - return _defaultValue; - } - - _value = _task.Result; - _isLoaded = true; - - return _value!; - } - } - - private readonly T? _defaultValue; - private readonly Task _task; - private T? _value; - private bool _isLoaded; - - public ResourceHandle(Task parTask, T? parDefaultValue) - { - _defaultValue = parDefaultValue; - _task = parTask; - } -} \ No newline at end of file diff --git a/Engine/src/Resource/ResourceManager.cs b/Engine/src/Resource/ResourceManager.cs index 230760a..e040edb 100644 --- a/Engine/src/Resource/ResourceManager.cs +++ b/Engine/src/Resource/ResourceManager.cs @@ -2,20 +2,14 @@ public class ResourceManager : IResourceManager { - internal IResourceStreamProvider StreamProvider => _streamProvider; + internal IResourceStreamProvider StreamProvider { get; } - private readonly IResourceStreamProvider _streamProvider; private readonly Dictionary _loaders = new(); private readonly Dictionary _storages = new(); public ResourceManager(IResourceStreamProvider parStreamProvider) { - _streamProvider = parStreamProvider; - } - - internal void RegisterLoader(IResourceLoader parLoader) where T : class - { - _loaders.Add(typeof(T), parLoader); + StreamProvider = parStreamProvider; } public T Load(string parPath) where T : class @@ -37,13 +31,18 @@ public class ResourceManager : IResourceManager throw new InvalidOperationException($"No loader found for type {typeof(T)}"); } - var resource = loader.Load(parPath, _streamProvider); + var resource = loader.Load(parPath, StreamProvider); storage.Add(parPath, resource); return (T)resource; } + internal void RegisterLoader(IResourceLoader parLoader) where T : class + { + _loaders.Add(typeof(T), parLoader); + } + internal void Reset() { _storages.Clear(); diff --git a/Engine/src/Resource/ShaderResource.resx b/Engine/src/Resource/ShaderResource.resx index a68988d..57eff86 100644 --- a/Engine/src/Resource/ShaderResource.resx +++ b/Engine/src/Resource/ShaderResource.resx @@ -1,8 +1,9 @@  - + diff --git a/Engine/src/Scene/Component/BuiltIn/OrthographicCamera.cs b/Engine/src/Scene/Component/BuiltIn/OrthographicCamera.cs index 5871630..79af865 100644 --- a/Engine/src/Scene/Component/BuiltIn/OrthographicCamera.cs +++ b/Engine/src/Scene/Component/BuiltIn/OrthographicCamera.cs @@ -11,13 +11,18 @@ public class OrthographicCamera( ) : Camera(parNearPlane, parFarPlane) { - public Axis FixedAxis { get; set; } = parAxis; - public float Size { get; set; } = parSize; - public bool UseScreenSize { get; set; } = false; - - public override Matrix4 View => GameObject.Transform.TransformMatrix.Inverted(); + public enum Axis + { + X, + Y + } public override Matrix4 Projection => GetProjectionMatrix(); + public override Matrix4 View => GameObject.Transform.TransformMatrix.Inverted(); + + public float Size { get; set; } = parSize; + public bool UseScreenSize { get; set; } = false; + public Axis FixedAxis { get; set; } = parAxis; private Matrix4 GetProjectionMatrix() { @@ -27,7 +32,7 @@ public class OrthographicCamera( public override Vector3 ScreenToWorld(Vector2 parScreenPosition) { - var normalized = parScreenPosition / ScreenSize - new Vector2(0.5f); + var normalized = (parScreenPosition / ScreenSize) - new Vector2(0.5f); normalized.X *= 2; normalized.Y *= -2; @@ -70,10 +75,4 @@ public class OrthographicCamera( } } } - - public enum Axis - { - X, - Y - } } \ No newline at end of file diff --git a/Engine/src/Scene/Component/BuiltIn/PerspectiveCamera.cs b/Engine/src/Scene/Component/BuiltIn/PerspectiveCamera.cs index a89096f..d20d752 100644 --- a/Engine/src/Scene/Component/BuiltIn/PerspectiveCamera.cs +++ b/Engine/src/Scene/Component/BuiltIn/PerspectiveCamera.cs @@ -10,9 +10,6 @@ public class PerspectiveCamera( ) : Camera(parNearPlane, parFarPlane) { - public float FieldOfView { get; set; } = parFieldOfView; - - public Vector3 Forward => new Vector4(0, 1, 0, 1).MulProject(GameObject.Transform.TransformMatrix).Xyz; public override Matrix4 View { get @@ -30,9 +27,12 @@ public class PerspectiveCamera( Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(FieldOfView), AspectRatio, NearPlane, FarPlane); + public Vector3 Forward => new Vector4(0, 1, 0, 1).MulProject(GameObject.Transform.TransformMatrix).Xyz; + public float FieldOfView { get; set; } = parFieldOfView; + public override Vector3 ScreenToWorld(Vector2 parScreenPosition) { - var normalized = parScreenPosition / ScreenSize - new Vector2(0.5f); + var normalized = (parScreenPosition / ScreenSize) - new Vector2(0.5f); normalized.X *= 2; normalized.Y *= -2; diff --git a/Engine/src/Scene/Component/BuiltIn/Renderer/Box2DRenderer.cs b/Engine/src/Scene/Component/BuiltIn/Renderer/Box2DRenderer.cs index f35adfd..f553188 100644 --- a/Engine/src/Scene/Component/BuiltIn/Renderer/Box2DRenderer.cs +++ b/Engine/src/Scene/Component/BuiltIn/Renderer/Box2DRenderer.cs @@ -7,7 +7,7 @@ namespace Engine.Scene.Component.BuiltIn.Renderer; public class Box2DRenderer : Component { public ref Vector4 Color => ref _color; - public Texture? Texture { get; set; } = null; + public Texture? Texture { get; set; } public RenderLayer RenderLayer { get; set; } = RenderLayer.DEFAULT; private Vector4 _color = Vector4.One; diff --git a/Engine/src/Scene/Component/BuiltIn/Renderer/TextRenderer.cs b/Engine/src/Scene/Component/BuiltIn/Renderer/TextRenderer.cs index a34026b..e43f3b7 100644 --- a/Engine/src/Scene/Component/BuiltIn/Renderer/TextRenderer.cs +++ b/Engine/src/Scene/Component/BuiltIn/Renderer/TextRenderer.cs @@ -7,9 +7,8 @@ namespace Engine.Scene.Component.BuiltIn.Renderer; public class TextRenderer : Component { public Font Font { get; set; } = null!; - public string? Text { get; set; } public ref Vector4 Color => ref _color; - + public string? Text { get; set; } public RenderLayer RenderLayer { get; set; } = RenderLayer.DEFAULT; private Vector4 _color = Vector4.One; @@ -17,7 +16,9 @@ public class TextRenderer : Component public override void Render() { if (Text == null) + { return; + } Engine.Instance.Renderer[RenderLayer].TextRenderer .Commit(Font, Text, Color, GameObject.Transform.FullTransformMatrix); diff --git a/Engine/src/Scene/Component/BuiltIn/Transform.cs b/Engine/src/Scene/Component/BuiltIn/Transform.cs index 4772f6a..abc82dd 100644 --- a/Engine/src/Scene/Component/BuiltIn/Transform.cs +++ b/Engine/src/Scene/Component/BuiltIn/Transform.cs @@ -4,24 +4,18 @@ namespace Engine.Scene.Component.BuiltIn; public class Transform : Component { - private Vector3 _translation = Vector3.Zero; - private Quaternion _rotation = Quaternion.Identity; - private Vector3 _scale = Vector3.One; - private Vector3 _size = Vector3.One; - - public ref Vector3 Translation => ref _translation; - public ref Quaternion Rotation => ref _rotation; - public ref Vector3 Scale => ref _scale; public ref Vector3 Size => ref _size; + public ref Vector3 Scale => ref _scale; + public ref Quaternion Rotation => ref _rotation; + public ref Vector3 Translation => ref _translation; + + public Matrix4 FullTransformMatrix => Matrix4.CreateScale(Size) * TransformMatrix; + public Matrix4 TransformMatrix => LocalTransformMatrix * ParentTransformMatrix; public Matrix4 LocalTransformMatrix => Matrix4.CreateScale(Scale) * Matrix4.CreateFromQuaternion(Rotation) * Matrix4.CreateTranslation(Translation); - public Matrix4 TransformMatrix => LocalTransformMatrix * ParentTransformMatrix; - - public Matrix4 FullTransformMatrix => Matrix4.CreateScale(Size) * TransformMatrix; - private Matrix4 ParentTransformMatrix { get @@ -31,6 +25,11 @@ public class Transform : Component } } + private Vector3 _size = Vector3.One; + private Vector3 _scale = Vector3.One; + private Quaternion _rotation = Quaternion.Identity; + private Vector3 _translation = Vector3.Zero; + public Vector3 GetFullTranslation() { return FullTransformMatrix.ExtractTranslation(); @@ -43,15 +42,4 @@ public class Transform : Component return clone; } - - public float SquaredDistanceTo(Transform parTransform) - { - var translation = GetFullTranslation(); - var otherTranslation = parTransform.GetFullTranslation(); - - var difference = translation - otherTranslation; - var squaredDistance = difference.LengthSquared; - - return squaredDistance; - } } \ No newline at end of file diff --git a/Engine/src/Scene/GameObject.cs b/Engine/src/Scene/GameObject.cs index d866790..bf68c8b 100644 --- a/Engine/src/Scene/GameObject.cs +++ b/Engine/src/Scene/GameObject.cs @@ -14,23 +14,22 @@ public sealed class GameObject : IUpdate, IRender set => _nextIsSelfEnabled = value; } - private bool IsSelfEnabled { get; set; } = true; - private bool _prevIsSelfEnabled = true; - private bool _nextIsSelfEnabled = true; - private bool IsParentEnabled => Scene?.Hierarchy.GetParent(this)?.IsEnabled ?? true; - public Transform Transform { get; } internal Scene? Scene { get; set; } - private readonly Queue _componentActions = new(); - - private readonly List _components = []; - private readonly HashSet _addedComponentTypes = []; + private bool IsParentEnabled => Scene?.Hierarchy.GetParent(this)?.IsEnabled ?? true; + private bool IsSelfEnabled { get; set; } = true; private readonly HashSet _addedComponents = []; + private readonly HashSet _addedComponentTypes = []; + private readonly Queue _componentActions = new(); + private readonly List _components = []; private readonly HashSet _removedComponents = []; + private bool _nextIsSelfEnabled = true; + private bool _prevIsSelfEnabled = true; + public GameObject() { AddComponent(); @@ -58,34 +57,14 @@ public sealed class GameObject : IUpdate, IRender } } - private void ProcessAddedComponents() - { - foreach (var component in _addedComponents) - { - component.Awake(); - component.Start(); - } - - _addedComponents.Clear(); - } - - private void ProcessRemovedComponents() - { - foreach (var component in _removedComponents) - { - component.Destroy(); - component.GameObject = null!; - } - - _removedComponents.Clear(); - } - public void Update(double parDeltaTime) { if (!IsEnabled) { if (!_prevIsSelfEnabled) + { return; + } foreach (var component in _components) { @@ -115,7 +94,9 @@ public sealed class GameObject : IUpdate, IRender public void Render() { if (!IsEnabled) + { return; + } foreach (var component in _components) { @@ -134,12 +115,16 @@ public sealed class GameObject : IUpdate, IRender public T? GetComponent() where T : Component.Component { if (!HasComponent()) + { return null; + } foreach (var component in _components) { if (component is T result) + { return result; + } } return null; @@ -149,7 +134,9 @@ public sealed class GameObject : IUpdate, IRender { var component = GetComponent(); if (component != null) + { return component; + } component = GetComponentInChildren(); return component; @@ -163,11 +150,15 @@ public sealed class GameObject : IUpdate, IRender { var component = child.GetComponent(); if (component != null) + { return component; + } var childComponent = child.GetComponentInChildren(); if (childComponent != null) + { return childComponent; + } } return null; @@ -257,6 +248,28 @@ public sealed class GameObject : IUpdate, IRender } } + private void ProcessAddedComponents() + { + foreach (var component in _addedComponents) + { + component.Awake(); + component.Start(); + } + + _addedComponents.Clear(); + } + + private void ProcessRemovedComponents() + { + foreach (var component in _removedComponents) + { + component.Destroy(); + component.GameObject = null!; + } + + _removedComponents.Clear(); + } + public override string ToString() { return Id.ToString(); diff --git a/Engine/src/Scene/Hierarchy.cs b/Engine/src/Scene/Hierarchy.cs index 5b68c14..88c57d8 100644 --- a/Engine/src/Scene/Hierarchy.cs +++ b/Engine/src/Scene/Hierarchy.cs @@ -10,7 +10,6 @@ public class Hierarchy private readonly Dictionary, IList> _childrenLookup = new(); private readonly Dictionary _parentLookup = new(); - private readonly ConcurrentQueue _hierarchyActions = new(); public Hierarchy() @@ -51,7 +50,9 @@ public class Hierarchy _hierarchyActions.Enqueue(() => { if (!Contains(parObj)) + { return; + } var parent = GetParent(parObj); _childrenLookup[parent].Remove(parObj); diff --git a/Engine/src/Scene/Scene.cs b/Engine/src/Scene/Scene.cs index 4c88bfb..925fc65 100644 --- a/Engine/src/Scene/Scene.cs +++ b/Engine/src/Scene/Scene.cs @@ -7,49 +7,14 @@ namespace Engine.Scene; public class Scene : IUpdate, IRender { public bool IsPlaying { get; private set; } - public IReadOnlyDictionary Cameras => _cameras; public float TimeScale { get; set; } = 1.0f; - private readonly Dictionary _cameras = new(); - internal Hierarchy Hierarchy { get; } = new(); + internal IReadOnlyDictionary Cameras => _cameras; + private readonly Dictionary _cameras = new(); private readonly Queue _sceneActions = []; - internal void Enter() - { - if (IsPlaying) - { - throw new InvalidOperationException("Scene is already playing"); - } - - ProcessChanges(); - - var allCameras = FindAllComponents(); - foreach (var camera in allCameras) - { - _cameras.Add(camera.RenderLayer, camera); - } - - IsPlaying = true; - } - - public List FindAllComponents(bool parOnlyEnabled = true) where T : Component.Component - { - return Hierarchy.Objects - .Where(parGameObject => !parOnlyEnabled || parGameObject.IsEnabled) - .Select(parGameObject => parGameObject.GetComponent()) - .Where(parComponent => parComponent != null) - .Distinct() - .ToList()!; - } - - public T? FindFirstComponent() where T : Component.Component - { - return Hierarchy.Objects.Select(parGameObject => parGameObject.GetComponent()) - .FirstOrDefault(parComponent => parComponent != null); - } - public void Update(double parDeltaTime) { if (!IsPlaying) @@ -85,19 +50,20 @@ public class Scene : IUpdate, IRender } } - internal void Exit() + public List FindAllComponents(bool parOnlyEnabled = true) where T : Component.Component { - if (!IsPlaying) - { - throw new InvalidOperationException("Scene is not playing"); - } + return Hierarchy.Objects + .Where(parGameObject => !parOnlyEnabled || parGameObject.IsEnabled) + .Select(parGameObject => parGameObject.GetComponent()) + .Where(parComponent => parComponent != null) + .Distinct() + .ToList()!; + } - foreach (var gameObject in Hierarchy.Objects) - { - gameObject.Destroy(); - } - - IsPlaying = false; + public T? FindFirstComponent() where T : Component.Component + { + return Hierarchy.Objects.Select(parGameObject => parGameObject.GetComponent()) + .FirstOrDefault(parComponent => parComponent != null); } public void Add(GameObject parGameObject) @@ -136,6 +102,39 @@ public class Scene : IUpdate, IRender return parRecursive ? Hierarchy.GetAllChildren(parParent) : Hierarchy.GetChildren(parParent); } + internal void Enter() + { + if (IsPlaying) + { + throw new InvalidOperationException("Scene is already playing"); + } + + ProcessChanges(); + + var allCameras = FindAllComponents(); + foreach (var camera in allCameras) + { + _cameras.Add(camera.RenderLayer, camera); + } + + IsPlaying = true; + } + + internal void Exit() + { + if (!IsPlaying) + { + throw new InvalidOperationException("Scene is not playing"); + } + + foreach (var gameObject in Hierarchy.Objects) + { + gameObject.Destroy(); + } + + IsPlaying = false; + } + private void ProcessChanges() { Hierarchy.ProcessChanges(); diff --git a/Engine/src/Scene/SceneManager.cs b/Engine/src/Scene/SceneManager.cs index 32dd02d..84ca403 100644 --- a/Engine/src/Scene/SceneManager.cs +++ b/Engine/src/Scene/SceneManager.cs @@ -2,32 +2,33 @@ public class SceneManager : IUpdate, IRender { - public Scene? CurrentScene => _currentScene; + public Scene? CurrentScene { get; private set; } - private Scene? _currentScene; private Func? _nextScene; - public void TransitionTo(Func? parScene) - { - _nextScene = parScene; - } - public void Update(double parDeltaTime) { if (_nextScene != null) { - _currentScene?.Exit(); - _currentScene = _nextScene(); + CurrentScene?.Exit(); + CurrentScene = _nextScene(); _nextScene = null; - _currentScene.Enter(); + CurrentScene.Enter(); } if (parDeltaTime != 0) - _currentScene?.Update(parDeltaTime); + { + CurrentScene?.Update(parDeltaTime); + } } public void Render() { - _currentScene?.Render(); + CurrentScene?.Render(); + } + + public void TransitionTo(Func? parScene) + { + _nextScene = parScene; } } \ No newline at end of file diff --git a/Engine/src/Util/TickableTimer.cs b/Engine/src/Util/TickableTimer.cs index 4bf65f8..b0cd1fe 100644 --- a/Engine/src/Util/TickableTimer.cs +++ b/Engine/src/Util/TickableTimer.cs @@ -2,21 +2,10 @@ public class TickableTimer { - public event Action? OnFinished; public event Action? OnUpdate; + public event Action? OnFinished; - public double TotalTime - { - get => _totalTime; - set - { - if (value <= 0) - ArgumentOutOfRangeException.ThrowIfNegativeOrZero(value); - - _totalTime = value; - CurrentTime = value; - } - } + public bool IsFinished => _currentTime <= 0; public double CurrentTime { @@ -24,30 +13,54 @@ public class TickableTimer set { if (value < 0) + { value = 0; + } + if (value > TotalTime) + { value = TotalTime; + } if (value == _currentTime) + { return; + } _currentTime = value; OnUpdate?.Invoke(value); if (IsFinished) + { OnFinished?.Invoke(); + } } } - public bool IsFinished => _currentTime <= 0; + public double TotalTime + { + get => _totalTime; + set + { + if (value <= 0) + { + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(value); + } + + _totalTime = value; + CurrentTime = value; + } + } - private double _totalTime; private double _currentTime; + private double _totalTime; public TickableTimer(double parTotalTime) { if (parTotalTime <= 0) + { ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parTotalTime); + } _totalTime = parTotalTime; _currentTime = parTotalTime; diff --git a/Engine/src/Window.cs b/Engine/src/Window.cs index 3893c57..91760b7 100644 --- a/Engine/src/Window.cs +++ b/Engine/src/Window.cs @@ -9,34 +9,34 @@ namespace Engine; public class Window : IPresenter { - public bool IsExiting => _window.IsExiting; - public int Width { get; private set; } - public int Height { get; private set; } public event Action? Resize; - internal NativeWindow NativeWindow => _window; + public int Width { get; private set; } + public int Height { get; private set; } + public bool IsExiting => NativeWindow.IsExiting; + + internal NativeWindow NativeWindow { get; } private readonly Engine _engine; - private readonly NativeWindow _window; private readonly bool _headless; public Window(Engine parEngine, NativeWindow parWindow, bool parHeadless) { _engine = parEngine; - _window = parWindow; + NativeWindow = parWindow; _headless = parHeadless; - (Width, Height) = _window.ClientSize; + (Width, Height) = NativeWindow.ClientSize; - _window.MakeCurrent(); - _window.Resize += parArgs => + NativeWindow.MakeCurrent(); + NativeWindow.Resize += parArgs => { Width = parArgs.Width; Height = parArgs.Height; Resize?.Invoke(parArgs); }; - _window.VSync = VSyncMode.On; + NativeWindow.VSync = VSyncMode.On; } public void Update(double parDeltaTime) @@ -50,9 +50,9 @@ public class Window : IPresenter return; } - _window.NewInputFrame(); + NativeWindow.NewInputFrame(); NativeWindow.ProcessWindowEvents(false); - _window.SwapBuffers(); + NativeWindow.SwapBuffers(); } public void Present(IConstTexture parTexture) @@ -72,7 +72,7 @@ public class Window : IPresenter public void Exit() { - _window.Close(); + NativeWindow.Close(); } } diff --git a/PresenterConsole/PresenterConsole.csproj b/PresenterConsole/PresenterConsole.csproj index d13d7d6..4aab53b 100644 --- a/PresenterConsole/PresenterConsole.csproj +++ b/PresenterConsole/PresenterConsole.csproj @@ -9,7 +9,7 @@ - + diff --git a/PresenterConsole/src/ConsoleFastOutput.cs b/PresenterConsole/src/ConsoleFastOutput.cs index ef8c077..f447055 100644 --- a/PresenterConsole/src/ConsoleFastOutput.cs +++ b/PresenterConsole/src/ConsoleFastOutput.cs @@ -5,16 +5,16 @@ namespace PresenterConsole; public sealed class ConsoleFastOutput : IDisposable { - private const uint GENERIC_WRITE = 0x40000000; private const int FILE_SHARE_WRITE = 0x2; + private const uint GENERIC_WRITE = 0x40000000; - private readonly SafeFileHandle _handle; private readonly WindowsFFI.Coord _bufferCoord = new(0, 0); + private readonly SafeFileHandle _handle; - private int _width; - private int _height; private WindowsFFI.CharInfo[] _buffer; private WindowsFFI.Coord _bufferSize; + private int _height; + private int _width; public ConsoleFastOutput(int parWidth, int parHeight) @@ -26,7 +26,9 @@ public sealed class ConsoleFastOutput : IDisposable IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero); if (_handle.IsInvalid) + { throw new InvalidOperationException("Failed to open console handle"); + } Resize(parWidth, parHeight); } @@ -34,7 +36,7 @@ public sealed class ConsoleFastOutput : IDisposable [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteChar(char parCharacter, int parX, int parY, ConsoleColor parForeground, ConsoleColor parBackground) { - var index = parX + parY * _width; + var index = parX + (parY * _width); ref var charInfo = ref _buffer[index]; charInfo.Char.UnicodeChar = parCharacter; charInfo.Attributes = (short)((ushort)parForeground | ((ushort)parBackground << 4)); @@ -53,7 +55,9 @@ public sealed class ConsoleFastOutput : IDisposable ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parHeight); if (parWidth == _width && parHeight == _height) + { return; + } _width = parWidth; _height = parHeight; diff --git a/PresenterConsole/src/ConsoleInputHandler.cs b/PresenterConsole/src/ConsoleInputHandler.cs index 9297518..5f576d8 100644 --- a/PresenterConsole/src/ConsoleInputHandler.cs +++ b/PresenterConsole/src/ConsoleInputHandler.cs @@ -7,7 +7,6 @@ namespace PresenterConsole; public class ConsoleInputHandler : IInputHandler { public CultureInfo CurrentInputLanguage => WindowsFFI.GetCurrentKeyboardLayout(); - public Vector2 MousePosition => Vector2.Zero; private readonly bool[] _currentKeys = new bool[256]; @@ -46,17 +45,20 @@ public class ConsoleInputHandler : IInputHandler return _currentKeys[consoleKey] && !_previousKeys[consoleKey]; } - private static int ConvertToConsoleKey(MouseButtonCode parMouseButtonCode) => - parMouseButtonCode switch + private static int ConvertToConsoleKey(MouseButtonCode parMouseButtonCode) + { + return parMouseButtonCode switch { MouseButtonCode.Left => 0x01, MouseButtonCode.Right => 0x02, MouseButtonCode.Middle => 0x04, _ => throw new ArgumentOutOfRangeException(nameof(parMouseButtonCode), parMouseButtonCode, null) }; + } - private static int ConvertToConsoleKey(KeyboardButtonCode parKeyboardButtonCode) => - parKeyboardButtonCode switch + private static int ConvertToConsoleKey(KeyboardButtonCode parKeyboardButtonCode) + { + return parKeyboardButtonCode switch { KeyboardButtonCode.A => 0x41, KeyboardButtonCode.B => 0x42, @@ -114,4 +116,5 @@ public class ConsoleInputHandler : IInputHandler KeyboardButtonCode.D9 => 0x39, _ => throw new ArgumentOutOfRangeException(nameof(parKeyboardButtonCode), parKeyboardButtonCode, null) }; + } } \ No newline at end of file diff --git a/PresenterConsole/src/ConsolePresenter.cs b/PresenterConsole/src/ConsolePresenter.cs index 23d31ec..f188a95 100644 --- a/PresenterConsole/src/ConsolePresenter.cs +++ b/PresenterConsole/src/ConsolePresenter.cs @@ -14,31 +14,30 @@ namespace PresenterConsole; public class ConsolePresenter : IPresenter { - public bool IsExiting { get; private set; } - public int Width { get; private set; } = 2; - public int Height { get; private set; } = 1; public event Action? Resize; - private readonly Engine.Engine _engine; + public int Width { get; private set; } = 2; + public int Height { get; private set; } = 1; + public bool IsExiting { get; private set; } - private readonly Framebuffer _framebuffer; - private readonly Engine.Graphics.Shader.Program _asciiProgram; - private Image? _asciiImage; - - private readonly IndexBuffer _indexBuffer; - private readonly VertexBuffer _vertexBuffer; - private readonly VertexArray _vertexArray; + private static readonly char[] LIGHTMAP = " .,:;=*#%@".Reverse().ToArray(); private readonly ConsoleFastOutput _consoleOutput; - private static readonly char[] LIGHTMAP = " .,:;=*#%@".Reverse().ToArray(); + + private readonly Engine.Graphics.Shader.Program _asciiProgram; + private readonly Framebuffer _framebuffer; + private readonly IndexBuffer _indexBuffer; + private readonly VertexArray _vertexArray; + private readonly VertexBuffer _vertexBuffer; + + private Image? _asciiImage; public ConsolePresenter(Engine.Engine parEngine) { - _engine = parEngine; - ((MemoryResourceStreamProvider)_engine.EngineResourceManager.StreamProvider).AddResource("shader/ascii", + ((MemoryResourceStreamProvider)parEngine.EngineResourceManager.StreamProvider).AddResource("shader/ascii", Encoding.UTF8.GetBytes(ShaderResource.Ascii)); - _asciiProgram = _engine.EngineResourceManager.Load("shader/ascii"); + _asciiProgram = parEngine.EngineResourceManager.Load("shader/ascii"); _framebuffer = Framebuffer.Builder(Width / 2, Height) .AddColorAttachment() @@ -77,36 +76,21 @@ public class ConsolePresenter : IPresenter _framebuffer.Unbind(); - // GL.Viewport(0, 0, Width / 2 * 4, Height * 4); - var asciiTexture = _framebuffer.TextureInternal; if (asciiTexture == null) + { throw new InvalidOperationException("Framebuffer texture is null"); + } if (_asciiImage == null || asciiTexture.Width != _asciiImage.Width || asciiTexture.Height != _asciiImage.Height) + { _asciiImage = new Image(asciiTexture.Width, asciiTexture.Height); + } asciiTexture.ReadPixels(_asciiImage); DrawImage(_asciiImage); } - private void DrawImage(Image parImage) - { - for (var y = 0; y < parImage.Height; y++) - { - for (var x = 0; x < parImage.Width; x++) - { - var pixel = parImage[y, x]; - var lightnessIndex = (byte)(pixel.Luminance / 255.0f * (LIGHTMAP.Length - 1)); - var colorIndex = (ConsoleColor)(pixel.Color / 255.0f * 15.0f); - _consoleOutput.WriteChar(LIGHTMAP[lightnessIndex], 2 * x, y, 0, colorIndex); - _consoleOutput.WriteChar(LIGHTMAP[lightnessIndex], 2 * x + 1, y, 0, colorIndex); - } - } - - _consoleOutput.Flush(); - } - public void Update(double parDeltaTime) { } @@ -131,4 +115,21 @@ public class ConsolePresenter : IPresenter { IsExiting = true; } + + private void DrawImage(Image parImage) + { + for (var y = 0; y < parImage.Height; y++) + { + for (var x = 0; x < parImage.Width; x++) + { + var pixel = parImage[y, x]; + var lightnessIndex = (byte)(pixel.Luminance / 255.0f * (LIGHTMAP.Length - 1)); + var colorIndex = (ConsoleColor)(pixel.Color / 255.0f * 15.0f); + _consoleOutput.WriteChar(LIGHTMAP[lightnessIndex], 2 * x, y, 0, colorIndex); + _consoleOutput.WriteChar(LIGHTMAP[lightnessIndex], (2 * x) + 1, y, 0, colorIndex); + } + } + + _consoleOutput.Flush(); + } } \ No newline at end of file diff --git a/PresenterConsole/src/Program.cs b/PresenterConsole/src/Program.cs index 1e1d05b..02e20da 100644 --- a/PresenterConsole/src/Program.cs +++ b/PresenterConsole/src/Program.cs @@ -1,4 +1,5 @@ -using Serilog.Events; +using Engine; +using Serilog.Events; namespace PresenterConsole; @@ -6,7 +7,7 @@ internal static class Program { public static void Main(string[] parArgs) { - var engine = new Engine.EngineBuilder() + var engine = new EngineBuilder() .Headless() .LogToFile(true, "log.txt") .LogLevel(LogEventLevel.Debug) diff --git a/PresenterConsole/src/Resource/ShaderResource.resx b/PresenterConsole/src/Resource/ShaderResource.resx index 4d2ff4c..e027370 100644 --- a/PresenterConsole/src/Resource/ShaderResource.resx +++ b/PresenterConsole/src/Resource/ShaderResource.resx @@ -1,8 +1,9 @@  - + diff --git a/PresenterNative/PresenterNative.csproj b/PresenterNative/PresenterNative.csproj index 1fb4d59..ec62ab6 100644 --- a/PresenterNative/PresenterNative.csproj +++ b/PresenterNative/PresenterNative.csproj @@ -8,7 +8,7 @@ - + diff --git a/PresenterWpf/PresenterWpf.csproj b/PresenterWpf/PresenterWpf.csproj index e50914d..06c6158 100644 --- a/PresenterWpf/PresenterWpf.csproj +++ b/PresenterWpf/PresenterWpf.csproj @@ -9,7 +9,7 @@ - + diff --git a/PresenterWpf/src/App.xaml b/PresenterWpf/src/App.xaml index f841d25..12e06c7 100644 --- a/PresenterWpf/src/App.xaml +++ b/PresenterWpf/src/App.xaml @@ -1,5 +1,4 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> \ No newline at end of file diff --git a/PresenterWpf/src/App.xaml.cs b/PresenterWpf/src/App.xaml.cs index 8249991..90686eb 100644 --- a/PresenterWpf/src/App.xaml.cs +++ b/PresenterWpf/src/App.xaml.cs @@ -1,6 +1,7 @@ using System.Globalization; using System.IO; using System.Windows; +using System.Windows.Threading; using Engine; using Engine.Graphics; using Engine.Graphics.Texture; @@ -12,7 +13,7 @@ using Serilog.Events; namespace PresenterWpf; /// -/// Interaction logic for App.xaml +/// Interaction logic for App.xaml /// public partial class App : Application { @@ -35,11 +36,11 @@ public partial class App : Application // Since engine claims current thread for rendering, we need to create a new thread to run WPF var thread = new Thread(() => { - var window = new MainWindow(engine); + var window = new MainWindow(); presenter.Presenter = window; inputHandler.InputHandler = new WpfInputHandler(window); window.Show(); - System.Windows.Threading.Dispatcher.Run(); + Dispatcher.Run(); }); thread.SetApartmentState(ApartmentState.STA); @@ -56,50 +57,41 @@ public partial class App : Application private class InputHandlerWrapper : IInputHandler { - public CultureInfo CurrentInputLanguage => _inputHandler?.CurrentInputLanguage ?? new CultureInfo(1033); + public IInputHandler? InputHandler { get; set; } - public Vector2 MousePosition => _inputHandler?.MousePosition ?? Vector2.Zero; + public CultureInfo CurrentInputLanguage => InputHandler?.CurrentInputLanguage ?? new CultureInfo(1033); - private IInputHandler? _inputHandler; - - public IInputHandler? InputHandler - { - get => _inputHandler; - set - { - _inputHandler = value; - } - } + public Vector2 MousePosition => InputHandler?.MousePosition ?? Vector2.Zero; public bool IsKeyPressed(KeyboardButtonCode parKeyboardButtonCode) { - return _inputHandler?.IsKeyPressed(parKeyboardButtonCode) ?? false; + return InputHandler?.IsKeyPressed(parKeyboardButtonCode) ?? false; } public bool IsKeyJustPressed(KeyboardButtonCode parKeyboardButtonCode) { - return _inputHandler?.IsKeyJustPressed(parKeyboardButtonCode) ?? false; + return InputHandler?.IsKeyJustPressed(parKeyboardButtonCode) ?? false; } public bool IsMouseButtonPressed(MouseButtonCode parButtonCode) { - return _inputHandler?.IsMouseButtonPressed(parButtonCode) ?? false; + return InputHandler?.IsMouseButtonPressed(parButtonCode) ?? false; } public bool IsMouseButtonJustPressed(MouseButtonCode parButtonCode) { - return _inputHandler?.IsMouseButtonJustPressed(parButtonCode) ?? false; + return InputHandler?.IsMouseButtonJustPressed(parButtonCode) ?? false; } public void Update(double parDeltaTime) { - _inputHandler?.Update(parDeltaTime); + InputHandler?.Update(parDeltaTime); } } private class PresenterWrapper : IPresenter { - private IPresenter? _presenter; + public event Action? Resize; public IPresenter? Presenter { @@ -120,10 +112,11 @@ public partial class App : Application } } - public bool IsExiting => Presenter?.IsExiting ?? false; public int Width => Presenter?.Width ?? 0; public int Height => Presenter?.Height ?? 0; - public event Action? Resize; + public bool IsExiting => Presenter?.IsExiting ?? false; + + private IPresenter? _presenter; public void Present(IConstTexture parTexture) { @@ -140,14 +133,14 @@ public partial class App : Application Presenter?.Render(); } - private void PresenterResize(ResizeEventArgs e) - { - Resize?.Invoke(e); - } - public void Exit() { Presenter?.Exit(); } + + private void PresenterResize(ResizeEventArgs e) + { + Resize?.Invoke(e); + } } } \ No newline at end of file diff --git a/PresenterWpf/src/MainWindow.xaml b/PresenterWpf/src/MainWindow.xaml index ef8cd4d..2b615ac 100644 --- a/PresenterWpf/src/MainWindow.xaml +++ b/PresenterWpf/src/MainWindow.xaml @@ -3,7 +3,6 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:local="clr-namespace:PresenterWpf" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" Closing="MainWindow_OnClosing"> diff --git a/PresenterWpf/src/MainWindow.xaml.cs b/PresenterWpf/src/MainWindow.xaml.cs index 375d788..74ae01b 100644 --- a/PresenterWpf/src/MainWindow.xaml.cs +++ b/PresenterWpf/src/MainWindow.xaml.cs @@ -12,23 +12,19 @@ namespace PresenterWpf; public partial class MainWindow : Window, IPresenter { - public bool IsExiting { get; private set; } - public new int Width { get; private set; } - public new int Height { get; private set; } - - private bool _scheduledResize; - public event Action? Resize; - private readonly Engine.Engine _engine; - private Image? _image; - private WriteableBitmap? _bitmap; + public new int Width { get; private set; } + public new int Height { get; private set; } + public bool IsExiting { get; private set; } - public MainWindow(Engine.Engine parEngine) + private WriteableBitmap? _bitmap; + private Image? _image; + private bool _scheduledResize; + + public MainWindow() { InitializeComponent(); - - _engine = parEngine; } public void Update(double parDeltaTime) diff --git a/PresenterWpf/src/WPFInputHandler.cs b/PresenterWpf/src/WPFInputHandler.cs index 03be6e4..b92f3fc 100644 --- a/PresenterWpf/src/WPFInputHandler.cs +++ b/PresenterWpf/src/WPFInputHandler.cs @@ -9,9 +9,7 @@ namespace PresenterWpf; public class WpfInputHandler : IInputHandler { public CultureInfo CurrentInputLanguage { get; private set; } - public Vector2 MousePosition => _mousePosition; - - private readonly Window _window; + public Vector2 MousePosition { get; private set; } = Vector2.Zero; private readonly bool[] _actualKeys = new bool[(int)KeyboardButtonCode.TotalCount]; private readonly bool[] _currentKeys = new bool[(int)KeyboardButtonCode.TotalCount]; @@ -21,8 +19,7 @@ public class WpfInputHandler : IInputHandler private readonly bool[] _currentMouseButtons = new bool[(int)MouseButtonCode.TotalCount]; private readonly bool[] _previousMouseButtons = new bool[(int)MouseButtonCode.TotalCount]; - - private Vector2 _mousePosition = Vector2.Zero; + private readonly Window _window; public WpfInputHandler(Window parWindow) { @@ -35,6 +32,14 @@ public class WpfInputHandler : IInputHandler _window.MouseMove += Window_MouseMove; } + ~WpfInputHandler() + { + _window.PreviewKeyDown -= Window_PreviewKeyDown; + _window.PreviewKeyUp -= Window_PreviewKeyUp; + _window.PreviewMouseDown -= Window_PreviewMouseDown; + _window.PreviewMouseUp -= Window_PreviewMouseUp; + } + public void Update(double parDeltaTime) { _window.Dispatcher.Invoke(() => @@ -55,6 +60,30 @@ public class WpfInputHandler : IInputHandler } } + public bool IsKeyPressed(KeyboardButtonCode parKeyboardButtonCode) + { + var keyCode = (int)parKeyboardButtonCode; + return _currentKeys[keyCode]; + } + + public bool IsKeyJustPressed(KeyboardButtonCode parKeyboardButtonCode) + { + var keyCode = (int)parKeyboardButtonCode; + return _currentKeys[keyCode] && !_previousKeys[keyCode]; + } + + public bool IsMouseButtonPressed(MouseButtonCode parButtonCode) + { + var buttonCode = (int)parButtonCode; + return _currentMouseButtons[buttonCode]; + } + + public bool IsMouseButtonJustPressed(MouseButtonCode parButtonCode) + { + var buttonCode = (int)parButtonCode; + return _currentMouseButtons[buttonCode] && !_previousMouseButtons[buttonCode]; + } + private void Window_PreviewKeyDown(object parSender, KeyEventArgs parEventArgs) { var keyCode = ConvertToKeyboardButtonCode(parEventArgs.Key); @@ -94,109 +123,82 @@ public class WpfInputHandler : IInputHandler private void Window_MouseMove(object parSender, MouseEventArgs parEventArgs) { var position = parEventArgs.GetPosition(null); - _mousePosition = new Vector2((float)position.X, (float)position.Y); + MousePosition = new Vector2((float)position.X, (float)position.Y); } - public bool IsKeyPressed(KeyboardButtonCode parKeyboardButtonCode) + private static int ConvertToKeyboardButtonCode(Key parKey) { - var keyCode = (int)parKeyboardButtonCode; - return _currentKeys[keyCode]; + return parKey switch + { + Key.A => (int)KeyboardButtonCode.A, + Key.B => (int)KeyboardButtonCode.B, + Key.C => (int)KeyboardButtonCode.C, + Key.D => (int)KeyboardButtonCode.D, + Key.E => (int)KeyboardButtonCode.E, + Key.F => (int)KeyboardButtonCode.F, + Key.G => (int)KeyboardButtonCode.G, + Key.H => (int)KeyboardButtonCode.H, + Key.I => (int)KeyboardButtonCode.I, + Key.J => (int)KeyboardButtonCode.J, + Key.K => (int)KeyboardButtonCode.K, + Key.L => (int)KeyboardButtonCode.L, + Key.M => (int)KeyboardButtonCode.M, + Key.N => (int)KeyboardButtonCode.N, + Key.O => (int)KeyboardButtonCode.O, + Key.P => (int)KeyboardButtonCode.P, + Key.Q => (int)KeyboardButtonCode.Q, + Key.R => (int)KeyboardButtonCode.R, + Key.S => (int)KeyboardButtonCode.S, + Key.T => (int)KeyboardButtonCode.T, + Key.U => (int)KeyboardButtonCode.U, + Key.V => (int)KeyboardButtonCode.V, + Key.W => (int)KeyboardButtonCode.W, + Key.X => (int)KeyboardButtonCode.X, + Key.Y => (int)KeyboardButtonCode.Y, + Key.Z => (int)KeyboardButtonCode.Z, + Key.LeftCtrl => (int)KeyboardButtonCode.Ctrl, + Key.LeftAlt => (int)KeyboardButtonCode.Alt, + Key.LeftShift => (int)KeyboardButtonCode.Shift, + Key.RightCtrl => (int)KeyboardButtonCode.Ctrl, + Key.RightAlt => (int)KeyboardButtonCode.Alt, + Key.RightShift => (int)KeyboardButtonCode.Shift, + Key.Space => (int)KeyboardButtonCode.Space, + Key.Tab => (int)KeyboardButtonCode.Tab, + Key.Back => (int)KeyboardButtonCode.Backspace, + Key.Return => (int)KeyboardButtonCode.Enter, + Key.Escape => (int)KeyboardButtonCode.Escape, + Key.PageUp => (int)KeyboardButtonCode.PageUp, + Key.PageDown => (int)KeyboardButtonCode.PageDown, + Key.Up => (int)KeyboardButtonCode.Up, + Key.Down => (int)KeyboardButtonCode.Down, + Key.Left => (int)KeyboardButtonCode.Left, + Key.Right => (int)KeyboardButtonCode.Right, + Key.Delete => (int)KeyboardButtonCode.Delete, + Key.Insert => (int)KeyboardButtonCode.Insert, + Key.Home => (int)KeyboardButtonCode.Home, + Key.End => (int)KeyboardButtonCode.End, + Key.D0 => (int)KeyboardButtonCode.D0, + Key.D1 => (int)KeyboardButtonCode.D1, + Key.D2 => (int)KeyboardButtonCode.D2, + Key.D3 => (int)KeyboardButtonCode.D3, + Key.D4 => (int)KeyboardButtonCode.D4, + Key.D5 => (int)KeyboardButtonCode.D5, + Key.D6 => (int)KeyboardButtonCode.D6, + Key.D7 => (int)KeyboardButtonCode.D7, + Key.D8 => (int)KeyboardButtonCode.D8, + Key.D9 => (int)KeyboardButtonCode.D9, + _ => -1 + }; } - public bool IsKeyJustPressed(KeyboardButtonCode parKeyboardButtonCode) + private static int ConvertToMouseButtonCode(MouseButton parButton) { - var keyCode = (int)parKeyboardButtonCode; - return _currentKeys[keyCode] && !_previousKeys[keyCode]; - } - - public bool IsMouseButtonPressed(MouseButtonCode parButtonCode) - { - var buttonCode = (int)parButtonCode; - return _currentMouseButtons[buttonCode]; - } - - public bool IsMouseButtonJustPressed(MouseButtonCode parButtonCode) - { - var buttonCode = (int)parButtonCode; - return _currentMouseButtons[buttonCode] && !_previousMouseButtons[buttonCode]; - } - - private static int ConvertToKeyboardButtonCode(Key parKey) => parKey switch - { - Key.A => (int)KeyboardButtonCode.A, - Key.B => (int)KeyboardButtonCode.B, - Key.C => (int)KeyboardButtonCode.C, - Key.D => (int)KeyboardButtonCode.D, - Key.E => (int)KeyboardButtonCode.E, - Key.F => (int)KeyboardButtonCode.F, - Key.G => (int)KeyboardButtonCode.G, - Key.H => (int)KeyboardButtonCode.H, - Key.I => (int)KeyboardButtonCode.I, - Key.J => (int)KeyboardButtonCode.J, - Key.K => (int)KeyboardButtonCode.K, - Key.L => (int)KeyboardButtonCode.L, - Key.M => (int)KeyboardButtonCode.M, - Key.N => (int)KeyboardButtonCode.N, - Key.O => (int)KeyboardButtonCode.O, - Key.P => (int)KeyboardButtonCode.P, - Key.Q => (int)KeyboardButtonCode.Q, - Key.R => (int)KeyboardButtonCode.R, - Key.S => (int)KeyboardButtonCode.S, - Key.T => (int)KeyboardButtonCode.T, - Key.U => (int)KeyboardButtonCode.U, - Key.V => (int)KeyboardButtonCode.V, - Key.W => (int)KeyboardButtonCode.W, - Key.X => (int)KeyboardButtonCode.X, - Key.Y => (int)KeyboardButtonCode.Y, - Key.Z => (int)KeyboardButtonCode.Z, - Key.LeftCtrl => (int)KeyboardButtonCode.Ctrl, - Key.LeftAlt => (int)KeyboardButtonCode.Alt, - Key.LeftShift => (int)KeyboardButtonCode.Shift, - Key.RightCtrl => (int)KeyboardButtonCode.Ctrl, - Key.RightAlt => (int)KeyboardButtonCode.Alt, - Key.RightShift => (int)KeyboardButtonCode.Shift, - Key.Space => (int)KeyboardButtonCode.Space, - Key.Tab => (int)KeyboardButtonCode.Tab, - Key.Back => (int)KeyboardButtonCode.Backspace, - Key.Return => (int)KeyboardButtonCode.Enter, - Key.Escape => (int)KeyboardButtonCode.Escape, - Key.PageUp => (int)KeyboardButtonCode.PageUp, - Key.PageDown => (int)KeyboardButtonCode.PageDown, - Key.Up => (int)KeyboardButtonCode.Up, - Key.Down => (int)KeyboardButtonCode.Down, - Key.Left => (int)KeyboardButtonCode.Left, - Key.Right => (int)KeyboardButtonCode.Right, - Key.Delete => (int)KeyboardButtonCode.Delete, - Key.Insert => (int)KeyboardButtonCode.Insert, - Key.Home => (int)KeyboardButtonCode.Home, - Key.End => (int)KeyboardButtonCode.End, - Key.D0 => (int)KeyboardButtonCode.D0, - Key.D1 => (int)KeyboardButtonCode.D1, - Key.D2 => (int)KeyboardButtonCode.D2, - Key.D3 => (int)KeyboardButtonCode.D3, - Key.D4 => (int)KeyboardButtonCode.D4, - Key.D5 => (int)KeyboardButtonCode.D5, - Key.D6 => (int)KeyboardButtonCode.D6, - Key.D7 => (int)KeyboardButtonCode.D7, - Key.D8 => (int)KeyboardButtonCode.D8, - Key.D9 => (int)KeyboardButtonCode.D9, - _ => -1 - }; - - private static int ConvertToMouseButtonCode(MouseButton parButton) => - parButton switch + return parButton switch { MouseButton.Left => (int)MouseButtonCode.Left, MouseButton.Right => (int)MouseButtonCode.Right, MouseButton.Middle => (int)MouseButtonCode.Middle, _ => -1 }; - - ~WpfInputHandler() - { - _window.PreviewKeyDown -= Window_PreviewKeyDown; - _window.PreviewKeyUp -= Window_PreviewKeyUp; - _window.PreviewMouseDown -= Window_PreviewMouseDown; - _window.PreviewMouseUp -= Window_PreviewMouseUp; } } \ No newline at end of file