using Engine.Scene.Component; namespace Engine.Scene; public sealed class GameObject { public Guid Id { get; } = Guid.NewGuid(); public Transform Transform { get; } private readonly Queue _componentActions = new(); private readonly List _components = new(); private readonly ISet _addedComponentTypes = new HashSet(); public GameObject() { AddComponent(); UpdateComponents(); Transform = GetComponent()!; } public T? GetComponent() where T : Component.Component { if (!_addedComponentTypes.Contains(typeof(T))) return null; return _components.OfType().FirstOrDefault(); } public void AddComponent(params object?[] args) where T : Component.Component { if (_addedComponentTypes.Contains(typeof(T))) return; var newArgs = new object?[args.Length + 1]; newArgs[0] = this; for (var i = 0; i < args.Length; i++) newArgs[i + 1] = args[i]; var component = (T?)Activator.CreateInstance(typeof(T), newArgs); if (component == null) throw new InvalidOperationException($"Failed to create component of type {typeof(T)}"); _componentActions.Enqueue(() => { _components.Add(component); _addedComponentTypes.Add(typeof(T)); }); } public void RemoveComponent() where T : Component.Component { if (!_addedComponentTypes.Contains(typeof(T)) || typeof(T) == typeof(Transform)) return; var component = GetComponent(); if (component == null) return; _componentActions.Enqueue(() => { _components.Remove(component); _addedComponentTypes.Remove(typeof(T)); }); } private void UpdateComponents() { while (_componentActions.TryDequeue(out var action)) action(); } }