You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.9 KiB
117 lines
3.9 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Runtime.CompilerServices; |
|
using gaemstone.ECS.Utility; |
|
using static flecs_hub.flecs; |
|
|
|
namespace gaemstone.ECS.Internal; |
|
|
|
public unsafe static class EntityAccess |
|
{ |
|
public static bool IsValid(World world, Entity entity) |
|
=> ecs_is_valid(world, entity); |
|
public static bool IsAlive(World world, Entity entity) |
|
=> ecs_is_alive(world, entity); |
|
|
|
public static string? GetName(World world, Entity entity) |
|
=> ecs_get_name(world, entity).FlecsToString()!; |
|
public static void SetName(World world, Entity entity, string? value) |
|
{ using var alloc = TempAllocator.Use(); ecs_set_name(world, entity, alloc.AllocateCString(value)); } |
|
|
|
public static string? GetSymbol(World world, Entity entity) |
|
=> ecs_get_symbol(world, entity).FlecsToString()!; |
|
public static void SetSymbol(World world, Entity entity, string? value) |
|
{ using var alloc = TempAllocator.Use(); ecs_set_symbol(world, entity, alloc.AllocateCString(value)); } |
|
|
|
|
|
public static void Add(World world, Entity entity, Id id) |
|
=> ecs_add_id(world, entity, id); |
|
public static void Remove(World world, Entity entity, Id id) |
|
=> ecs_remove_id(world, entity, id); |
|
public static bool Has(World world, Entity entity, Id id) |
|
=> ecs_has_id(world, entity, id); |
|
|
|
|
|
public static IEnumerable<Entity> GetTargets(World world, Entity entity, Entity relation) |
|
{ |
|
Entity GetTarget(int index) |
|
=> new(ecs_get_target(world, entity, relation, index)); |
|
for (var i = 0; GetTarget(i) is { IsSome: true } target; i++) |
|
yield return target; |
|
} |
|
|
|
|
|
public static T? GetOrNull<T>(World world, Entity entity, Id id) |
|
where T : unmanaged |
|
{ |
|
var ptr = ecs_get_id(world, entity, id); |
|
return (ptr != null) ? Unsafe.Read<T>(ptr) : null; |
|
} |
|
|
|
public static T? GetOrNull<T>(World world, Entity entity, Id id, T _ = null!) |
|
where T : class |
|
{ |
|
var ptr = ecs_get_id(world, entity, id); |
|
return (T?)Unsafe.Read<ReferenceHandle>(ptr).Target; |
|
} |
|
|
|
public static T GetOrThrow<T>(World world, Entity entity, Id id) |
|
{ |
|
var ptr = ecs_get_id(world, entity, id); |
|
if (ptr == null) throw new ComponentNotFoundException($"Component {id} not found on {entity}"); |
|
if (typeof(T).IsValueType) return Unsafe.Read<T>(ptr); |
|
else return (T)Unsafe.Read<ReferenceHandle>(ptr).Target!; |
|
} |
|
|
|
public static ref T GetMut<T>(World world, Entity entity, Id id) |
|
where T : unmanaged |
|
{ |
|
var ptr = ecs_get_mut_id(world, entity, id); |
|
// NOTE: Value is added if it doesn't exist on the entity. |
|
return ref Unsafe.AsRef<T>(ptr); |
|
} |
|
|
|
public static ref T GetRefOrNull<T>(World world, Entity entity, Id id) |
|
where T : unmanaged |
|
{ |
|
var @ref = ecs_ref_init_id(world, entity, id); |
|
var ptr = ecs_ref_get_id(world, &@ref, id); |
|
return ref (ptr != null) ? ref Unsafe.AsRef<T>(ptr) |
|
: ref Unsafe.NullRef<T>(); |
|
} |
|
|
|
public static ref T GetRefOrThrow<T>(World world, Entity entity, Id id) |
|
where T : unmanaged |
|
{ |
|
ref var ptr = ref GetRefOrNull<T>(world, entity, id); |
|
if (Unsafe.IsNullRef(ref ptr)) throw new Exception( |
|
$"Component {typeof(T)} not found on {entity}"); |
|
return ref ptr; |
|
} |
|
|
|
|
|
public static void Modified(World world, Entity entity, Id id) |
|
=> ecs_modified_id(world, entity, id); |
|
|
|
public static Entity Set<T>(World world, Entity entity, Id id, in T value) |
|
where T : unmanaged |
|
{ |
|
var size = (ulong)Unsafe.SizeOf<T>(); |
|
fixed (T* ptr = &value) |
|
if (ecs_set_id(world, entity, id, size, ptr).Data == 0) |
|
throw new InvalidOperationException(); |
|
return entity; |
|
} |
|
|
|
public static Entity Set<T>(World world, Entity entity, Id id, T value) |
|
where T : class |
|
{ |
|
if (value == null) throw new ArgumentNullException(nameof(value)); |
|
var size = (ulong)sizeof(ReferenceHandle); |
|
// Dispose entity handle afterwards, since Flecs clones it. |
|
using var handle = ReferenceHandle.Alloc(value); |
|
if (ecs_set_id(world, entity, id, size, &handle).Data == 0) |
|
throw new InvalidOperationException(); |
|
return entity; |
|
} |
|
}
|
|
|