Ejemplo n.º 1
0
        // Public methods
        ///////////////////////////

        public static Action Create(Ecs.Internals ecs, MethodInfo systemInfo)
        {
            var systemName = $"{systemInfo.DeclaringType}.{systemInfo.Name}";
            var arguments  = systemInfo.GetParameters()
                             .Select(p => GetArgumentData(ecs, p))
                             .ToArray();

            if (arguments.Length == 0)
            {
                return(() => systemInfo.Invoke(null, null));
            }
            var resources = arguments
                            .Where(a => a.isResource)
                            .ToArray();
            var components = arguments
                             .Where(a => !a.isResource)
                             .ToArray();
            var src = default(string);

            if (components.Length > 0)
            {
                src = ForEachSource(ecs, arguments, resources, components);
            }
            else
            {
                src = ResourceOnlySource(ecs, resources);
            }
            var asmGen = new AssemblyGenerator();

            asmGen.ReferenceAssemblyByName("System");
            asmGen.ReferenceAssemblyByName("System.Collections");
            asmGen.ReferenceAssemblyByName("System.Reflection");
            asmGen.ReferenceAssemblyContainingType(typeof(Ecs));
            src = asmGen.Format(src);
            var startTime = TimeNow();

            var(assembly, errors) = asmGen.Generate(src);
            if (errors != null)
            {
                var sb = new System.Text.StringBuilder();
                sb.Append($"encountered error(s) compiling system runner for {systemName}");
                foreach (var error in errors)
                {
                    sb.Append($"\n  {error.Replace("\n", "\n  ")}");
                }
                var srcLines = src.Split("\n");
                for (var i = 0; i < srcLines.Length; i++)
                {
                    sb.Append($"\n{i+1}\t{srcLines[i]}");
                }
                throw new Exception(sb.ToString());
            }
            var runner   = assembly.GetType("Runner");
            var duration = TimeNow() - startTime;

            Console.WriteLine($"generated system runner for {systemName} in {duration}ms:\n  {src.Replace("\n", "\n  ")}");
            runner.GetMethod("Initialize").Invoke(null, new object[] { ecs, systemInfo });
            return((Action)runner.GetMethod("Run").CreateDelegate(typeof(Action)));
        }
Ejemplo n.º 2
0
        // Internal methods
        ///////////////////////////

        static string ForEachSource(
            Ecs.Internals ecs,
            ArgumentData[] arguments,
            ArgumentData[] resources,
            ArgumentData[] components
            )
        {
            return($@"
      using System;
      using System.Reflection;

      using static ArchetypeEcs;

      public delegate void SystemDelegate(
        {LinesFor(0, arguments.Length, ",\n", i => $"{arguments[i].type} {arguments[i].name}")}
      );

      public static class Runner {{

        static Ecs.Internals ecs;
        static SystemDelegate system;
        static EntityId[] componentIds;
        static EntityType entityType;

        public static void Initialize(Ecs.Internals ecsInstance, MethodInfo systemInfo) {{
          ecs = ecsInstance;
          system = (SystemDelegate)systemInfo.CreateDelegate(typeof(SystemDelegate));
          componentIds = new EntityId[]{{
          {LinesFor(0, components.Length, ",\n", i => $@"
            ecs.GetDataTypeReflected(typeof({components[i].baseType}))
          ")}
          }};
          entityType = new EntityType(componentIds);
        }}

        public static void Run() {{
          {LinesFor(0, resources.Length, "\n", i => {
            var refPrefix = resources[i].isReference ? "ref " : "";
            return $@"{refPrefix}var {resources[i].name}Resource = {refPrefix}ecs.GetResource<{resources[i].baseType}>();";
          })}