using System; using System.Collections; using GlitchyEngine.Core; using internal GlitchyEngine.World; namespace GlitchyEngine.World { public struct Entity { private EcsEntity _entity = .InvalidEntity; private Scene _scene = null; public EcsEntity Handle => _entity; public Scene Scene => _scene; public this() { } public this(EcsEntity entity, Scene scene) { _entity = entity; _scene = scene; } public ChildEnumerator EnumerateChildren => .(this); public bool IsValid => _entity.IsValid && _scene != null; public Entity? Parent { get { var cmp = GetComponent(); if (cmp.Parent == .InvalidEntity) return null; return .(cmp.Parent, _scene); } set { if (value == null) { var cmp = GetComponent(); cmp.Parent = .InvalidEntity; } else { Entity parent = value.Value; if (parent.Scene != _scene) { Log.EngineLogger.AssertDebug(false); return; } var cmp = GetComponent(); cmp.Parent = parent._entity; } } } public UUID UUID => GetComponent().ID; public StringView Name { get => GetComponent().Name; set => GetComponent().Name = value; } public TransformComponent* Transform => GetComponent(); public T* AddComponent(T value = T()) where T: struct, new { Log.EngineLogger.AssertDebug(!HasComponent(), scope $"Entity already has component."); T* component = _scene._ecsWorld.AssignComponent(_entity, value); _scene.[Friend]OnComponentAdded(this, typeof(T), component); return component; } public T* GetComponent() where T: struct, new { Log.EngineLogger.AssertDebug(HasComponent(), "Entity doesn't have component!"); return _scene._ecsWorld.GetComponent(_entity); } public bool HasComponent() where T: struct, new { return _scene._ecsWorld.HasComponent(_entity); } public bool TryGetComponent(out T* component) where T: struct, new { if (HasComponent()) { component = GetComponent(); return true; } component = null; return false; } public void RemoveComponent() where T: struct, new { Log.EngineLogger.AssertDebug(HasComponent(), "Entity doesn't have component!"); _scene._ecsWorld.RemoveComponent(_entity); } public struct ChildEnumerator : IEnumerator, IDisposable { private WorldEnumerator _transformEnum; private EcsEntity _entity; private Entity _currentChild; public this(Entity entity) { _entity = entity.Handle; _transformEnum = entity.Scene._ecsWorld.Enumerate(); _currentChild = .(.InvalidEntity, entity.Scene); } public Entity Current => _currentChild; public Result GetNext() mut { while (true) { (EcsEntity entity, TransformComponent* transform) = Try!(_transformEnum.GetNext()); if (transform.Parent == _entity) { _currentChild.[Friend]_entity = entity; return .Ok(_currentChild); } } } public void Dispose() { _transformEnum.Dispose(); } } } }