Files
GhostEngine/Ghost.Entities/Component.cs
Misaki 7cd881b7d4 Refactor project management and enhance architecture
Added a new static class `AssetsPath` for asset management.
Added a new icon file (`icon-256.ico`) for UI representation.
Added new package references to enhance functionality.
Added internals visibility attributes for better testing.
Added a new `EngineEditorViewModel` class for MVVM support.
Added a new `GameObject` class for component management.
Added a new `BitSet` class for efficient bit manipulation.
Added various utility classes to support the new entity system.

Changed the `ID` property in `ProjectInfo` to internal.
Changed the `AddProjectAsync` method to return the created `ProjectInfo`.
Changed the connection string retrieval method to use the new `Command` constant.
Changed the `DataPath` class to use `readonly` fields for folder paths.
Changed the `ActivationHandler` class to use new `DataPath` constants.
Changed the `OpenProjectPage` layout and interaction for better UI.

Updated the target framework to a newer version for compatibility.
Updated the `ProjectService` to use new constants from `DataPath`.
Updated the `World` class to improve entity management.

Refactored the `ProjectRepository` class to encapsulate SQL commands.
Refactored the `Transform` class to use properties for better encapsulation.
2025-04-05 16:07:53 +09:00

103 lines
2.5 KiB
C#

using Ghost.Entities.Helpers;
using Ghost.Entities.Registries;
using Misaki.HighPerformance.Unsafe.Collections;
using Misaki.HighPerformance.Unsafe.Helpers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Ghost.Entities;
public interface IComponent
{
}
[SkipLocalsInit]
internal readonly record struct ComponentData
{
public readonly int id;
public readonly int sizeInByte;
public ComponentData(int id, int sizeInByte)
{
this.id = id;
this.sizeInByte = sizeInByte;
}
}
internal static class Component
{
public static unsafe UnsafeArray<int> ToLookupArray(Span<ComponentData> datas, Allocator allocator)
{
var max = 0;
foreach (var data in datas)
{
var componentId = data.id;
if (componentId >= max)
{
max = componentId;
}
}
// Create lookup table where the component ID points to the component index.
var array = new UnsafeArray<int>(max + 1, allocator);
array.AsSpan().Fill(-1);
for (var index = 0; index < datas.Length; index++)
{
ref var type = ref datas[index];
var componentId = type.id;
array[componentId] = index;
}
return array;
}
public static int GetHashCode(Span<ComponentData> components)
{
// Search for the highest id to determine how much uints we need for the stack.
var highestId = 0;
foreach (ref var cmp in components)
{
if (cmp.id > highestId)
{
highestId = cmp.id;
}
}
// Allocate the stack and set bits to replicate a bitset
var length = BitSet.RequiredLength(highestId + 1);
Span<uint> stack = stackalloc uint[length];
var spanBitSet = new SpanBitSet(stack);
foreach (ref var type in components)
{
var x = type.id;
spanBitSet.SetBit(x);
}
return GetHashCode(stack);
}
public static int GetHashCode(Span<uint> span)
{
var hashCode = new HashCode();
hashCode.AddBytes(MemoryMarshal.AsBytes(span));
return hashCode.ToHashCode();
}
}
internal static class Component<T>
where T : unmanaged, IComponent
{
public static readonly ComponentData data;
public static readonly Signature signature;
static Component()
{
data = ComponentRegistry.GetOrAdd<T>();
signature = new Signature(data);
}
}