Skip to content

Instantly share code, notes, and snippets.

@dasannikov
Last active April 9, 2020 09:29
Show Gist options
  • Save dasannikov/c3c0c88091a3004108cf5d701a0ef0b2 to your computer and use it in GitHub Desktop.
Save dasannikov/c3c0c88091a3004108cf5d701a0ef0b2 to your computer and use it in GitHub Desktop.
using System;
using System.Reflection;
using Leopotam.Ecs;
using UnityEngine;
//-----------------------------------------------------------------------------
// Attributes
//-----------------------------------------------------------------------------
class EcsInjectToStatic : Attribute { }
class EcsRequireFilters : Attribute { }
//-----------------------------------------------------------------------------
// Inject EcsWorld and EcsFilters to all classes with attribute [EcsInjectToStatic]
//-----------------------------------------------------------------------------
sealed class RequireAndInjectEcsSystem : IEcsInitSystem, IEcsDestroySystem {
EcsWorld _world = null;
readonly Type _filterType = typeof(EcsFilter);
readonly Type _worldType = typeof(EcsWorld);
readonly Type _attributeInjectType = typeof(EcsInjectToStatic);
readonly Type _attributeRequireType = typeof(EcsRequireFilters);
void IEcsInitSystem.Init() => ScanAllTypesAndInject(false);
void IEcsDestroySystem.Destroy() => ScanAllTypesAndInject(true);
void ScanAllTypesAndInject(bool isDestroy) {
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach(var assembly in assemblies)
foreach(var type in assembly.GetTypes()) {
if(Attribute.IsDefined(type, _attributeInjectType))
Inject(type, isDestroy);
if(!isDestroy && Attribute.IsDefined(type, _attributeRequireType))
RequireFilter(type);
}
}
void RequireFilter(Type type) {
foreach(var f in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) {
if(f.FieldType.IsSubclassOf(_filterType))
_world.GetFilter(f.FieldType);
}
}
void Inject(Type type, bool isDestroy) {
foreach(var f in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)) {
// Inject filters
if(f.FieldType.IsSubclassOf(_filterType))
f.SetValue(type, isDestroy ? null : _world.GetFilter(f.FieldType));
// Inject world
if(f.FieldType == _worldType)
f.SetValue(type, isDestroy ? null : _world);
// Additional inject?
// ...
}
}
}
//-----------------------------------------------------------------------------
// Inject usage example. Inject to static members.
//-----------------------------------------------------------------------------
[EcsInjectToStatic]
class TestEcsStatic : MonoBehaviour {
static readonly EcsWorld _world = default;
static readonly EcsFilter<Item> _itemFilter = default;
void Start() {
Debug.Log(_itemFilter.IsEmpty());
Debug.Log(_world.GetStats().Filters);
}
}
//-----------------------------------------------------------------------------
// Require usage example.
//-----------------------------------------------------------------------------
[EcsRequireFilters]
class TestEcs : MonoBehaviour {
EcsFilter<Item> _itemFilter = default;
void Start() {
// You need EcsWorld to get filter
_itemFilter = EcsWorld.GetFilter(typeof(EcsFilter<Item>)) as EcsFilter<Item>;
Debug.Log(_itemFilter?.IsEmpty());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment