csharp: implement ecs world resources

This commit is contained in:
SeanOMik 2024-11-09 19:13:15 -05:00
parent 1d97046195
commit 3245b4dad4
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
9 changed files with 100 additions and 37 deletions

View File

@ -1,39 +1,10 @@
namespace ExampleWorld; namespace ExampleWorld;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ExampleWorld.wit.imports.lyra.api; using ExampleWorld.wit.imports.lyra.api;
using LyraApi;
using LyraApi.Ecs; using LyraApi.Ecs;
using LyraApi.Engine;
[StructLayout(LayoutKind.Sequential)] using LyraApi.Math;
struct Vec3(float x, float y, float z) : IComponent
{
/// <summary>
/// The X component.
/// </summary>
public float X { get; set; } = x;
/// <summary>
/// The Y component
/// </summary>
public float Y { get; set; } = y;
/// <summary>
/// The Z component
/// </summary>
public float Z { get; set; } = z;
public static string HostName => "Vec3";
public static ulong HostSize => (ulong)Marshal.SizeOf<Vec3>();
public static ulong HostAlignment => (ulong)MarshalUtils.AlignmentOf<Vec3>();
public static ulong TypeId => 4124409524;
public static object? TakeFromBytes(byte[] bytes)
{
byte[] taken = bytes.Take((int)HostSize).ToArray();
return MarshalUtils.FromBytes<Vec3>(taken);
}
}
public class ExampleWorldImpl : IExampleWorld public class ExampleWorldImpl : IExampleWorld
{ {
@ -47,6 +18,11 @@ public class ExampleWorldImpl : IExampleWorld
{ {
Console.WriteLine("C#: Found entity at ({0}, {1}, {2})", comp.X, comp.Y, comp.Z); Console.WriteLine("C#: Found entity at ({0}, {1}, {2})", comp.X, comp.Y, comp.Z);
} }
DeltaTime? dt = world.GetResource<DeltaTime>();
if (dt != null) {
Console.WriteLine($"C#: Delta time: {dt?.Seconds:0.##}");
}
} }
public static void OnUpdate(IEcs.EcsWorld gameWorld, IEcs.Entity owningEntity) public static void OnUpdate(IEcs.EcsWorld gameWorld, IEcs.Entity owningEntity)

View File

@ -0,0 +1,10 @@
using static ExampleWorld.wit.imports.lyra.api.IEcs;
namespace LyraApi.Ecs;
public interface IResource
{
public abstract static ulong TypeId { get; }
public abstract static object? FromWasmResult(WorldResourceResult result);
}

View File

@ -27,4 +27,10 @@ public class World(IEcs.EcsWorld world)
IEcs.EcsDynamicView dynamicView = Inner.View(infos); IEcs.EcsDynamicView dynamicView = Inner.View(infos);
return new ViewResult(comps, dynamicView).Get<T1>(); return new ViewResult(comps, dynamicView).Get<T1>();
} }
public T? GetResource<T>() where T : IResource
{
IEcs.WorldResourceResult result = Inner.GetResource(Utils.ToWasmTypeId(T.TypeId));
return (T?) T.FromWasmResult(result);
}
} }

View File

@ -0,0 +1,23 @@
using System.Runtime.InteropServices;
using LyraApi;
using LyraApi.Ecs;
using static ExampleWorld.wit.imports.lyra.api.IEcs;
namespace LyraApi.Engine;
[StructLayout(LayoutKind.Sequential)]
public struct DeltaTime : IResource {
public float Seconds;
public static ulong TypeId => 83716348954;
public static object? FromWasmResult(WorldResourceResult result)
{
return result.Tag switch
{
WorldResourceResult.NONE | WorldResourceResult.WASM_RESOURCE_REP => null,
WorldResourceResult.BYTES => MarshalUtils.FromBytes<DeltaTime>(result.AsBytes),
_ => null,
};
}
}

View File

@ -0,0 +1,32 @@
using System.Runtime.InteropServices;
using LyraApi.Ecs;
namespace LyraApi.Math;
[StructLayout(LayoutKind.Sequential)]
struct Vec3(float x, float y, float z) : IComponent
{
/// <summary>
/// The X component.
/// </summary>
public float X { get; set; } = x;
/// <summary>
/// The Y component
/// </summary>
public float Y { get; set; } = y;
/// <summary>
/// The Z component
/// </summary>
public float Z { get; set; } = z;
public static string HostName => "Vec3";
public static ulong HostSize => (ulong)Marshal.SizeOf<Vec3>();
public static ulong HostAlignment => (ulong)MarshalUtils.AlignmentOf<Vec3>();
public static ulong TypeId => 4124409524;
public static object? TakeFromBytes(byte[] bytes)
{
byte[] taken = bytes.Take((int)HostSize).ToArray();
return MarshalUtils.FromBytes<Vec3>(taken);
}
}

View File

@ -0,0 +1,8 @@
using static ExampleWorld.wit.imports.lyra.api.IEcs;
internal static class Utils {
public static WasmTypeId ToWasmTypeId(ulong typeId)
{
return new WasmTypeId((typeId, 0));
}
}

View File

@ -18,12 +18,12 @@
</PropertyGroup> </PropertyGroup>
<!-- Copy WIT files from LyraApi to lyra-api wit folder. --> <!-- Copy WIT files from LyraApi to lyra-api wit folder. -->
<!-- <Target Name="CopyFolderOnBuild" BeforeTargets="WitCompile_InvokeTool"> <Target Name="CopyFolderOnBuild" BeforeTargets="WitCompile_InvokeTool">
<ItemGroup> <ItemGroup>
<MyFiles Include="..\LyraApi\wit\**\*.wit" /> <MyFiles Include="..\..\rust\common-api\wit\**\*.wit" />
</ItemGroup> </ItemGroup>
<Copy SourceFiles="@(MyFiles)" DestinationFolder="wit\deps\lyraapi\%(RecursiveDir)" /> <Copy SourceFiles="@(MyFiles)" DestinationFolder="wit\deps\lyraapi\%(RecursiveDir)" />
</Target> --> </Target>
<!-- Remove bindgen of LyraApi WIT .--> <!-- Remove bindgen of LyraApi WIT .-->
<!-- <Target Name="RemoveBindgenLyraApi" AfterTargets="WitCompile_InvokeTool"> <!-- <Target Name="RemoveBindgenLyraApi" AfterTargets="WitCompile_InvokeTool">

View File

@ -37,6 +37,12 @@ interface ecs {
next: func() -> option<tuple<entity, list<u8>>>; next: func() -> option<tuple<entity, list<u8>>>;
} }
variant world-resource-result {
none,
wasm-resource-rep(u32),
bytes(list<u8>),
}
resource ecs-world { resource ecs-world {
constructor(); constructor();
@ -76,6 +82,8 @@ interface ecs {
/// Returns: A row of components serialized as bytes. The buffer is tighly packed. /// Returns: A row of components serialized as bytes. The buffer is tighly packed.
view-one: func(en: entity, component-infos: list<component-info>) -> option<list<u8>>; view-one: func(en: entity, component-infos: list<component-info>) -> option<list<u8>>;
get-resource: func(type-id: wasm-type-id) -> world-resource-result;
//with_system: func(stage: string, component-infos: list<component-info>, system: func(components: list<u8>)); //with_system: func(stage: string, component-infos: list<component-info>, system: func(components: list<u8>));
} }
} }

View File

@ -462,8 +462,8 @@ async fn main() -> wasmtime::Result<()> {
); );
// Load the component from disk // Load the component from disk
let bytes = std::fs::read("target/wasm32-wasip1/debug/witguest-component.wasm")?; //let bytes = std::fs::read("target/wasm32-wasip1/debug/witguest-component.wasm")?;
//let bytes = std::fs::read("guests/csharp/dotnet-guest-test/bin/Debug/net9.0/wasi-wasm/native/dotnet-guest-test.wasm")?; let bytes = std::fs::read("guests/csharp/dotnet-guest-test/bin/Debug/net9.0/wasi-wasm/native/dotnet-guest-test.wasm")?;
let component = wasmtime::component::Component::new(&engine, bytes)?; let component = wasmtime::component::Component::new(&engine, bytes)?;
let (script_en, (world_res_a, world_res_b)) = { let (script_en, (world_res_a, world_res_b)) = {