Skip to content

Commit

Permalink
add DynBundle
Browse files Browse the repository at this point in the history
  • Loading branch information
sicusa committed Mar 25, 2024
1 parent f383023 commit 517db23
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
38 changes: 38 additions & 0 deletions Sia.Examples/Example5_ComponentBundle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,33 @@ public static EntityRef Create(World world)
.AddBundle(transform)
.AddBundle(gameObject);
}

public static EntityRef CreateWithDynBundle(World world)
{
var transform = new Transform {
Position = new Position {
Value = Vector3.Zero
},
Rotation = new Rotation {
Value = Quaternion.Identity
},
Scale = new Scale {
Value = Vector3.One
}
};
var gameObject = new GameObject {
Id = new Sid<ObjectId>(0),
Name = "Test"
};

return world.CreateInArrayHost()
.AddBundle(
new DynBundle()
.Add(new HP(100))
.AddBundle(transform)
.AddBundle(gameObject)
.Remove<Scale>());
}
}
}

Expand All @@ -60,11 +87,22 @@ public static partial class Example5_ComponentBundle
public static void Run(World world)
{
var entity = ComponentBundle.TestObject.Create(world);
Console.WriteLine("Entity 1:");
Console.WriteLine(entity.Get<ComponentBundle.Name>().Value);
Console.WriteLine(entity.Get<ComponentBundle.HP>().Value);
Console.WriteLine(entity.Get<ComponentBundle.Position>().Value);
Console.WriteLine(entity.Get<ComponentBundle.Rotation>().Value);
Console.WriteLine(entity.Get<ComponentBundle.Scale>().Value);

Console.WriteLine();

var entity2 = ComponentBundle.TestObject.CreateWithDynBundle(world);
Console.WriteLine("Entity 2:");
Console.WriteLine(entity2.Get<ComponentBundle.Name>().Value);
Console.WriteLine(entity2.Get<ComponentBundle.HP>().Value);
Console.WriteLine(entity2.Get<ComponentBundle.Position>().Value);
Console.WriteLine(entity2.Get<ComponentBundle.Rotation>().Value);
Console.WriteLine(entity2.Contains<ComponentBundle.Scale>());
}
}
}
101 changes: 101 additions & 0 deletions Sia/Components/DynBundle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
namespace Sia;

public class DynBundle : IBundle
{
private class BundleImpl<THList>(in THList list) : IBundle
where THList : IHList
{
private readonly THList _list = list;

public void ToHList(IGenericHandler<IHList> handler)
=> handler.Handle(_list);
}

#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type

private unsafe struct BundleCreator(IBundle* result)
: IGenericHandler<IHList>
{
public readonly void Handle<T>(in T value) where T : IHList
=> *result = new BundleImpl<T>(value);
}

private unsafe struct ComponentAdder<TComponent>(IBundle* result, in TComponent initial)
: IGenericHandler<IHList>
{
private readonly TComponent _initial = initial;

public readonly void Handle<T>(in T value)
where T : IHList
=> *result = new BundleImpl<HList<TComponent, T>>(HList.Cons(_initial, value));
}

private unsafe struct ComponentConcater<THList>(IBundle* result, in THList list)
: IGenericHandler<IHList>
where THList : IHList
{
private readonly THList _list = list;

public readonly void Handle<T>(in T value)
where T : IHList
=> _list.Concat(value, new BundleCreator(result));
}

private unsafe struct BundleAdder(IBundle* result) : IGenericHandler<IHList>
{
public readonly void Handle<T>(in T value)
where T : IHList
=> (*result).ToHList(new ComponentConcater<T>(result, value));
}

private unsafe struct ComponentRemover<TComponent>(IBundle* result)
: IGenericHandler<IHList>
{
public readonly void Handle<T>(in T value)
where T : IHList
=> value.Remove(TypeProxy<TComponent>.Default, new BundleCreator(result));
}

private IBundle _bundleImpl = new BundleImpl<EmptyHList>(EmptyHList.Default);

public DynBundle Add<TComponent>() => Add<TComponent>(default!);

public unsafe DynBundle Add<TComponent>(in TComponent initial)
{
fixed (IBundle* bundlePtr = &_bundleImpl) {
_bundleImpl.ToHList(new ComponentAdder<TComponent>(bundlePtr, initial));
}
return this;
}

public unsafe DynBundle AddMany<THList>(in THList list)
where THList : IHList
{
fixed (IBundle* bundlePtr = &_bundleImpl) {
_bundleImpl.ToHList(new ComponentConcater<THList>(bundlePtr, list));
}
return this;
}

public unsafe DynBundle AddBundle<TBundle>(in TBundle bundle)
where TBundle : IBundle
{
fixed (IBundle* bundlePtr = &_bundleImpl) {
bundle.ToHList(new BundleAdder(bundlePtr));
}
return this;
}

public unsafe DynBundle Remove<TComponent>()
{
fixed (IBundle* bundlePtr = &_bundleImpl) {
_bundleImpl.ToHList(new ComponentRemover<TComponent>(bundlePtr));
}
return this;
}

#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type

public void ToHList(IGenericHandler<IHList> handler)
=> _bundleImpl.ToHList(handler);
}

0 comments on commit 517db23

Please sign in to comment.