mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-17 09:24:37 +08:00
Update WIP
This commit is contained in:
parent
80458d2e70
commit
491e8069c3
14
DragonECS.asmdef
Normal file
14
DragonECS.asmdef
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "DCFApixels.DragonECS",
|
||||||
|
"rootNamespace": "DCFApixels",
|
||||||
|
"references": [],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
7
DragonECS.asmdef.meta
Normal file
7
DragonECS.asmdef.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: abb125fa67fff1e45914d0825236f608
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
src.meta
Normal file
8
src.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0192fd952d3f4a24d8057af65f35d8e1
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
13
src/EcsEntityTable.cs
Normal file
13
src/EcsEntityTable.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public interface IEcsEntityTable
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
11
src/EcsEntityTable.cs.meta
Normal file
11
src/EcsEntityTable.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1d395d007b9c7c24c9f1f4c09f16e04c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
84
src/EcsEntityTableManager.cs
Normal file
84
src/EcsEntityTableManager.cs
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public class EcsEntityTableManager
|
||||||
|
{
|
||||||
|
private int _count;
|
||||||
|
private IEcsFieldPool[] _fieldPools;
|
||||||
|
|
||||||
|
private int _idIncrement;
|
||||||
|
private Dictionary<IDKey, int> _ids;
|
||||||
|
|
||||||
|
public EcsEntityTableManager(int capacity)
|
||||||
|
{
|
||||||
|
_fieldPools = new IEcsFieldPool[capacity];
|
||||||
|
_ids = new Dictionary<IDKey, int>(capacity);
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EcsFieldPool<T> GetFieldPool<T>(int id)
|
||||||
|
{
|
||||||
|
if(id < _count)
|
||||||
|
return (EcsFieldPool<T>)_fieldPools[id];
|
||||||
|
|
||||||
|
_count++;
|
||||||
|
if(_fieldPools.Length < _count)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _fieldPools, _fieldPools.Length << 1);
|
||||||
|
}
|
||||||
|
EcsFieldPool<T> newPool = new EcsFieldPool<T>(7);
|
||||||
|
_fieldPools[id] = newPool;
|
||||||
|
return newPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResizeFieldPool(int id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int GetFieldID(string name, int index)
|
||||||
|
{
|
||||||
|
IDKey key = new IDKey(name, index);
|
||||||
|
if (_ids.TryGetValue(key, out int id))
|
||||||
|
return id;
|
||||||
|
|
||||||
|
id = _idIncrement++;
|
||||||
|
_ids.Add(key, id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct IDKey
|
||||||
|
{
|
||||||
|
public string name;
|
||||||
|
public int index;
|
||||||
|
|
||||||
|
public IDKey(string name, int index)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is IDKey key &&
|
||||||
|
name == key.name &&
|
||||||
|
index == key.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(name, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return name + "_" + index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/EcsEntityTableManager.cs.meta
Normal file
11
src/EcsEntityTableManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f568bc9f583414c4188526dfade20358
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
17
src/EcsField.cs
Normal file
17
src/EcsField.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public struct EcsField<T>
|
||||||
|
{
|
||||||
|
private EcsFieldPool<T> _pool;
|
||||||
|
public ref T this[int index]
|
||||||
|
{
|
||||||
|
get => ref _pool[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/EcsField.cs.meta
Normal file
11
src/EcsField.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f2fa97ad86c494a40939307a2cfaca36
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
51
src/EcsFieldPool.cs
Normal file
51
src/EcsFieldPool.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public interface IEcsFieldPool
|
||||||
|
{
|
||||||
|
public bool Has(int index);
|
||||||
|
public void Add(int index);
|
||||||
|
}
|
||||||
|
public class EcsFieldPool<T> : IEcsFieldPool
|
||||||
|
{
|
||||||
|
private SparseSet _sparseSet;
|
||||||
|
private T[] _denseItems;
|
||||||
|
|
||||||
|
public EcsFieldPool(int capacity)
|
||||||
|
{
|
||||||
|
_denseItems = new T[capacity];
|
||||||
|
_sparseSet = new SparseSet(capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref T this[int index]
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => ref _denseItems[_sparseSet[index]];
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public ref T Add(int index)
|
||||||
|
{
|
||||||
|
_sparseSet.Add(index);
|
||||||
|
_sparseSet.Normalize(ref _denseItems);
|
||||||
|
return ref _denseItems[_sparseSet.IndexOf(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Has(int index)
|
||||||
|
{
|
||||||
|
return _sparseSet.Contains(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEcsFieldPool
|
||||||
|
void IEcsFieldPool.Add(int index)
|
||||||
|
{
|
||||||
|
Add(index);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
11
src/EcsFieldPool.cs.meta
Normal file
11
src/EcsFieldPool.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2b523e51b8d5f4c4c969e0ffec1b8b6f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
119
src/EcsSession.cs
Normal file
119
src/EcsSession.cs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
|
||||||
|
public class EcsSession
|
||||||
|
{
|
||||||
|
private List<IEcsSystem> _allSystems;
|
||||||
|
private ReadOnlyCollection<IEcsSystem> _ecsSystemsSealed;
|
||||||
|
|
||||||
|
private bool _isInit = false;
|
||||||
|
private bool _isDestoryed = false;
|
||||||
|
|
||||||
|
private int _worldIdIncrement;
|
||||||
|
private Dictionary<string, EcsWorld> _worldsDict = new Dictionary<string, EcsWorld>();
|
||||||
|
private List<EcsWorld> _worlds = new List<EcsWorld>();
|
||||||
|
|
||||||
|
private Dictionary<Type, IEcsSystemsRunner> _runners;
|
||||||
|
private Dictionary<Type, IEcsSystemsMessenger> _messengers;
|
||||||
|
private EcsSystemsRunner<_Run> _runRunnerCache;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public ReadOnlyCollection<IEcsSystem> AllSystems => _ecsSystemsSealed;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region React Runners/Messengers
|
||||||
|
public EcsSystemsRunner<TDoTag> GetRunner<TDoTag>()
|
||||||
|
where TDoTag : IEcsDoTag
|
||||||
|
{
|
||||||
|
Type type = typeof(TDoTag);
|
||||||
|
if (_runners.TryGetValue(type, out IEcsSystemsRunner result))
|
||||||
|
{
|
||||||
|
return (EcsSystemsRunner<TDoTag>)result;
|
||||||
|
}
|
||||||
|
result = new EcsSystemsRunner<TDoTag>(this);
|
||||||
|
_runners.Add(type, result);
|
||||||
|
return (EcsSystemsRunner<TDoTag>)result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EcsSystemsMessenger<TMessege> GetMessenger<TMessege>()
|
||||||
|
where TMessege : IEcsMessage
|
||||||
|
{
|
||||||
|
Type type = typeof(TMessege);
|
||||||
|
if (_messengers.TryGetValue(type, out IEcsSystemsMessenger result))
|
||||||
|
{
|
||||||
|
return (EcsSystemsMessenger<TMessege>)result;
|
||||||
|
}
|
||||||
|
result = new EcsSystemsMessenger<TMessege>(this);
|
||||||
|
_messengers.Add(type, result);
|
||||||
|
return (EcsSystemsMessenger<TMessege>)result;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Configuration
|
||||||
|
public EcsSession Add(IEcsSystem system)
|
||||||
|
{
|
||||||
|
CheckInitForMethod(nameof(AddWorld));
|
||||||
|
|
||||||
|
_allSystems.Add(system);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public EcsSession AddWorld(string name)
|
||||||
|
{
|
||||||
|
CheckInitForMethod(nameof(AddWorld));
|
||||||
|
|
||||||
|
//_worlds.Add(new EcsWorld(_worldIdIncrement++));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region LifeCycle
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
CheckInitForMethod(nameof(Init));
|
||||||
|
_ecsSystemsSealed = _allSystems.AsReadOnly();
|
||||||
|
_isInit = true;
|
||||||
|
|
||||||
|
GetRunner<_PreInit>().Run();
|
||||||
|
GetRunner<_Init>().Run();
|
||||||
|
|
||||||
|
_runRunnerCache = GetRunner<_Run>();
|
||||||
|
}
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
CheckDestroyForMethod(nameof(Run));
|
||||||
|
|
||||||
|
|
||||||
|
_runRunnerCache.Run();
|
||||||
|
}
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
CheckDestroyForMethod(nameof(Run));
|
||||||
|
_isDestoryed = true;
|
||||||
|
GetRunner<_Destroy>().Run();
|
||||||
|
GetRunner<_PostDestroy>().Run();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region StateChecks
|
||||||
|
private void CheckInitForMethod(string methodName)
|
||||||
|
{
|
||||||
|
if (_isInit)
|
||||||
|
throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после инициализации {nameof(EcsSession)}");
|
||||||
|
}
|
||||||
|
private void CheckDestroyForMethod(string methodName)
|
||||||
|
{
|
||||||
|
if (_isInit)
|
||||||
|
throw new MethodAccessException($"Запрещено вызывать метод {methodName}, после уничтожения {nameof(EcsSession)}");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
11
src/EcsSession.cs.meta
Normal file
11
src/EcsSession.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2ae31658c78bbf04cb755ac72be367dd
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
83
src/EcsWorld.cs
Normal file
83
src/EcsWorld.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public class EcsWorld
|
||||||
|
{
|
||||||
|
public const int MAX_WORLDS = byte.MaxValue; //Номер последнего мира 254
|
||||||
|
public const int DEAD_WORLD_ID = byte.MaxValue; //Зарезервированный номер мира для мертвых сущьностей
|
||||||
|
|
||||||
|
private byte _id = DEAD_WORLD_ID;
|
||||||
|
|
||||||
|
private Dictionary<Type, IEcsFieldPool> _pools;
|
||||||
|
private SparseSet _entities = new SparseSet();
|
||||||
|
private short[] _gens;
|
||||||
|
private byte[] _components;
|
||||||
|
|
||||||
|
//private Dictionary<Type, IEcsEntityTable> _tables;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public int ID => _id;
|
||||||
|
public bool IsAlive => _id != DEAD_WORLD_ID;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public EcsWorld()
|
||||||
|
{
|
||||||
|
_pools = new Dictionary<Type, IEcsFieldPool>();
|
||||||
|
_entities = new SparseSet();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ID
|
||||||
|
internal void SetId(byte id)
|
||||||
|
{
|
||||||
|
_id = id;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GetPool
|
||||||
|
public EcsFieldPool<T> GetPool<T>()
|
||||||
|
{
|
||||||
|
Type type = typeof(T);
|
||||||
|
if (_pools.TryGetValue(type, out IEcsFieldPool pool))
|
||||||
|
{
|
||||||
|
return (EcsFieldPool<T>)pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
//pool = new EcsPool<T>();
|
||||||
|
_pools.Add(type, pool);
|
||||||
|
return (EcsFieldPool<T>)pool;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region NewEntity
|
||||||
|
public ent NewEntity()
|
||||||
|
{
|
||||||
|
int entityID = _entities.GetFree();
|
||||||
|
_entities.Normalize(ref _gens);
|
||||||
|
_entities.Normalize(ref _components);
|
||||||
|
_gens[entityID]++;
|
||||||
|
|
||||||
|
|
||||||
|
return new ent(entityID, _gens[entityID], _id, _components[entityID]);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Destroy
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
_id = Consts.DEAD_WORLD_ID;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private void Resize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/EcsWorld.cs.meta
Normal file
11
src/EcsWorld.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b045d6a8b5bcf654f9c2be8012a526f6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
2
src/INFO.txt
Normal file
2
src/INFO.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Мервтый мир - значение byte 255, зарезервированный адишник мира, все что ссылается на мертвый мир считается так же мертвым.
|
||||||
|
|
7
src/INFO.txt.meta
Normal file
7
src/INFO.txt.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 39030d83d78d46048982adceaa08bfbd
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
src/Interfaces.meta
Normal file
8
src/Interfaces.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4ed6f2439b576f34eaefee5b9d0978bf
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
29
src/Interfaces/IEcsSystem.cs
Normal file
29
src/Interfaces/IEcsSystem.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public interface IEcsSystem { }
|
||||||
|
|
||||||
|
public interface IEcsDoTag { }
|
||||||
|
public struct _PreInit : IEcsDoTag { }
|
||||||
|
public struct _Init : IEcsDoTag { }
|
||||||
|
public struct _Run : IEcsDoTag { }
|
||||||
|
public struct _Destroy : IEcsDoTag { }
|
||||||
|
public struct _PostDestroy : IEcsDoTag { }
|
||||||
|
public interface IEcsDo<TTag> : IEcsSystem
|
||||||
|
where TTag : IEcsDoTag
|
||||||
|
{
|
||||||
|
public void Do(EcsSession engine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IEcsMessage { }
|
||||||
|
public interface IEcsDoMessege<TMessage> : IEcsSystem
|
||||||
|
where TMessage : IEcsMessage
|
||||||
|
{
|
||||||
|
public void Do(EcsSession engine, in TMessage message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IEcsSimpleCycleSystem :
|
||||||
|
IEcsDo<_Init>,
|
||||||
|
IEcsDo<_Run>,
|
||||||
|
IEcsDo<_Destroy>
|
||||||
|
{ }
|
||||||
|
}
|
11
src/Interfaces/IEcsSystem.cs.meta
Normal file
11
src/Interfaces/IEcsSystem.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c440e40c9802ce54fb7a84fda930b22d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
src/React.meta
Normal file
8
src/React.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c0c409d38416ea840b358d614c3e62a4
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
41
src/React/EcsSystemsMessenger.cs
Normal file
41
src/React/EcsSystemsMessenger.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public interface IEcsSystemsMessenger
|
||||||
|
{
|
||||||
|
public EcsSession Source { get; }
|
||||||
|
}
|
||||||
|
public class EcsSystemsMessenger<TMessage> : IEcsSystemsMessenger
|
||||||
|
where TMessage : IEcsMessage
|
||||||
|
{
|
||||||
|
private EcsSession _source;
|
||||||
|
private IEcsDoMessege<TMessage>[] _systems;
|
||||||
|
|
||||||
|
public EcsSession Source => _source;
|
||||||
|
public IReadOnlyList<IEcsDoMessege<TMessage>> Systems => _systems;
|
||||||
|
|
||||||
|
internal EcsSystemsMessenger(EcsSession source)
|
||||||
|
{
|
||||||
|
_source = source;
|
||||||
|
List<IEcsDoMessege<TMessage>> list = new List<IEcsDoMessege<TMessage>>();
|
||||||
|
|
||||||
|
foreach (var item in _source.AllSystems)
|
||||||
|
{
|
||||||
|
if (item is IEcsDoMessege<TMessage> targetItem)
|
||||||
|
{
|
||||||
|
list.Add(targetItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_systems = list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Send(in TMessage message)
|
||||||
|
{
|
||||||
|
foreach (var item in _systems)
|
||||||
|
{
|
||||||
|
item.Do(_source, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/React/EcsSystemsMessenger.cs.meta
Normal file
11
src/React/EcsSystemsMessenger.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: dc514cbb93c3f3049adf666ad237c6ee
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
42
src/React/EcsSystemsRunner.cs
Normal file
42
src/React/EcsSystemsRunner.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public interface IEcsSystemsRunner
|
||||||
|
{
|
||||||
|
public EcsSession Source { get; }
|
||||||
|
public void Run();
|
||||||
|
}
|
||||||
|
public class EcsSystemsRunner<TDoTag> : IEcsSystemsRunner
|
||||||
|
where TDoTag : IEcsDoTag
|
||||||
|
{
|
||||||
|
private EcsSession _source;
|
||||||
|
private IEcsDo<TDoTag>[] _systems;
|
||||||
|
|
||||||
|
public EcsSession Source => _source;
|
||||||
|
public IReadOnlyList<IEcsDo<TDoTag>> Systems => _systems;
|
||||||
|
|
||||||
|
internal EcsSystemsRunner(EcsSession source)
|
||||||
|
{
|
||||||
|
_source = source;
|
||||||
|
List<IEcsDo<TDoTag>> list = new List<IEcsDo<TDoTag>>();
|
||||||
|
|
||||||
|
foreach (var item in _source.AllSystems)
|
||||||
|
{
|
||||||
|
if (item is IEcsDo<TDoTag> targetItem)
|
||||||
|
{
|
||||||
|
list.Add(targetItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_systems = list.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
foreach (var item in _systems)
|
||||||
|
{
|
||||||
|
item.Do(_source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/React/EcsSystemsRunner.cs.meta
Normal file
11
src/React/EcsSystemsRunner.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 37fabd05090af0843a67e6c8046ad374
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
src/Utils.meta
Normal file
8
src/Utils.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 16b79c30e1b668e47bd35de518796871
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
12
src/Utils/ComponentTypeID.cs
Normal file
12
src/Utils/ComponentTypeID.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public class ComponentTypeID
|
||||||
|
{
|
||||||
|
protected static int _incerement = 0;
|
||||||
|
}
|
||||||
|
public class TypeID<T> : ComponentTypeID
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
public static readonly int id = _incerement++;
|
||||||
|
}
|
||||||
|
}
|
11
src/Utils/ComponentTypeID.cs.meta
Normal file
11
src/Utils/ComponentTypeID.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b5af477721d789f498a0de809e753321
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
264
src/Utils/GrowingSparseCollection.cs
Normal file
264
src/Utils/GrowingSparseCollection.cs
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.Contracts;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.ConstrainedExecution;
|
||||||
|
|
||||||
|
namespace DCFApixels
|
||||||
|
{
|
||||||
|
public class GrowingSparseCollection<TValue>
|
||||||
|
{
|
||||||
|
private const int EMPTY = -1;
|
||||||
|
|
||||||
|
private int[] _buckets = Array.Empty<int>();
|
||||||
|
private Entry[] _entries = Array.Empty<Entry>();
|
||||||
|
|
||||||
|
private int _capacity;
|
||||||
|
private int _count;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public TValue this[int key]
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _entries[FindEntry(key)].value;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Add
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Add(int key, TValue value)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (Contains(key))
|
||||||
|
throw new ArgumentException("Contains(key) is true");
|
||||||
|
#endif
|
||||||
|
Insert(key, value);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Getter
|
||||||
|
public bool TryGetValue(int key, out TValue value)
|
||||||
|
{
|
||||||
|
int index = IndexOfKey(key);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value = _entries[index].value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public GrowingSparseCollection(int capacity)
|
||||||
|
{
|
||||||
|
Initialize(capacity);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Initialize
|
||||||
|
private void Initialize(int capacity)
|
||||||
|
{
|
||||||
|
_capacity = HashHelpers.GetPrime(capacity);
|
||||||
|
_buckets = new int[_capacity];
|
||||||
|
|
||||||
|
for (int i = 0; i < _capacity; i++)
|
||||||
|
_buckets[i] = EMPTY;
|
||||||
|
|
||||||
|
_entries = new Entry[_capacity];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Clear
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (_count > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _buckets.Length; i++)
|
||||||
|
{
|
||||||
|
_buckets[i] = -1;
|
||||||
|
}
|
||||||
|
Array.Clear(_entries, 0, _count);
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Contains
|
||||||
|
public bool Contains(int key)
|
||||||
|
{
|
||||||
|
return IndexOfKey(key) >= 0;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IndexOfKey/Find/Insert
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOfKey(int key)
|
||||||
|
{
|
||||||
|
key &= ~int.MinValue;
|
||||||
|
for (int i = _buckets[key % _capacity]; i >= 0; i = _entries[i].next)
|
||||||
|
{
|
||||||
|
if (_entries[i].key == key)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private int FindEntry(int key)
|
||||||
|
{
|
||||||
|
key &= ~int.MinValue;
|
||||||
|
for (int i = _buckets[key % _capacity]; i >= 0; i = _entries[i].next)
|
||||||
|
{
|
||||||
|
if (_entries[i].key == key)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
throw new KeyNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Insert(int key, TValue value)
|
||||||
|
{
|
||||||
|
key &= ~int.MinValue;
|
||||||
|
int targetBucket = key % _capacity;
|
||||||
|
|
||||||
|
for (int i = _buckets[targetBucket]; i >= 0; i = _entries[i].next)
|
||||||
|
{
|
||||||
|
if (_entries[i].key == key)
|
||||||
|
{
|
||||||
|
_entries[i].value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_count >= _entries.Length)
|
||||||
|
{
|
||||||
|
Resize();
|
||||||
|
targetBucket = key % _capacity;
|
||||||
|
}
|
||||||
|
int index = _count;
|
||||||
|
_count++;
|
||||||
|
|
||||||
|
_entries[index].next = _buckets[targetBucket];
|
||||||
|
_entries[index].key = key;
|
||||||
|
_entries[index].value = value;
|
||||||
|
_buckets[targetBucket] = index;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Resize
|
||||||
|
private void Resize()
|
||||||
|
{
|
||||||
|
Resize(HashHelpers.ExpandPrime(_count), false);
|
||||||
|
}
|
||||||
|
private void Resize(int newSize, bool forceNewHashCodes)
|
||||||
|
{
|
||||||
|
_capacity = newSize;
|
||||||
|
Contract.Assert(newSize >= _entries.Length);
|
||||||
|
int[] newBuckets = new int[newSize];
|
||||||
|
for (int i = 0; i < newBuckets.Length; i++)
|
||||||
|
{
|
||||||
|
newBuckets[i] = EMPTY;
|
||||||
|
}
|
||||||
|
Entry[] newEntries = new Entry[newSize];
|
||||||
|
Array.Copy(_entries, 0, newEntries, 0, _count);
|
||||||
|
if (forceNewHashCodes)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _count; i++)
|
||||||
|
{
|
||||||
|
if (newEntries[i].key != -1)
|
||||||
|
{
|
||||||
|
newEntries[i].key = newEntries[i].key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < _count; i++)
|
||||||
|
{
|
||||||
|
if (newEntries[i].key >= 0)
|
||||||
|
{
|
||||||
|
int bucket = newEntries[i].key % newSize;
|
||||||
|
newEntries[i].next = newBuckets[bucket];
|
||||||
|
newBuckets[bucket] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_buckets = newBuckets;
|
||||||
|
_entries = newEntries;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Utils
|
||||||
|
private struct Entry
|
||||||
|
{
|
||||||
|
public int next; // Index of next entry, -1 if last
|
||||||
|
public int key; // key & hash
|
||||||
|
public TValue value;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#region HashHelpers
|
||||||
|
internal static class HashHelpers
|
||||||
|
{
|
||||||
|
public const int MaxPrimeArrayLength = 0x7FEFFFFD;
|
||||||
|
public static readonly int[] primes = {
|
||||||
|
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
|
||||||
|
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
|
||||||
|
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
|
||||||
|
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
|
||||||
|
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};
|
||||||
|
|
||||||
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||||
|
public static bool IsPrime(int candidate)
|
||||||
|
{
|
||||||
|
if ((candidate & 1) != 0)
|
||||||
|
{
|
||||||
|
int limit = (int)Math.Sqrt(candidate);
|
||||||
|
for (int divisor = 3; divisor <= limit; divisor += 2)
|
||||||
|
{
|
||||||
|
if ((candidate % divisor) == 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (candidate == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ExpandPrime(int oldSize)
|
||||||
|
{
|
||||||
|
int newSize = 2 * oldSize;
|
||||||
|
|
||||||
|
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
|
||||||
|
{
|
||||||
|
Contract.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
|
||||||
|
return MaxPrimeArrayLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetPrime(newSize);
|
||||||
|
}
|
||||||
|
internal const int HashtableHashPrime = 101;
|
||||||
|
|
||||||
|
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
|
||||||
|
public static int GetPrime(int min)
|
||||||
|
{
|
||||||
|
if (min < 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("min < 0"); //TODO
|
||||||
|
}
|
||||||
|
Contract.EndContractBlock();
|
||||||
|
|
||||||
|
for (int i = 0; i < primes.Length; i++)
|
||||||
|
{
|
||||||
|
int prime = primes[i];
|
||||||
|
if (prime >= min)
|
||||||
|
return prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = (min | 1); i < int.MaxValue; i += 2)
|
||||||
|
{
|
||||||
|
if (IsPrime(i) && ((i - 1) % HashtableHashPrime != 0))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
11
src/Utils/GrowingSparseCollection.cs.meta
Normal file
11
src/Utils/GrowingSparseCollection.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0862221477782744a98863ae86648660
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
1036
src/Utils/IntSet.cs
Normal file
1036
src/Utils/IntSet.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
src/Utils/IntSet.cs.meta
Normal file
11
src/Utils/IntSet.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9cad30d5b37df1d48bc2abe5d1743649
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
489
src/Utils/SparseSet.cs
Normal file
489
src/Utils/SparseSet.cs
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
// _sparse[value] == index
|
||||||
|
// _dense[index] == value
|
||||||
|
//
|
||||||
|
// int[] _dense => |2|4|1|_|_|
|
||||||
|
// int[] _sparse => |_|2|0|_|1|
|
||||||
|
//
|
||||||
|
// indexator => [0]2, [1]4, [2]1
|
||||||
|
//
|
||||||
|
// can use foreach
|
||||||
|
// implements IEnumerable<int>
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public class SparseSet : IEnumerable<int>, ICollection<int>, IReadOnlyCollection<int>
|
||||||
|
{
|
||||||
|
public const int DEFAULT_CAPACITY = 16;
|
||||||
|
|
||||||
|
private int[] _dense;
|
||||||
|
private int[] _sparse;
|
||||||
|
|
||||||
|
private int _count;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public int Count => _count;
|
||||||
|
public int Capacity => _dense.Length;
|
||||||
|
|
||||||
|
public int this[int index]
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
#if DEBUG
|
||||||
|
get
|
||||||
|
{
|
||||||
|
ThrowHalper.CheckOutOfRange(this, index);
|
||||||
|
return _dense[index];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
get => _dense[index];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexesCollection Indexes => new IndexesCollection(_sparse);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
public SparseSet() : this(DEFAULT_CAPACITY) { }
|
||||||
|
public SparseSet(int capacity)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
ThrowHalper.CheckCapacity(capacity);
|
||||||
|
#endif
|
||||||
|
_dense = new int[capacity];
|
||||||
|
_sparse = new int[capacity];
|
||||||
|
for (int i = 0; i < _sparse.Length; i++)
|
||||||
|
{
|
||||||
|
_dense[i] = i;
|
||||||
|
_sparse[i] = i;
|
||||||
|
}
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Add/AddRange/GetFree
|
||||||
|
public void Add<T>(int value, ref T[] normalizedArray)
|
||||||
|
{
|
||||||
|
Add(value);
|
||||||
|
Normalize(ref normalizedArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Add(int value)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
ThrowHalper.CheckValueIsPositive(value);
|
||||||
|
ThrowHalper.CheckValueNotContained(this, value);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int neadedSpace = _dense.Length;
|
||||||
|
while (value >= neadedSpace)
|
||||||
|
neadedSpace <<= 1;
|
||||||
|
|
||||||
|
if (neadedSpace != _dense.Length)
|
||||||
|
Resize(neadedSpace);
|
||||||
|
|
||||||
|
if (Contains(value))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Swap(value, _count++);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryAdd<T>(int value, ref T[] normalizedArray)
|
||||||
|
{
|
||||||
|
if (Contains(value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Add(value, ref normalizedArray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryAdd(int value)
|
||||||
|
{
|
||||||
|
if (Contains(value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Add(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange<T>(IEnumerable<int> range, ref T[] normalizedArray)
|
||||||
|
{
|
||||||
|
foreach (var item in range)
|
||||||
|
{
|
||||||
|
if (Contains(item))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Add(item);
|
||||||
|
}
|
||||||
|
Normalize(ref normalizedArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRange(IEnumerable<int> range)
|
||||||
|
{
|
||||||
|
foreach (var item in range)
|
||||||
|
{
|
||||||
|
if (Contains(item))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a value between 0 and Capacity to the array and returns it.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Value between 0 and Capacity</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int GetFree<T>(ref T[] normalizedArray)
|
||||||
|
{
|
||||||
|
int result = GetFree();
|
||||||
|
Normalize(ref normalizedArray);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a value between 0 and Capacity to the array and returns it.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Value between 0 and Capacity</returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int GetFree()
|
||||||
|
{
|
||||||
|
if (++_count >= _dense.Length)
|
||||||
|
AddSpaces();
|
||||||
|
|
||||||
|
return _dense[_count - 1];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Contains
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Contains(int value)
|
||||||
|
{
|
||||||
|
return value >= 0 && value < Capacity && _sparse[value] < _count;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Remove
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Remove(int value)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
ThrowHalper.CheckValueContained(this, value);
|
||||||
|
#endif
|
||||||
|
Swap(_sparse[value], --_count);
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool TryRemove(int value)
|
||||||
|
{
|
||||||
|
if (!Contains(value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Remove(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void RemoveAt(int index)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
ThrowHalper.CheckOutOfRange(this, index);
|
||||||
|
#endif
|
||||||
|
Remove(_dense[index]);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Other
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Normalize<T>(ref T[] array)
|
||||||
|
{
|
||||||
|
if (array.Length != _dense.Length)
|
||||||
|
Array.Resize(ref array, _dense.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public int IndexOf(int value)
|
||||||
|
{
|
||||||
|
if (value < 0 || !Contains(value))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return _sparse[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sort()
|
||||||
|
{
|
||||||
|
int increment = 0;
|
||||||
|
for (int i = 0; i < Capacity; i++)
|
||||||
|
{
|
||||||
|
if (_sparse[i] < _count)
|
||||||
|
{
|
||||||
|
_sparse[i] = increment;
|
||||||
|
_dense[increment++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HardSort()
|
||||||
|
{
|
||||||
|
int inc = 0;
|
||||||
|
int inc2 = _count;
|
||||||
|
for (int i = 0; i < Capacity; i++)
|
||||||
|
{
|
||||||
|
if (_sparse[i] < _count)
|
||||||
|
{
|
||||||
|
_sparse[i] = inc;
|
||||||
|
_dense[inc++] = i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_sparse[i] = inc2;
|
||||||
|
_dense[inc2++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(SparseSet other)
|
||||||
|
{
|
||||||
|
other._count = _count;
|
||||||
|
if (Capacity != other.Capacity)
|
||||||
|
{
|
||||||
|
other.Resize(Capacity);
|
||||||
|
}
|
||||||
|
_dense.CopyTo(other._dense, 0);
|
||||||
|
_sparse.CopyTo(other._sparse, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CopyTo(int[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (arrayIndex < 0)
|
||||||
|
throw new ArgumentException("arrayIndex is less than 0");
|
||||||
|
if (arrayIndex + _count >= array.Length)
|
||||||
|
throw new ArgumentException("The number of elements in the source List<T> is greater than the available space from arrayIndex to the end of the destination array.");
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < _count; i++, arrayIndex++)
|
||||||
|
{
|
||||||
|
array[arrayIndex] = this[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Clear/Reset
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
for (int i = 0; i < _dense.Length; i++)
|
||||||
|
{
|
||||||
|
_dense[i] = i;
|
||||||
|
_sparse[i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Reset(int newCapacity)
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
ThrowHalper.CheckCapacity(newCapacity);
|
||||||
|
#endif
|
||||||
|
Reset();
|
||||||
|
Resize(newCapacity);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region AddSpace/Resize
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void AddSpaces() => Resize(_count << 1);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void Resize(int newSpace)
|
||||||
|
{
|
||||||
|
int oldspace = _dense.Length;
|
||||||
|
Array.Resize(ref _dense, newSpace);
|
||||||
|
Array.Resize(ref _sparse, newSpace);
|
||||||
|
|
||||||
|
for (int i = oldspace; i < newSpace; i++)
|
||||||
|
{
|
||||||
|
_dense[i] = i;
|
||||||
|
_sparse[i] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Swap
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void Swap(int fromIndex, int toIndex)
|
||||||
|
{
|
||||||
|
int value = _dense[toIndex];
|
||||||
|
int oldValue = _dense[fromIndex];
|
||||||
|
|
||||||
|
_dense[toIndex] = oldValue;
|
||||||
|
_dense[fromIndex] = value;
|
||||||
|
_sparse[_dense[fromIndex]] = fromIndex;
|
||||||
|
_sparse[_dense[toIndex]] = toIndex;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Enumerator
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public RefEnumerator GetEnumerator() => new RefEnumerator(_dense, _count);
|
||||||
|
|
||||||
|
public ref struct RefEnumerator
|
||||||
|
{
|
||||||
|
private readonly int[] _dense;
|
||||||
|
private readonly int _count;
|
||||||
|
private int _index;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public RefEnumerator(int[] values, int count)
|
||||||
|
{
|
||||||
|
_dense = values;
|
||||||
|
_count = count;
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Current
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => _dense[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Dispose() { }
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool MoveNext() => ++_index < _count;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public void Reset() => _index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator<int> IEnumerable<int>.GetEnumerator() => new Enumerator(_dense, _count);
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => new Enumerator(_dense, _count);
|
||||||
|
public struct Enumerator : IEnumerator<int> //to implement the IEnumerable interface and use the ref structure, 2 Enumerators were created.
|
||||||
|
{
|
||||||
|
private readonly int[] _dense;
|
||||||
|
private readonly int _count;
|
||||||
|
private int _index;
|
||||||
|
public Enumerator(int[] values, int count)
|
||||||
|
{
|
||||||
|
_dense = values;
|
||||||
|
_count = count;
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
public int Current => _dense[_index];
|
||||||
|
object IEnumerator.Current => _dense[_index];
|
||||||
|
public void Dispose() { }
|
||||||
|
public bool MoveNext() => ++_index < _count;
|
||||||
|
public void Reset() => _index = -1;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Utils
|
||||||
|
public ref struct IndexesCollection
|
||||||
|
{
|
||||||
|
private readonly int[] _indexes;
|
||||||
|
|
||||||
|
public IndexesCollection(int[] indexes)
|
||||||
|
{
|
||||||
|
_indexes = indexes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int this[int value]
|
||||||
|
{
|
||||||
|
get => _indexes[value];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICollection
|
||||||
|
bool ICollection<int>.IsReadOnly => false;
|
||||||
|
|
||||||
|
bool ICollection<int>.Remove(int value) => TryRemove(value);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Debug
|
||||||
|
public string Log()
|
||||||
|
{
|
||||||
|
StringBuilder logbuild = new StringBuilder();
|
||||||
|
for (int i = 0; i < Capacity; i++)
|
||||||
|
{
|
||||||
|
logbuild.Append(_dense[i] + ", ");
|
||||||
|
}
|
||||||
|
logbuild.Append("\n\r");
|
||||||
|
for (int i = 0; i < Capacity; i++)
|
||||||
|
{
|
||||||
|
logbuild.Append(_sparse[i] + ", ");
|
||||||
|
}
|
||||||
|
logbuild.Append("\n\r --------------------------");
|
||||||
|
logbuild.Append("\n\r");
|
||||||
|
for (int i = 0; i < Capacity; i++)
|
||||||
|
{
|
||||||
|
logbuild.Append((i < _count ? _dense[i].ToString() : "_") + ", ");
|
||||||
|
}
|
||||||
|
logbuild.Append("\n\r");
|
||||||
|
for (int i = 0; i < Capacity; i++)
|
||||||
|
{
|
||||||
|
logbuild.Append((_sparse[i] < _count ? _sparse[i].ToString() : "_") + ", ");
|
||||||
|
}
|
||||||
|
logbuild.Append("\n\r Count: " + _count);
|
||||||
|
logbuild.Append("\n\r Capacity: " + Capacity);
|
||||||
|
logbuild.Append("\n\r IsValide: " + IsValide_Debug());
|
||||||
|
|
||||||
|
logbuild.Append("\n\r");
|
||||||
|
return logbuild.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsValide_Debug()
|
||||||
|
{
|
||||||
|
bool isPass = true;
|
||||||
|
for (int index = 0; index < Capacity; index++)
|
||||||
|
{
|
||||||
|
int value = _dense[index];
|
||||||
|
isPass = isPass && _sparse[value] == index;
|
||||||
|
}
|
||||||
|
return isPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private static class ThrowHalper
|
||||||
|
{
|
||||||
|
public static void CheckCapacity(int capacity)
|
||||||
|
{
|
||||||
|
if (capacity < 0)
|
||||||
|
throw new ArgumentException("Capacity cannot be a negative number");
|
||||||
|
}
|
||||||
|
public static void CheckValueIsPositive(int value)
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
throw new ArgumentException("The SparseSet can only contain positive numbers");
|
||||||
|
}
|
||||||
|
public static void CheckValueContained(SparseSet source, int value)
|
||||||
|
{
|
||||||
|
if (!source.Contains(value))
|
||||||
|
throw new ArgumentException($"Value {value} is not contained");
|
||||||
|
}
|
||||||
|
public static void CheckValueNotContained(SparseSet source, int value)
|
||||||
|
{
|
||||||
|
if (source.Contains(value))
|
||||||
|
throw new ArgumentException($"Value {value} is already contained");
|
||||||
|
}
|
||||||
|
public static void CheckOutOfRange(SparseSet source, int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= source.Count)
|
||||||
|
throw new ArgumentOutOfRangeException($"Index {index} was out of range. Must be non-negative and less than the size of the collection.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
11
src/Utils/SparseSet.cs.meta
Normal file
11
src/Utils/SparseSet.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d46dabbefb72a224bbf8e74eb12fc455
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
113
src/ent.cs
Normal file
113
src/ent.cs
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, Pack = 0, Size = 8)]
|
||||||
|
public readonly struct ent : IEquatable<long>, IEquatable<ent>
|
||||||
|
{
|
||||||
|
//private const int ID_BITS = 32;
|
||||||
|
//private const int GEN_BITS = 16;
|
||||||
|
//private const int WORLD_BITS = 8;
|
||||||
|
//private const int COM_BITS = 8;
|
||||||
|
|
||||||
|
public readonly long _full;
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public int id
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => (int)(_full >> 32);
|
||||||
|
}
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public short gen
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => (short)((_full << 32) >> 48);
|
||||||
|
|
||||||
|
}
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public byte world
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => (byte)((_full << 48) >> 56);
|
||||||
|
|
||||||
|
}
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public byte com
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get => (byte)((_full << 56) >> 56);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public ent(int id, short gen, byte world, byte com)
|
||||||
|
{
|
||||||
|
_full = ((long)id) << 32;
|
||||||
|
_full += ((long)gen) << 16;
|
||||||
|
_full += ((long)world) << 8;
|
||||||
|
_full += com;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public ent(long value)
|
||||||
|
{
|
||||||
|
_full = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public TypeCode GetTypeCode()
|
||||||
|
{
|
||||||
|
return TypeCode.Int64;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region GetHashCode
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return unchecked((int)(_full)) ^ (int)(_full >> 32);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Equals
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Equals(in ent other)
|
||||||
|
{
|
||||||
|
return _full == other._full;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is ent other && Equals(in other);
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Equals(ent other)
|
||||||
|
{
|
||||||
|
return _full == other._full;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public bool Equals(long other)
|
||||||
|
{
|
||||||
|
return _full == other;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region operators
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool operator ==(in ent left, in ent right) => left.Equals(in right);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static bool operator !=(in ent left, in ent right) => !left.Equals(in right);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static implicit operator long(in ent eent) => eent._full;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static implicit operator ent(in long value) => new ent(value);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
11
src/ent.cs.meta
Normal file
11
src/ent.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 24f0d55c3815f3c429a749511f5d3837
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
test.meta
Normal file
8
test.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3776f76149b634c48a0bf7a7f98ee0c5
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
23
test/TestSystem.cs
Normal file
23
test/TestSystem.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public class TestSystem : IEcsDo<_Init>, IEcsDo<_Run>, IEcsDo<_Destroy>
|
||||||
|
{
|
||||||
|
void IEcsDo<_Init>.Do(EcsSession engine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IEcsDo<_Run>.Do(EcsSession engine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void IEcsDo<_Destroy>.Do(EcsSession engine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
test/TestSystem.cs.meta
Normal file
11
test/TestSystem.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: affa952a9e445864ebfe2ca2388e76de
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
12
test/TransformTable.cs
Normal file
12
test/TransformTable.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public struct TransformTable
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
11
test/TransformTable.cs.meta
Normal file
11
test/TransformTable.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d6c6320184f942444b499e3f027a72a7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
Loading…
Reference in New Issue
Block a user