using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using gaemstone.ECS; using gaemstone.Utility; using static flecs_hub.flecs; namespace gaemstone.Flecs; [Module, Path("/flecs/doc")] public static class Doc { [Tag] public struct Brief { } [Tag] public struct Detail { } [Tag] public struct Link { } [Tag] public struct Color { } [Relation, Component] public struct Description { internal unsafe void* Value; public override string? ToString() { unsafe { return Marshal.PtrToStringUTF8((nint)Value); } } public static implicit operator string?(Description desc) => desc.ToString(); } } public static unsafe class DocExtensions { private static EntityRef Set(EntityRef entity, string? value) { var world = entity.World; var descEntity = world.LookupByTypeOrThrow(); var docEntity = world.LookupByTypeOrThrow(); var id = Identifier.Pair(descEntity, docEntity); var has = entity.Has(id); var alloc = GlobalHeapAllocator.Instance; if (value != null) { var ptr = ecs_get_mut_id(world, entity, id); ref var desc = ref Unsafe.AsRef(ptr); // FIXME: Why does freeing these cause crashes? // if (has) alloc.Free((nint)desc.Value); // Free previous value. desc.Value = (void*)(nint)alloc.AllocateCString(value); } else if (has) { // var @ref = ecs_ref_init_id(world, entity, id); // var ptr = ecs_ref_get_id(world, &@ref, id); // var desc = Unsafe.AsRef(ptr); // alloc.Free((nint)desc.Value); // Free previous value. entity.Remove(id); } return entity; } public static string? GetDocName(this EntityRef entity, bool fallbackToEntityName = true) => fallbackToEntityName || entity.Has() ? ecs_doc_get_name(entity.World, entity).FlecsToString() : null; public static EntityRef SetDocName(this EntityRef entity, string? value) => Set(entity, value); public static string? GetDocBrief(this EntityRef entity) => ecs_doc_get_brief(entity.World, entity).FlecsToString()!; public static EntityRef SetDocBrief(this EntityRef entity, string? value) => Set(entity, value); public static string? GetDocDetail(this EntityRef entity) => ecs_doc_get_detail(entity.World, entity).FlecsToString()!; public static EntityRef SetDocDetail(this EntityRef entity, string? value) => Set(entity, value); public static string? GetDocLink(this EntityRef entity) => ecs_doc_get_link(entity.World, entity).FlecsToString()!; public static EntityRef SetDocLink(this EntityRef entity, string? value) => Set(entity, value); public static string? GetDocColor(this EntityRef entity) => ecs_doc_get_color(entity.World, entity).FlecsToString()!; public static EntityRef SetDocColor(this EntityRef entity, string? value) => Set(entity, value); }