From 81625abd2576d8d554b8d6fe044405f2a52f76e8 Mon Sep 17 00:00:00 2001 From: Syntriax Date: Sun, 10 Nov 2024 19:18:44 +0300 Subject: [PATCH] refactor: Improved & Fixed Issues with Transforms with Parents --- Engine.Core/Abstract/ITransform.cs | 2 +- Engine.Core/GameManager.cs | 6 ++++++ Engine.Core/GameObject.cs | 23 +++++++++++++++++++++ Engine.Core/Transform.cs | 4 ++-- Engine.Physics2D/Collider2DBehaviourBase.cs | 2 +- 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Engine.Core/Abstract/ITransform.cs b/Engine.Core/Abstract/ITransform.cs index 8511f34..5069368 100644 --- a/Engine.Core/Abstract/ITransform.cs +++ b/Engine.Core/Abstract/ITransform.cs @@ -99,7 +99,7 @@ public interface ITransform : IAssignableGameObject, IEnumerable delegate void OnPositionChangedDelegate(ITransform sender); delegate void OnScaleChangedDelegate(ITransform sender); delegate void OnRotationChangedDelegate(ITransform sender); - delegate void OnParentChangedDelegate(ITransform sender, ITransform? newParent); + delegate void OnParentChangedDelegate(ITransform sender, ITransform? previousParent, ITransform? newParent); delegate void OnChildrenAddedDelegate(ITransform sender, ITransform childrenAdded); delegate void OnChildrenRemovedDelegate(ITransform sender, ITransform childrenRemoved); } diff --git a/Engine.Core/GameManager.cs b/Engine.Core/GameManager.cs index af7c6bd..8fe4591 100644 --- a/Engine.Core/GameManager.cs +++ b/Engine.Core/GameManager.cs @@ -140,6 +140,9 @@ public class GameManager : BaseEntity, IGameManager gameObject.OnFinalized += OnGameObjectFinalize; gameObject.OnExitedHierarchy += OnGameObjectExitedHierarchy; + foreach (ITransform child in gameObject.Transform.Children) + Register(child.GameObject); + if (!gameObject.Initialize()) throw new Exception($"{nameof(gameObject)} can't be initialized"); @@ -161,6 +164,9 @@ public class GameManager : BaseEntity, IGameManager gameObject.OnFinalized -= OnGameObjectFinalize; gameObject.OnExitedHierarchy -= OnGameObjectExitedHierarchy; + foreach (ITransform child in gameObject.Transform.Children) + Unregister(child.GameObject); + _gameObjects.Remove(gameObject); _hierarchyObjects.Remove(gameObject); diff --git a/Engine.Core/GameObject.cs b/Engine.Core/GameObject.cs index 794db4d..c952724 100644 --- a/Engine.Core/GameObject.cs +++ b/Engine.Core/GameObject.cs @@ -71,6 +71,8 @@ public class GameObject : BaseEntity, IGameObject _transform = transform; OnTransformAssigned?.Invoke(this); + transform.OnParentChanged += OnParentChangedInternal; + OnParentChangedInternal(transform, null, transform.Parent); return true; } @@ -88,6 +90,8 @@ public class GameObject : BaseEntity, IGameObject { base.UnassignInternal(); + _transform.OnParentChanged -= OnParentChangedInternal; + OnParentChangedInternal(_transform, _transform.Parent, null); _transform = null!; _behaviourController = null!; _gameManager = null!; @@ -103,6 +107,25 @@ public class GameObject : BaseEntity, IGameObject private void OnBehaviourRemoved(IBehaviourController _, IBehaviour behaviour) { if (IsInitialized) behaviour.Finalize(); } private void OnBehaviourAdded(IBehaviourController _, IBehaviour behaviour) { if (!IsInitialized) behaviour.Initialize(); } + private void OnParentChangedInternal(ITransform sender, ITransform? previousParent, ITransform? newParent) + { + if (previousParent is not null) + { + previousParent.OnParentChanged -= OnParentChangedInternal; + previousParent.GameObject.OnEnteredHierarchy -= EnterHierarchyInternal; + previousParent.GameObject.OnExitedHierarchy -= ExitHierarchyInternal; + } + if (newParent is not null) + { + newParent.OnParentChanged += OnParentChangedInternal; + newParent.GameObject.OnEnteredHierarchy += EnterHierarchyInternal; + newParent.GameObject.OnExitedHierarchy += ExitHierarchyInternal; + } + } + + private void EnterHierarchyInternal(IHierarchyObject sender, IGameManager gameManager) => ((IHierarchyObject)this).EnterHierarchy(gameManager); + private void ExitHierarchyInternal(IHierarchyObject sender, IGameManager gameManager) => ((IHierarchyObject)this).ExitHierarchy(); + bool IHierarchyObject.EnterHierarchy(IGameManager gameManager) { if (IsInHierarchy) diff --git a/Engine.Core/Transform.cs b/Engine.Core/Transform.cs index 3e8e858..654c91a 100644 --- a/Engine.Core/Transform.cs +++ b/Engine.Core/Transform.cs @@ -150,7 +150,7 @@ public class Transform : ITransform UpdateLocalScale(); UpdateLocalRotation(); - OnParentChanged?.Invoke(this, previousParent); + OnParentChanged?.Invoke(this, previousParent, transform); } public void AddChild(ITransform transform) @@ -175,7 +175,7 @@ public class Transform : ITransform public IEnumerator GetEnumerator() => _children.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _children.GetEnumerator(); - private void NotifyChildrenOnParentChange(ITransform transform, ITransform? previousParent) + private void NotifyChildrenOnParentChange(ITransform transform, ITransform? previousParent, ITransform? newParent) { // TODO No idea how logical this is to propagate this to the children the way I'm doing right now. // I was originally gonna just call `child.OnParentChanged?.Invoke(child, child.Parent);` but seems an unnecessary call too? diff --git a/Engine.Physics2D/Collider2DBehaviourBase.cs b/Engine.Physics2D/Collider2DBehaviourBase.cs index c567f76..7764132 100644 --- a/Engine.Physics2D/Collider2DBehaviourBase.cs +++ b/Engine.Physics2D/Collider2DBehaviourBase.cs @@ -46,7 +46,7 @@ public abstract class Collider2DBehaviourBase : Behaviour, ICollider2D Transform.OnParentChanged += UpdateRigidBody2D; } - private void UpdateRigidBody2D(ITransform _1, ITransform? _2) + private void UpdateRigidBody2D(ITransform sender, ITransform? previousParent, ITransform? newParent) { BehaviourController.TryGetBehaviourInParent(out _rigidBody2D); }