|
|
|
using System;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Reflection;
|
|
|
|
using gaemstone.Flecs;
|
|
|
|
using gaemstone.Utility;
|
|
|
|
using gaemstone.Utility.IL;
|
|
|
|
|
|
|
|
namespace gaemstone.ECS;
|
|
|
|
|
|
|
|
[AttributeUsage(AttributeTargets.Method)]
|
|
|
|
public class SystemAttribute : Attribute
|
|
|
|
{
|
|
|
|
public Type Phase { get; }
|
|
|
|
public SystemAttribute() : this(typeof(SystemPhase.OnUpdate)) { }
|
|
|
|
internal SystemAttribute(Type phase) => Phase = phase; // Use generic type instead.
|
|
|
|
}
|
|
|
|
public class SystemAttribute<TPhase> : SystemAttribute
|
|
|
|
{ public SystemAttribute() : base(typeof(TPhase)) { } }
|
|
|
|
|
|
|
|
[AttributeUsage(AttributeTargets.Method)]
|
|
|
|
public class ExpressionAttribute : Attribute
|
|
|
|
{
|
|
|
|
public string Value { get; }
|
|
|
|
public ExpressionAttribute(string value) => Value = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static class SystemExtensions
|
|
|
|
{
|
|
|
|
public static EntityRef InitSystem(this World world, Delegate action)
|
|
|
|
{
|
|
|
|
var attr = action.Method.Get<SystemAttribute>();
|
|
|
|
var expr = action.Method.Get<ExpressionAttribute>()?.Value;
|
|
|
|
|
|
|
|
QueryDesc query;
|
|
|
|
if (action is Action<Iterator> callback) {
|
|
|
|
query = new(expr ?? throw new ArgumentException(
|
|
|
|
"System must specify ExpressionAttribute", nameof(action)));
|
|
|
|
} else {
|
|
|
|
var gen = IterActionGenerator.GetOrBuild(world, action.Method);
|
|
|
|
query = (expr != null) ? new(expr) : new(gen.Terms.ToArray());
|
|
|
|
callback = iter => gen.RunWithTryCatch(action.Target, iter);
|
|
|
|
}
|
|
|
|
|
|
|
|
var phase = world.LookupByTypeOrThrow(attr?.Phase ?? typeof(SystemPhase.OnUpdate));
|
|
|
|
return world.New(action.Method.Name).Build().InitSystem(phase, query, callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static EntityRef InitSystem(this World world,
|
|
|
|
object? instance, MethodInfo method)
|
|
|
|
{
|
|
|
|
var attr = method.Get<SystemAttribute>();
|
|
|
|
var expr = method.Get<ExpressionAttribute>()?.Value;
|
|
|
|
|
|
|
|
QueryDesc query;
|
|
|
|
Action<Iterator> callback;
|
|
|
|
var param = method.GetParameters();
|
|
|
|
if ((param.Length == 1) && (param[0].ParameterType == typeof(Iterator))) {
|
|
|
|
query = new(expr ?? throw new ArgumentException(
|
|
|
|
"System must specify ExpressionAttribute", nameof(method)));
|
|
|
|
callback = (Action<Iterator>)Delegate.CreateDelegate(typeof(Action<Iterator>), instance, method);
|
|
|
|
} else {
|
|
|
|
var gen = IterActionGenerator.GetOrBuild(world, method);
|
|
|
|
query = (expr != null) ? new(expr) : new(gen.Terms.ToArray());
|
|
|
|
callback = iter => gen.RunWithTryCatch(instance, iter);
|
|
|
|
}
|
|
|
|
|
|
|
|
var phase = world.LookupByTypeOrThrow(attr?.Phase ?? typeof(SystemPhase.OnUpdate));
|
|
|
|
return world.New(method.Name).Build().InitSystem(phase, query, callback);
|
|
|
|
}
|
|
|
|
}
|