158 lines
3.4 KiB
C#
158 lines
3.4 KiB
C#
using System.Reflection;
|
|
using Engine.Scene.Component;
|
|
using Engine.Scene.Component.BuiltIn;
|
|
|
|
namespace Engine.Scene;
|
|
|
|
public sealed class GameObject : IUpdate, IRender
|
|
{
|
|
public Guid Id { get; } = Guid.NewGuid();
|
|
public Transform Transform { get; }
|
|
|
|
internal Scene? Scene { get; set; }
|
|
|
|
private readonly Queue<Action> _componentActions = new();
|
|
|
|
private readonly List<Component.Component> _components = [];
|
|
private readonly HashSet<Type> _addedComponentTypes = [];
|
|
|
|
public GameObject()
|
|
{
|
|
AddComponent<Transform>();
|
|
ProcessChanges();
|
|
|
|
Transform = GetComponent<Transform>()!;
|
|
}
|
|
|
|
public GameObject(Transform parTransform)
|
|
{
|
|
AddComponent(parTransform.Clone());
|
|
ProcessChanges();
|
|
|
|
Transform = GetComponent<Transform>()!;
|
|
}
|
|
|
|
public void Awake()
|
|
{
|
|
foreach (var component in _components)
|
|
{
|
|
component.Awake();
|
|
}
|
|
}
|
|
|
|
public void Start()
|
|
{
|
|
foreach (var component in _components)
|
|
{
|
|
component.Start();
|
|
}
|
|
}
|
|
|
|
public void Update(double parDeltaTime)
|
|
{
|
|
foreach (var component in _components)
|
|
{
|
|
component.Update(parDeltaTime);
|
|
}
|
|
}
|
|
|
|
public void Render()
|
|
{
|
|
foreach (var component in _components)
|
|
{
|
|
component.Render();
|
|
}
|
|
}
|
|
|
|
public void Destroy()
|
|
{
|
|
foreach (var component in _components)
|
|
{
|
|
component.Destroy();
|
|
}
|
|
}
|
|
|
|
public T? GetComponent<T>() where T : Component.Component
|
|
{
|
|
return !HasComponent<T>() ? null : _components.OfType<T>().First();
|
|
}
|
|
|
|
public void AddComponent<T>() where T : Component.Component, new()
|
|
{
|
|
var component = new T();
|
|
AddComponent(component);
|
|
}
|
|
|
|
public void AddComponent<T>(params object?[] parArgs) where T : Component.Component
|
|
{
|
|
var component = (T?)Activator.CreateInstance(
|
|
typeof(T),
|
|
BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance |
|
|
BindingFlags.OptionalParamBinding,
|
|
null,
|
|
parArgs,
|
|
null
|
|
);
|
|
|
|
if (component == null)
|
|
{
|
|
throw new InvalidOperationException($"Failed to create component of type {typeof(T)}");
|
|
}
|
|
|
|
AddComponent(component);
|
|
}
|
|
|
|
public void AddComponent<T>(T parComponent) where T : Component.Component
|
|
{
|
|
_componentActions.Enqueue(() =>
|
|
{
|
|
if (HasComponent<T>())
|
|
{
|
|
throw new ArgumentException($"GameObject already has component of type {typeof(T)}");
|
|
}
|
|
|
|
parComponent.GameObject = this;
|
|
_components.Add(parComponent);
|
|
_addedComponentTypes.Add(typeof(T).GetComponentBaseType());
|
|
});
|
|
}
|
|
|
|
public void RemoveComponent<T>() where T : Component.Component
|
|
{
|
|
if (typeof(T) == typeof(Transform))
|
|
{
|
|
throw new ArgumentException("GameObject cannot remove Transform component");
|
|
}
|
|
|
|
_componentActions.Enqueue(() =>
|
|
{
|
|
if (!HasComponent<T>())
|
|
{
|
|
throw new ArgumentException($"GameObject does not have component of type {typeof(T)}");
|
|
}
|
|
|
|
var component = GetComponent<T>();
|
|
if (component == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_components.Remove(component);
|
|
_addedComponentTypes.Remove(typeof(T));
|
|
});
|
|
}
|
|
|
|
public bool HasComponent<T>() where T : Component.Component
|
|
{
|
|
var baseType = typeof(T).GetComponentBaseType();
|
|
return _addedComponentTypes.Contains(baseType);
|
|
}
|
|
|
|
internal void ProcessChanges()
|
|
{
|
|
while (_componentActions.TryDequeue(out var action))
|
|
{
|
|
action();
|
|
}
|
|
}
|
|
} |