using Syntriax.Engine.Core.Abstract; using Syntriax.Engine.Core.Exceptions; namespace Syntriax.Engine.Core; [System.Diagnostics.DebuggerDisplay("Name: {Name}, Initialized: {Initialized}")] public class GameObject : BaseEntity, IGameObject { public event IHierarchyObject.OnEnteredHierarchyDelegate? OnEnteredHierarchy = null; public event IHierarchyObject.OnExitedHierarchyDelegate? OnExitedHierarchy = null; public event IAssignableTransform.OnTransformAssignedDelegate? OnTransformAssigned = null; public event IAssignableBehaviourController.OnBehaviourControllerAssignedDelegate? OnBehaviourControllerAssigned = null; public event INameable.OnNameChangedDelegate? OnNameChanged = null; public event IGameObject.OnUpdatedDelegate? OnUpdated = null; private ITransform _transform = null!; private IBehaviourController _behaviourController = null!; private IGameManager _gameManager = null!; private string _name = nameof(GameObject); public ITransform Transform => _transform; public IBehaviourController BehaviourController => _behaviourController; public IGameManager GameManager => _gameManager; public bool IsInHierarchy => GameManager is not null; public string Name { get => _name; set { if (value == _name) return; string previousName = _name; _name = value; OnNameChanged?.Invoke(this, previousName); } } protected override void InitializeInternal() { base.InitializeInternal(); NotAssignedException.Check(this, _transform); NotAssignedException.Check(this, _behaviourController); if (!_behaviourController.Initialize()) throw new System.Exception($"Failed to Initialize {BehaviourController.GetType().Name} on {Transform.GameObject.Name}"); } public void Update() { if (!StateEnable.Enabled) return; OnUpdated?.Invoke(this); } protected override void FinalizeInternal() { base.FinalizeInternal(); if (!_behaviourController.Finalize()) throw new System.Exception($"Failed to Finalize {BehaviourController.GetType().Name} on {Transform.GameObject.Name}"); } public bool Assign(ITransform transform) { if (IsInitialized) return false; _transform = transform; OnTransformAssigned?.Invoke(this); transform.OnParentChanged += OnParentChangedInternal; OnParentChangedInternal(transform, null, transform.Parent); return true; } public bool Assign(IBehaviourController behaviourController) { if (IsInitialized) return false; _behaviourController = behaviourController; OnBehaviourControllerAssigned?.Invoke(this); return true; } protected override void UnassignInternal() { base.UnassignInternal(); _transform.OnParentChanged -= OnParentChangedInternal; OnParentChangedInternal(_transform, _transform.Parent, null); _transform = null!; _behaviourController = null!; _gameManager = null!; } public GameObject() { OnBehaviourControllerAssigned += ConnectBehaviourController; } private void ConnectBehaviourController(IAssignableBehaviourController controller) { controller.BehaviourController.OnBehaviourAdded += OnBehaviourAdded; controller.BehaviourController.OnBehaviourRemoved += OnBehaviourRemoved; } 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) return false; _gameManager = gameManager; OnEnteredHierarchy?.Invoke(this, gameManager); return true; } bool IHierarchyObject.ExitHierarchy() { if (!IsInHierarchy || _gameManager is not IGameManager gameManager) return false; _gameManager = null!; OnExitedHierarchy?.Invoke(this, gameManager); return true; } }