forked from Misaki/GhostEngine
257 lines
6.6 KiB
C#
257 lines
6.6 KiB
C#
#if false
|
|
using Ghost.Core;
|
|
using Misaki.HighPerformance.Collections;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Ghost.Entities;
|
|
|
|
public interface IManagedComponent;
|
|
public interface IManagedWrapper;
|
|
|
|
public readonly struct Managed<T> : IComponent, IManagedWrapper
|
|
where T : IManagedComponent
|
|
{
|
|
public readonly int id;
|
|
public readonly int generation;
|
|
|
|
internal Managed(int id, int generation)
|
|
{
|
|
this.id = id;
|
|
this.generation = generation;
|
|
}
|
|
}
|
|
|
|
public static class ManagedComponemtnID<T>
|
|
where T : IManagedComponent
|
|
{
|
|
public static readonly Identifier<IManagedComponent> value = ManagedComponentRegister.GetOrRegisterComponent<T>();
|
|
}
|
|
|
|
internal struct ManagedComponentInfo
|
|
{
|
|
public int id;
|
|
public bool isScriptComponent;
|
|
}
|
|
|
|
internal static class ManagedComponentRegister
|
|
{
|
|
private static readonly List<ManagedComponentInfo> s_registeredComponents = new();
|
|
private static readonly Dictionary<IntPtr, int> s_typeHandleToID = new();
|
|
private static readonly Dictionary<string, int> s_nameToRuntimeID = new();
|
|
#if DEBUG || GHOST_EDITOR
|
|
internal static readonly Dictionary<int, Type> s_runtimeIDToType = new();
|
|
#endif
|
|
|
|
public static Identifier<IManagedComponent> GetOrRegisterComponent<T>()
|
|
where T : IManagedComponent
|
|
{
|
|
var typeHandle = typeof(T).TypeHandle.Value;
|
|
|
|
lock (s_registeredComponents)
|
|
{
|
|
if (s_typeHandleToID.TryGetValue(typeHandle, out var existingID))
|
|
{
|
|
return existingID;
|
|
}
|
|
|
|
var newID = new Identifier<IManagedComponent>(s_registeredComponents.Count);
|
|
var stableName = typeof(T).FullName ?? typeof(T).Name;
|
|
var info = new ManagedComponentInfo
|
|
{
|
|
id = newID,
|
|
isScriptComponent = typeof(ScriptComponent).IsAssignableFrom(typeof(T)),
|
|
};
|
|
|
|
s_registeredComponents.Add(info);
|
|
|
|
s_typeHandleToID[typeHandle] = newID;
|
|
s_nameToRuntimeID[stableName] = newID;
|
|
#if DEBUG || GHOST_EDITOR
|
|
s_runtimeIDToType[newID.value] = typeof(T);
|
|
#endif
|
|
|
|
return newID;
|
|
}
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static Identifier<IManagedComponent> GetComponentID(Type type)
|
|
{
|
|
var typeHandle = type.TypeHandle.Value;
|
|
lock (s_registeredComponents)
|
|
{
|
|
if (s_typeHandleToID.TryGetValue(typeHandle, out var existingID))
|
|
{
|
|
return existingID;
|
|
}
|
|
}
|
|
|
|
return Identifier<IManagedComponent>.Invalid;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static ManagedComponentInfo GetComponentInfo(Identifier<IManagedComponent> typeId)
|
|
{
|
|
lock (s_registeredComponents)
|
|
{
|
|
return s_registeredComponents[typeId];
|
|
}
|
|
}
|
|
}
|
|
|
|
internal interface IManagedComponentStorage
|
|
{
|
|
public Identifier<IManagedComponent> TypeID { get; }
|
|
}
|
|
|
|
internal class ManagedComponentStorage<T> : IManagedComponentStorage
|
|
where T : IManagedComponent
|
|
{
|
|
private readonly SlotMap<T> _storage = new(16);
|
|
|
|
public Identifier<IManagedComponent> TypeID => ManagedComponemtnID<T>.value;
|
|
|
|
public Managed<T> Add(T component)
|
|
{
|
|
var id = _storage.Add(component, out var generation);
|
|
return new Managed<T>(id, generation);
|
|
}
|
|
|
|
public void Remove(Managed<T> managed)
|
|
{
|
|
_storage.Remove(managed.id, managed.generation);
|
|
}
|
|
|
|
public ref T GetComponentReference(Managed<T> managed)
|
|
{
|
|
return ref _storage.GetElementReferenceAt(managed.id, managed.generation, out _);
|
|
}
|
|
}
|
|
|
|
public abstract class ScriptComponent : IManagedComponent
|
|
{
|
|
internal World _world = null!;
|
|
internal Entity _entity;
|
|
|
|
public World World => _world;
|
|
public Entity Entity => _entity;
|
|
|
|
protected ref T GetComponent<T>()
|
|
where T : unmanaged, IComponent
|
|
{
|
|
return ref _world.EntityManager.GetComponent<T>(_entity);
|
|
}
|
|
|
|
public virtual void OnCreate()
|
|
{
|
|
}
|
|
|
|
public virtual void OnDestroy()
|
|
{
|
|
}
|
|
|
|
public virtual void OnEnable()
|
|
{
|
|
}
|
|
|
|
public virtual void OnDisable()
|
|
{
|
|
}
|
|
|
|
public virtual void Start()
|
|
{
|
|
}
|
|
|
|
public virtual void Update()
|
|
{
|
|
}
|
|
|
|
public virtual void FixedUpdate()
|
|
{
|
|
}
|
|
|
|
public virtual void LateUpdate()
|
|
{
|
|
}
|
|
}
|
|
|
|
public partial class EntityManager
|
|
{
|
|
private IManagedComponentStorage[] _storages;
|
|
|
|
internal IManagedComponentStorage[] Storages => _storages;
|
|
|
|
private ManagedComponentStorage<T> GetOrCreateManagedComponentStorage<T>()
|
|
where T : IManagedComponent
|
|
{
|
|
var id = ManagedComponemtnID<T>.value;
|
|
if (_storages == null || _storages.Length <= id.value)
|
|
{
|
|
Array.Resize(ref _storages, id.value + 1);
|
|
}
|
|
|
|
ref var storage = ref _storages[id.value];
|
|
storage ??= new ManagedComponentStorage<T>();
|
|
|
|
return (ManagedComponentStorage<T>)storage;
|
|
}
|
|
|
|
public Managed<T> AddManagedComponent<T>(Entity entity)
|
|
where T : IManagedComponent, new()
|
|
{
|
|
var instance = new T();
|
|
if (instance is ScriptComponent scriptComponent)
|
|
{
|
|
scriptComponent._world = _world;
|
|
scriptComponent._entity = entity;
|
|
scriptComponent.OnCreate();
|
|
}
|
|
|
|
var managed = GetOrCreateManagedComponentStorage<T>().Add(instance);
|
|
AddComponent(entity, managed);
|
|
|
|
return managed;
|
|
}
|
|
|
|
public bool RemoveManagedComponent<T>(Entity entity)
|
|
where T : IManagedComponent
|
|
{
|
|
ref var component = ref GetComponent<Managed<T>>(entity);
|
|
if (!Unsafe.IsNullRef(ref component))
|
|
{
|
|
var storage = GetOrCreateManagedComponentStorage<T>();
|
|
var componentRef = storage.GetComponentReference(component);
|
|
if (componentRef is ScriptComponent scriptComponent)
|
|
{
|
|
scriptComponent.OnDestroy();
|
|
}
|
|
|
|
RemoveComponent<Managed<T>>(entity);
|
|
storage.Remove(component);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public ref T GetManagedComponent<T>(Entity entity)
|
|
where T : IManagedComponent
|
|
{
|
|
ref var component = ref GetComponent<Managed<T>>(entity);
|
|
if (Unsafe.IsNullRef(ref component))
|
|
{
|
|
return ref Unsafe.NullRef<T>();
|
|
}
|
|
|
|
return ref GetOrCreateManagedComponentStorage<T>().GetComponentReference(component);
|
|
}
|
|
|
|
public ref T GetManagedComponent<T>(Managed<T> managedComponent)
|
|
where T : IManagedComponent
|
|
{
|
|
return ref GetOrCreateManagedComponentStorage<T>().GetComponentReference(managedComponent);
|
|
}
|
|
}
|
|
#endif
|