/// <summary> /// Injects EcsWorld / EcsFilter fields to IEcsSystem. /// </summary> /// <param name="system">System to scan for injection.</param> /// <param name="world">EcsWorld instance to inject.</param> public static void Inject(IEcsSystem system, EcsWorld world) { var systemType = system.GetType(); if (!Attribute.IsDefined(systemType, typeof(EcsInjectAttribute))) { return; } var worldType = world.GetType(); var filterType = typeof(EcsFilter); foreach (var f in systemType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { // EcsWorld if (f.FieldType.IsAssignableFrom(worldType) && !f.IsStatic) { f.SetValue(system, world); continue; } // EcsFilter Internals.EcsHelpers.Assert(f.FieldType != filterType, string.Format("Cant use EcsFilter type at \"{0}\" system for dependency injection, use generic version instead", system)); if (f.FieldType.IsSubclassOf(filterType) && !f.IsStatic) { f.SetValue(system, world.GetFilter(f.FieldType)); } } }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public EcsSystems Add(IEcsSystem system) { #if DEBUG if (system == null) { throw new ArgumentNullException(); } #endif EcsInjections.Inject(_world, system); var preInitSystem = system as IEcsPreInitSystem; if (preInitSystem != null) { _preInitSystems.Add(preInitSystem); } var initSystem = system as IEcsInitSystem; if (initSystem != null) { _initSystems.Add(initSystem); } var runSystem = system as IEcsRunSystem; if (runSystem != null) { if (_runSystemsCount == _runSystems.Length) { var newRunSystems = new IEcsRunSystem[_runSystemsCount << 1]; Array.Copy(_runSystems, 0, newRunSystems, 0, _runSystemsCount); _runSystems = newRunSystems; } _runSystems[_runSystemsCount++] = runSystem; } return(this); }
public EcsSystem Add(IEcsSystem system) { var initSystem = system as IEcsInitSystem; if (initSystem != null) { if (_initSystemCount == _initSystems.Length) { Array.Resize(ref _initSystems, _initSystemCount << 1); } _initSystems[_initSystemCount++] = initSystem; } var runSystem = system as IEcsRunSystem; if (runSystem != null) { if (_runSystemCount == _runSystems.Length) { Array.Resize(ref _runSystems, _runSystemCount << 1); } _runSystems[_runSystemCount++] = runSystem; } return(this); }
/// <summary> /// Listens for when a property is changed and ensures that the subscription is properly disposed when the system disposes or when the component disposes. /// </summary> /// <typeparam name="TComponentType"></typeparam> /// <typeparam name="TPropertyType"></typeparam> /// <param name="system">This system to install this listner on, it will get disposed with this one.</param> /// <param name="select">A selector for the property observable on TComponentType that you wish to listen for.</param> /// <param name="handler">The method that is invoked when the property changes.</param> /// <param name="getImmediateValue">The lambda method for retreiving the primtive value, if this is not null, it will immedietly invoke the handler with this value.</param> /// <param name="onlyWhenChanged">Only invoke the method when the value actually changes rather than when it is set.</param> public static void PropertyChangedEvent <TComponentType, TPropertyType>(this IEcsSystem system, Func <TComponentType, IObservable <PropertyChangedEvent <TPropertyType> > > select, Action <TComponentType, PropertyChangedEvent <TPropertyType> > handler, Func <TComponentType, TPropertyType> getImmediateValue = null, bool onlyWhenChanged = false) where TComponentType : class, IEcsComponent { if (onlyWhenChanged) { system.OnComponentCreated <TComponentType>().Subscribe(_ => { select(_).Where(p => !Equals(p.PreviousValue, p.CurrentValue)).Subscribe(v => handler(_, v)).DisposeWith(_).DisposeWith(system); if (getImmediateValue != null) { handler(_, new PropertyChangedEvent <TPropertyType>() { CurrentValue = getImmediateValue(_) }); } }).DisposeWith(system); } else { system.OnComponentCreated <TComponentType>().Subscribe(_ => { select(_).Subscribe(v => handler(_, v)).DisposeWith(_).DisposeWith(system); if (getImmediateValue != null) { handler(_, new PropertyChangedEvent <TPropertyType>() { CurrentValue = getImmediateValue(_) }); } }).DisposeWith(system); } }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public EcsSystems Add(IEcsSystem system) { #if DEBUG if (system == null) { throw new ArgumentNullException(); } #endif #if !LEOECS_DISABLE_INJECT Internals.EcsInjections.Inject(_world, system); #endif var preInitSystem = system as IEcsPreInitSystem; if (preInitSystem != null) { _preInitSystems.Add(preInitSystem); } var initSystem = system as IEcsInitSystem; if (initSystem != null) { _initSystems.Add(initSystem); } var runSystem = system as IEcsRunSystem; if (runSystem != null) { if (_runSystemsCount == _runSystems.Length) { Array.Resize(ref _runSystems, _runSystemsCount << 1); } _runSystems[_runSystemsCount++] = runSystem; } return(this); }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public EcsSystems Add(IEcsSystem system, string namedRunSystem = null) { #if DEBUG if (system == null) { throw new Exception("System is null."); } if (_inited) { throw new Exception("Cant add system after initialization."); } if (_destroyed) { throw new Exception("Cant touch after destroy."); } if (!string.IsNullOrEmpty(namedRunSystem) && !(system is IEcsRunSystem)) { throw new Exception("Cant name non-IEcsRunSystem."); } #endif _allSystems.Add(system); if (system is IEcsRunSystem) { if (namedRunSystem != null) { _namedRunSystems[namedRunSystem.GetHashCode()] = _runSystems.Count; } _runSystems.Add(new EcsSystemsRunItem() { Active = true, System = (IEcsRunSystem)system }); } return(this); }
/// <summary> /// Listens for when a property is changed and ensures that the subscription is properly disposed when the system disposes or when the component disposes. /// </summary> /// <typeparam name="TComponentType"></typeparam> /// <typeparam name="TPropertyType"></typeparam> /// <param name="system">This system to install this listner on, it will get disposed with this one.</param> /// <param name="select">A selector for the property observable on TComponentType that you wish to listen for.</param> /// <param name="handler">The method that is invoked when the property changes.</param> /// <param name="getImmediateValue">The lambda method for retreiving the primtive value, if this is not null, it will immedietly invoke the handler with this value.</param> /// <param name="onlyWhenChanged">Only invoke the method when the value actually changes rather than when it is set.</param> public static void PropertyChanged <TComponentType, TPropertyType>(this IEcsSystem system, Func <TComponentType, IObservable <TPropertyType> > select, Action <TComponentType, TPropertyType> handler, Func <TComponentType, TPropertyType> getImmediateValue = null, bool onlyWhenChanged = false) where TComponentType : class, IEcsComponent { if (onlyWhenChanged) { system.OnComponentCreated <TComponentType>().DistinctUntilChanged().Subscribe(_ => { select(_).Subscribe(v => handler(_, v)).DisposeWith(_).DisposeWith(system); if (getImmediateValue != null) { handler(_, getImmediateValue(_)); } }).DisposeWith(system); } else { system.OnComponentCreated <TComponentType>().Subscribe(_ => { select(_).Subscribe(v => handler(_, v)).DisposeWith(_).DisposeWith(system); if (getImmediateValue != null) { handler(_, getImmediateValue(_)); } }).DisposeWith(system); } }
public EcsSystems Add(IEcsSystem system) { _allSystems.Add(system); if (system is IEcsRunSystem) { _runSystemsCount++; } return(this); }
public EcsEngine AddSystem(IEcsSystem system) { if (system.Init()) { _systemPool.Add(system); } return(this); }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public EcsWorld AddSystem(IEcsSystem system) { if (_inited) { throw new Exception("Already initialized, cant add new system."); } _allSystems.Add(system); return(this); }
public void RegisterDrawSystem(IEcsSystem system) { if (!drawSystems.Contains(system)) { drawSystems.Add(system); } else { throw new AlreadyRegisteredSystemException("This " + system.GetType() + " is already registered"); } }
/// <summary> /// Listens for when a Reactive Collection's item has been removed, and ensures that the subscription properly disposed when the system disposes or when the component disposes. /// </summary> /// <typeparam name="TComponentType"></typeparam> /// <typeparam name="TPropertyType"></typeparam> /// <param name="system">This system to install this listner on, it will get disposed with this one.</param> /// <param name="select">The ReactiveCollection selector.</param> /// <param name="handler">The method that is invoked when an item is added to the collection</param> public static void CollectionItemRemoved <TComponentType, TPropertyType>(this IEcsSystem system, Func <TComponentType, ReactiveCollection <TPropertyType> > select, Action <TComponentType, TPropertyType> handler) where TComponentType : class, IEcsComponent { system.OnComponentCreated <TComponentType>().Subscribe(_ => { select(_).ObserveRemove().Subscribe(v => handler(_, v.Value)).DisposeWith(_).DisposeWith(system); }).DisposeWith(system); }
static bool InjectShared(FieldInfo fieldInfo, IEcsSystem system, object shared, Type sharedType) { if (shared != null && Attribute.IsDefined(fieldInfo, SharedAttrType)) { if (fieldInfo.FieldType.IsAssignableFrom(sharedType)) { fieldInfo.SetValue(system, shared); } return(true); } return(false); }
static bool InjectWorld(FieldInfo fieldInfo, IEcsSystem system, EcsSystems systems) { if (fieldInfo.FieldType == WorldType) { if (Attribute.IsDefined(fieldInfo, WorldAttrType)) { var worldAttr = (EcsWorldAttribute)Attribute.GetCustomAttribute(fieldInfo, WorldAttrType); fieldInfo.SetValue(system, systems.GetWorld(worldAttr.World)); } return(true); } return(false); }
static bool InjectPool(FieldInfo fieldInfo, IEcsSystem system, EcsSystems systems) { if (fieldInfo.FieldType.IsGenericType && fieldInfo.FieldType.GetGenericTypeDefinition() == PoolType) { if (Attribute.IsDefined(fieldInfo, PoolAttrType)) { var poolAttr = (EcsPoolAttribute)Attribute.GetCustomAttribute(fieldInfo, PoolAttrType); var world = systems.GetWorld(poolAttr.World); var componentTypes = fieldInfo.FieldType.GetGenericArguments(); fieldInfo.SetValue(system, GetGenericGetPoolMethod(componentTypes[0]).Invoke(world, null)); } return(true); } return(false); }
/// <summary> /// Injects EcsWorld / EcsFilter fields to IEcsSystem. /// </summary> /// <param name="system">System to scan for injection.</param> /// <param name="world">EcsWorld instance to inject.</param> public static void Inject(IEcsSystem system, EcsWorld world, System.Collections.Generic.Dictionary <Type, object> injections) { var systemType = system.GetType(); if (!Attribute.IsDefined(systemType, typeof(EcsInjectAttribute))) { return; } var worldType = world.GetType(); var filterType = typeof(EcsFilter); var ignoreType = typeof(EcsIgnoreInjectAttribute); foreach (var f in systemType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { // skip fields with [EcsIgnoreInject] attribute. if (Attribute.IsDefined(f, ignoreType)) { continue; } // EcsWorld if (f.FieldType.IsAssignableFrom(worldType) && !f.IsStatic) { f.SetValue(system, world); continue; } // EcsFilter #if DEBUG if (f.FieldType == filterType) { throw new Exception(string.Format("Cant use EcsFilter type at \"{0}\" system for dependency injection, use generic version instead", system)); } #endif if (f.FieldType.IsSubclassOf(filterType) && !f.IsStatic) { f.SetValue(system, world.GetFilter(f.FieldType)); continue; } // Other injections. foreach (var pair in injections) { if (f.FieldType.IsAssignableFrom(pair.Key) && !f.IsStatic) { f.SetValue(system, pair.Value); break; } } } }
static bool InjectCustomData(FieldInfo fieldInfo, IEcsSystem system, object[] injects) { if (injects.Length > 0 && Attribute.IsDefined(fieldInfo, InjectAttrType)) { foreach (var inject in injects) { if (fieldInfo.FieldType.IsInstanceOfType(inject)) { fieldInfo.SetValue(system, inject); break; } } return(true); } return(false); }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public EcsSystems Add(IEcsSystem system) { #if DEBUG if (system == null) { throw new ArgumentNullException("system"); } #endif #if !LEOECS_DISABLE_INJECT if (_injectSystemsCount == _injectSystems.Length) { Array.Resize(ref _injectSystems, _injectSystemsCount << 1); } _injectSystems[_injectSystemsCount++] = system; #endif var preInitSystem = system as IEcsPreInitSystem; if (preInitSystem != null) { if (_preInitSystemsCount == _preInitSystems.Length) { Array.Resize(ref _preInitSystems, _preInitSystemsCount << 1); } _preInitSystems[_preInitSystemsCount++] = preInitSystem; } var initSystem = system as IEcsInitSystem; if (initSystem != null) { if (_initSystemsCount == _initSystems.Length) { Array.Resize(ref _initSystems, _initSystemsCount << 1); } _initSystems[_initSystemsCount++] = initSystem; } var runSystem = system as IEcsRunSystem; if (runSystem != null) { if (_runSystemsCount == _runSystems.Length) { Array.Resize(ref _runSystems, _runSystemsCount << 1); } _runSystems[_runSystemsCount++] = runSystem; } return(this); }
public int GetAllSystems(ref IEcsSystem[] list) { var itemsCount = _allSystems.Count; if (itemsCount == 0) { return(0); } if (list == null || list.Length < itemsCount) { list = new IEcsSystem[_allSystems.Capacity]; } for (int i = 0, iMax = itemsCount; i < iMax; i++) { list[i] = _allSystems[i]; } return(itemsCount); }
/// <summary> /// Listens for when a property is changed and ensures that the subscription is properly disposed when the system disposes or when the component disposes. /// </summary> /// <typeparam name="TComponentType"></typeparam> /// <typeparam name="TPropertyType"></typeparam> /// <param name="system">This system to install this listner on, it will get disposed with this one.</param> /// <param name="select">A selector for the property observable on TComponentType that you wish to listen for.</param> /// <param name="handler">The method that is invoked when the property changes.</param> /// <param name="getImmediateValue">The lambda method for retreiving the primtive value, if this is not null, it will immedietly invoke the handler with this value.</param> /// <param name="onlyWhenChanged">Only invoke the method when the value actually changes rather than when it is set.</param> public static void PropertyChangedEvent <TComponentType, TPropertyType>(this IEcsSystem system, Func <TComponentType, IObservable <PropertyChangedEvent <TPropertyType> > > select, Action <TComponentType, PropertyChangedEvent <TPropertyType> > handler, Func <TComponentType, TPropertyType> getImmediateValue = null, bool onlyWhenChanged = false) where TComponentType : class, IEcsComponent { if (onlyWhenChanged) { system.OnComponentCreated <TComponentType>().Subscribe(_ => { select(_).Subscribe(v => { // the next line crashes unity: //!Equals(v.PreviousValue, v.CurrentValue)) //That is why we got some nastiness here if (!v.Comparer.Equals(v.PreviousValue, v.CurrentValue)) { handler(_, v); } }).DisposeWith(_).DisposeWith(system); if (getImmediateValue != null) { handler(_, new PropertyChangedEvent <TPropertyType>() { CurrentValue = getImmediateValue(_) }); } }).DisposeWith(system); } else { system.OnComponentCreated <TComponentType>().Subscribe(_ => { select(_).Subscribe(v => handler(_, v)).DisposeWith(_).DisposeWith(system); if (getImmediateValue != null) { handler(_, new PropertyChangedEvent <TPropertyType>() { CurrentValue = getImmediateValue(_) }); } }).DisposeWith(system); } }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> /// <param name="namedRunSystem">Optional name of system.</param> public EcsSystems Add(IEcsSystem system, string namedRunSystem = null) { #if DEBUG if (system == null) { throw new Exception("System is null."); } if (_initialized) { throw new Exception("Cant add system after initialization."); } if (_destroyed) { throw new Exception("Cant touch after destroy."); } if (!string.IsNullOrEmpty(namedRunSystem) && !(system is IEcsRunSystem)) { throw new Exception("Cant name non-IEcsRunSystem."); } #endif _allSystems.Add(system); if (system is IEcsRunSystem) { if (namedRunSystem == null && system is EcsSystems ecsSystems) { namedRunSystem = ecsSystems.Name; } if (namedRunSystem != null) { #if DEBUG if (_namedRunSystems.ContainsKey(namedRunSystem.GetHashCode())) { throw new Exception($"Cant add named system - \"{namedRunSystem}\" name already exists."); } #endif _namedRunSystems[namedRunSystem.GetHashCode()] = _runSystems.Count; } _runSystems.Add(new EcsSystemsRunItem { Active = true, System = (IEcsRunSystem)system }); } return(this); }
/// <summary> /// Listens for when a Reactive Collection's item has been added, and ensures that the subscription properly disposed when the system disposes or when the component disposes. /// </summary> /// <typeparam name="TComponentType"></typeparam> /// <typeparam name="TPropertyType"></typeparam> /// <param name="system">This system to install this listner on, it will get disposed with this one.</param> /// <param name="select">The ReactiveCollection selector.</param> /// <param name="handler">The method that is invoked when an item is added to the collection</param> /// <param name="immediate">Should the handler be invoked for every item that is currently in the list?</param> public static void CollectionItemAdded <TComponentType, TPropertyType>(this IEcsSystem system, Func <TComponentType, ReactiveCollection <TPropertyType> > select, Action <TComponentType, TPropertyType> handler, bool immediate = false) where TComponentType : class, IEcsComponent { system.OnComponentCreated <TComponentType>().Subscribe(_ => { select(_).ObserveAdd().Subscribe(v => handler(_, v.Value)).DisposeWith(_).DisposeWith(system); if (immediate) { foreach (var item in select(_)) { handler(_, item); } } }).DisposeWith(system); }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public EcsWorld AddSystem(IEcsSystem system) { #if DEBUG && !ECS_PERF_TEST if (_inited) { throw new Exception("Already initialized, cant add new system."); } #endif if (UseDependencyInjection) { EcsInjections.Inject(this, system); } var preInitSystem = system as IEcsPreInitSystem; if (preInitSystem != null) { _preInitSystems.Add(preInitSystem); } var initSystem = system as IEcsInitSystem; if (initSystem != null) { _initSystems.Add(initSystem); } var runSystem = system as IEcsRunSystem; if (runSystem != null) { switch (runSystem.GetRunSystemType()) { case EcsRunSystemType.Update: _runUpdateSystems.Add(runSystem); break; case EcsRunSystemType.FixedUpdate: _runFixedUpdateSystems.Add(runSystem); break; } } return(this); }
/// <summary> /// Adds a system or group of systems to the list /// </summary> /// <param name="groupHierarchy">Parent group hierarchy</param> /// <param name="system">System or group of systems</param> private void AddSystem(Stack <Type> groupHierarchy, IEcsSystem system) { if (groupHierarchy.Count > 0) { Type parentType = groupHierarchy.Pop(); if (!TryGetSystemGroup(parentType, out EcsSystemGroup systemGroup)) { systemGroup = (EcsSystemGroup)Activator.CreateInstance(parentType); _systems.Add(systemGroup); _dirty = true; } systemGroup.AddSystem(groupHierarchy, system); } else { _systems.Add(system); _dirty = true; } }
private void ActivateSystem(Type systemType, LeoSystemData data, IEcsSystem ecsSystem) { var systemInfo = GetSystemInfo(systemType); if (!systemInfo.IsActive) { systemInfo.data = data; var system = ecsSystem ?? _factory.Create(systemType); var systems = system is IEcsRunSystem ? new EcsSystems(_world).Add(system, systemType.Name): new EcsSystems(_world).Add(system); systemInfo.systems = systems; systemInfo.ecsSystem = system; systems.Init(); _updateQueues[data.updateType].Add(systems); } systemInfo.counter++; }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public EcsSystems Add(IEcsSystem system) { Internals.EcsHelpers.Assert(system != null, "system is null"); #if !LEOECS_DISABLE_INJECT EcsInjections.Inject(system, _world); #endif var preInitSystem = system as IEcsPreInitSystem; if (preInitSystem != null) { if (_preInitSystemsCount == _preInitSystems.Length) { Array.Resize(ref _preInitSystems, _preInitSystemsCount << 1); } _preInitSystems[_preInitSystemsCount++] = preInitSystem; } var initSystem = system as IEcsInitSystem; if (initSystem != null) { if (_initSystemsCount == _initSystems.Length) { Array.Resize(ref _initSystems, _initSystemsCount << 1); } _initSystems[_initSystemsCount++] = initSystem; } var runSystem = system as IEcsRunSystem; if (runSystem != null) { if (_runSystemsCount == _runSystems.Length) { Array.Resize(ref _runSystems, _runSystemsCount << 1); } _runSystems[_runSystemsCount++] = runSystem; } return(this); }
/// <summary> /// Adds new system to processing. /// </summary> /// <param name="system">System instance.</param> public MultiTickEcsSystems Add(IEcsSystem system) { #if DEBUG if (system == null) { throw new ArgumentNullException(); } #endif var initSystem = system as IEcsInitSystem; if (initSystem != null) { if (_initSystemsCount == _initSystems.Length) { Array.Resize(ref _initSystems, _initSystemsCount << 1); } _initSystems[_initSystemsCount++] = initSystem; } #if !LEOECS_DISABLE_INJECT EcsInjections.Inject(system, _world); #endif var runSystem = system as IEcsRunSystem; if (runSystem != null) { if (_runSystemsCount == _runSystems.Length) { Array.Resize(ref _runSystems, _runSystemsCount << 1); } _runSystems[_runSystemsCount++] = runSystem; } return(this); }
public void AddSystem(IEcsSystem system) { AddSystem(GetSystemGroupHierarchy(system.GetType()), system); }
public void ActivateSystem(IEcsSystem system, LeoSystemData systemData) { var systemType = system.GetType(); ActivateSystem(systemType, systemData, system); }
public void ActivateSystem(IEcsSystem system) { var systemType = system.GetType(); ActivateSystem(systemType, CreateSystemInfo(systemType), system); }