From d17bcb6b36863da5ddf857a13279d5bab9e12a89 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sat, 1 Jul 2017 15:54:13 +0100 Subject: [PATCH 1/7] update FastConcat --- Utilities/Print.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utilities/Print.cs b/Utilities/Print.cs index 6a64d26..0d7e601 100644 --- a/Utilities/Print.cs +++ b/Utilities/Print.cs @@ -7,7 +7,7 @@ public static class FastConcatUtility { static readonly StringBuilder _stringBuilder = new StringBuilder(256); - public static string FastConcat(this string str1, string str2) + public static string FastConcat(this string str1, T str2) { lock (_stringBuilder) { From 00566256ce5d27714d0e68c83ea6e7b7994b45c9 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sat, 1 Jul 2017 16:10:39 +0100 Subject: [PATCH 2/7] stupid meta files --- Context.meta | 9 --------- Context/ContextNotifier.cs.meta | 12 ------------ Context/Factories.meta | 9 --------- Context/Factories/GameObjectFactory.cs.meta | 12 ------------ Context/Factories/MonoBehaviourFactory.cs.meta | 12 ------------ Context/ICompositionRoot.cs.meta | 7 ------- Context/IContextNotifer.cs.meta | 8 -------- Context/IWaitForFrameworkDestruction.cs.meta | 8 -------- Context/IWaitForFrameworkInitialization.cs.meta | 8 -------- Context/UnityContext.cs.meta | 7 ------- DataStructures.meta | 9 --------- DataStructures/CircularBufferIndexer.cs.meta | 8 -------- DataStructures/FasterList.cs.meta | 12 ------------ DataStructures/HashableWeakReference.cs.meta | 12 ------------ DataStructures/Priority Queue.meta | 5 ----- .../Priority Queue/HeapPriorityQueue.cs.meta | 8 -------- DataStructures/Priority Queue/IPriorityQueue.cs.meta | 8 -------- .../Priority Queue/PriorityQueueNode.cs.meta | 8 -------- DataStructures/ReadOnlyDictionary.cs.meta | 12 ------------ DataStructures/ThreadSafeDictionary.cs.meta | 12 ------------ DataStructures/ThreadSafeQueue.cs.meta | 8 -------- DataStructures/WeakReference.cs.meta | 12 ------------ ECS.meta | 7 ------- ECS/Dispatcher.meta | 9 --------- ECS/Dispatcher/DispatchOnChange.cs.meta | 8 -------- ECS/Dispatcher/DispatcherOnSet.cs.meta | 12 ------------ ECS/EngineNodeDB.cs.meta | 12 ------------ ECS/EnginesRoot.cs.meta | 8 -------- ECS/EntityDescriptor.cs.meta | 12 ------------ ECS/GenericEntityDescriptor.cs.meta | 12 ------------ ECS/GenericEntityDescriptorHolder.cs.meta | 12 ------------ ECS/ICallBackOnAddEngine.cs.meta | 12 ------------ ECS/IEngine.cs.meta | 8 -------- ECS/IEngineNodeDB.cs.meta | 12 ------------ ECS/IEnginesRoot.cs.meta | 8 -------- ECS/IEntityDescriptorHolder.cs.meta | 12 ------------ ECS/INode.cs.meta | 8 -------- ECS/IRemoveEntityComponent.cs.meta | 12 ------------ ECS/Profiler.meta | 9 --------- ECS/Profiler/Editor.meta | 9 --------- ECS/Profiler/Editor/EngineProfiler.meta | 9 --------- .../EngineProfiler/EngineProfilerInspector.cs.meta | 12 ------------ .../EngineProfiler/EngineProfilerMenuItem.cs.meta | 12 ------------ .../Editor/EngineProfiler/EnginesMonitor.cs.meta | 12 ------------ .../EngineProfiler/ProfilerEditorLayout.cs.meta | 12 ------------ ECS/Profiler/EngineInfo.cs.meta | 12 ------------ ECS/Profiler/EngineProfiler.cs.meta | 12 ------------ ECS/Profiler/EngineProfilerBehaviour.cs.meta | 12 ------------ ECS/Sequencer.cs.meta | 12 ------------ ECS/SingleNodeEngine.cs.meta | 12 ------------ ECS/note.txt.meta | 4 ---- Factories.meta | 9 --------- Factories/IGameObjectFactory.cs.meta | 8 -------- Factories/IMonoBehaviourFactory.cs.meta | 8 -------- LICENSE.meta | 8 -------- README.md.meta | 8 -------- Utilities.meta | 9 --------- Utilities/DesignByContract.cs.meta | 10 ---------- Utilities/Print.cs.meta | 8 -------- Utilities/WeakActionStruct.cs.meta | 12 ------------ Utilities/WeakEvent.cs.meta | 12 ------------ 61 files changed, 601 deletions(-) delete mode 100644 Context.meta delete mode 100644 Context/ContextNotifier.cs.meta delete mode 100644 Context/Factories.meta delete mode 100644 Context/Factories/GameObjectFactory.cs.meta delete mode 100644 Context/Factories/MonoBehaviourFactory.cs.meta delete mode 100644 Context/ICompositionRoot.cs.meta delete mode 100644 Context/IContextNotifer.cs.meta delete mode 100644 Context/IWaitForFrameworkDestruction.cs.meta delete mode 100644 Context/IWaitForFrameworkInitialization.cs.meta delete mode 100644 Context/UnityContext.cs.meta delete mode 100644 DataStructures.meta delete mode 100644 DataStructures/CircularBufferIndexer.cs.meta delete mode 100644 DataStructures/FasterList.cs.meta delete mode 100644 DataStructures/HashableWeakReference.cs.meta delete mode 100644 DataStructures/Priority Queue.meta delete mode 100644 DataStructures/Priority Queue/HeapPriorityQueue.cs.meta delete mode 100644 DataStructures/Priority Queue/IPriorityQueue.cs.meta delete mode 100644 DataStructures/Priority Queue/PriorityQueueNode.cs.meta delete mode 100644 DataStructures/ReadOnlyDictionary.cs.meta delete mode 100644 DataStructures/ThreadSafeDictionary.cs.meta delete mode 100644 DataStructures/ThreadSafeQueue.cs.meta delete mode 100644 DataStructures/WeakReference.cs.meta delete mode 100644 ECS.meta delete mode 100644 ECS/Dispatcher.meta delete mode 100644 ECS/Dispatcher/DispatchOnChange.cs.meta delete mode 100644 ECS/Dispatcher/DispatcherOnSet.cs.meta delete mode 100644 ECS/EngineNodeDB.cs.meta delete mode 100644 ECS/EnginesRoot.cs.meta delete mode 100644 ECS/EntityDescriptor.cs.meta delete mode 100644 ECS/GenericEntityDescriptor.cs.meta delete mode 100644 ECS/GenericEntityDescriptorHolder.cs.meta delete mode 100644 ECS/ICallBackOnAddEngine.cs.meta delete mode 100644 ECS/IEngine.cs.meta delete mode 100644 ECS/IEngineNodeDB.cs.meta delete mode 100644 ECS/IEnginesRoot.cs.meta delete mode 100644 ECS/IEntityDescriptorHolder.cs.meta delete mode 100644 ECS/INode.cs.meta delete mode 100644 ECS/IRemoveEntityComponent.cs.meta delete mode 100644 ECS/Profiler.meta delete mode 100644 ECS/Profiler/Editor.meta delete mode 100644 ECS/Profiler/Editor/EngineProfiler.meta delete mode 100644 ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs.meta delete mode 100644 ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs.meta delete mode 100644 ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs.meta delete mode 100644 ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs.meta delete mode 100644 ECS/Profiler/EngineInfo.cs.meta delete mode 100644 ECS/Profiler/EngineProfiler.cs.meta delete mode 100644 ECS/Profiler/EngineProfilerBehaviour.cs.meta delete mode 100644 ECS/Sequencer.cs.meta delete mode 100644 ECS/SingleNodeEngine.cs.meta delete mode 100644 ECS/note.txt.meta delete mode 100644 Factories.meta delete mode 100644 Factories/IGameObjectFactory.cs.meta delete mode 100644 Factories/IMonoBehaviourFactory.cs.meta delete mode 100644 LICENSE.meta delete mode 100644 README.md.meta delete mode 100644 Utilities.meta delete mode 100644 Utilities/DesignByContract.cs.meta delete mode 100644 Utilities/Print.cs.meta delete mode 100644 Utilities/WeakActionStruct.cs.meta delete mode 100644 Utilities/WeakEvent.cs.meta diff --git a/Context.meta b/Context.meta deleted file mode 100644 index fe9df04..0000000 --- a/Context.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 9e37272d8aa8b6e4cb7b1fc15f1e57a8 -folderAsset: yes -timeCreated: 1431201025 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Context/ContextNotifier.cs.meta b/Context/ContextNotifier.cs.meta deleted file mode 100644 index 5bd27d3..0000000 --- a/Context/ContextNotifier.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: d74bed1689bb4114aa8a1f95cd95c788 -timeCreated: 1431300049 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Context/Factories.meta b/Context/Factories.meta deleted file mode 100644 index f14959d..0000000 --- a/Context/Factories.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: ec4bd87e898bf7c42823fb5ec2456b43 -folderAsset: yes -timeCreated: 1431630831 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Context/Factories/GameObjectFactory.cs.meta b/Context/Factories/GameObjectFactory.cs.meta deleted file mode 100644 index ef025ff..0000000 --- a/Context/Factories/GameObjectFactory.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 613a705e128b35e4f9361e29f4661191 -timeCreated: 1431630831 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Context/Factories/MonoBehaviourFactory.cs.meta b/Context/Factories/MonoBehaviourFactory.cs.meta deleted file mode 100644 index f19e685..0000000 --- a/Context/Factories/MonoBehaviourFactory.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 369e3378b91069c4aadba2af5aa8882b -timeCreated: 1431630831 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Context/ICompositionRoot.cs.meta b/Context/ICompositionRoot.cs.meta deleted file mode 100644 index 0ce1f88..0000000 --- a/Context/ICompositionRoot.cs.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 48c80cc65bea8254ba8082043f53405e -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} diff --git a/Context/IContextNotifer.cs.meta b/Context/IContextNotifer.cs.meta deleted file mode 100644 index 97fff82..0000000 --- a/Context/IContextNotifer.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a28c8df5741efe54ea588a1bcea92f0f -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Context/IWaitForFrameworkDestruction.cs.meta b/Context/IWaitForFrameworkDestruction.cs.meta deleted file mode 100644 index aa5adc5..0000000 --- a/Context/IWaitForFrameworkDestruction.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 36b1da25aaa515e4bad98fa0f61bc662 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Context/IWaitForFrameworkInitialization.cs.meta b/Context/IWaitForFrameworkInitialization.cs.meta deleted file mode 100644 index 3ba1f65..0000000 --- a/Context/IWaitForFrameworkInitialization.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 93cf465dd97f6144390620250c362485 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Context/UnityContext.cs.meta b/Context/UnityContext.cs.meta deleted file mode 100644 index b3c44ab..0000000 --- a/Context/UnityContext.cs.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 54e46daa2d2d723499a114d6d8de9dc2 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} diff --git a/DataStructures.meta b/DataStructures.meta deleted file mode 100644 index 0f993f8..0000000 --- a/DataStructures.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 6663fc83070cb0842b4665b38356feb2 -folderAsset: yes -timeCreated: 1463348260 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/DataStructures/CircularBufferIndexer.cs.meta b/DataStructures/CircularBufferIndexer.cs.meta deleted file mode 100644 index a7e75ad..0000000 --- a/DataStructures/CircularBufferIndexer.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 0d87fb4479e8365499c162fe0fc94acc -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/DataStructures/FasterList.cs.meta b/DataStructures/FasterList.cs.meta deleted file mode 100644 index b678658..0000000 --- a/DataStructures/FasterList.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: d19e59cbec974dd4d821a7dd21f87a88 -timeCreated: 1472488070 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/DataStructures/HashableWeakReference.cs.meta b/DataStructures/HashableWeakReference.cs.meta deleted file mode 100644 index 6d88c48..0000000 --- a/DataStructures/HashableWeakReference.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 0cfa789b3147c2e4e80d067693a58103 -timeCreated: 1455809369 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/DataStructures/Priority Queue.meta b/DataStructures/Priority Queue.meta deleted file mode 100644 index 8f88283..0000000 --- a/DataStructures/Priority Queue.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 8fffa27a4e8919a4db6fe1369e22e1b5 -folderAsset: yes -DefaultImporter: - userData: diff --git a/DataStructures/Priority Queue/HeapPriorityQueue.cs.meta b/DataStructures/Priority Queue/HeapPriorityQueue.cs.meta deleted file mode 100644 index b994121..0000000 --- a/DataStructures/Priority Queue/HeapPriorityQueue.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ac754b29409379046935c0890bab6dc5 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/DataStructures/Priority Queue/IPriorityQueue.cs.meta b/DataStructures/Priority Queue/IPriorityQueue.cs.meta deleted file mode 100644 index 21920be..0000000 --- a/DataStructures/Priority Queue/IPriorityQueue.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 5d399e4c2c1fe1f47833d6b70bf16184 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/DataStructures/Priority Queue/PriorityQueueNode.cs.meta b/DataStructures/Priority Queue/PriorityQueueNode.cs.meta deleted file mode 100644 index 1002889..0000000 --- a/DataStructures/Priority Queue/PriorityQueueNode.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2a6cc02a61a6ff549b1dcac74c71681f -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/DataStructures/ReadOnlyDictionary.cs.meta b/DataStructures/ReadOnlyDictionary.cs.meta deleted file mode 100644 index 9d767f0..0000000 --- a/DataStructures/ReadOnlyDictionary.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: e13aaf89d27048246bcf0d30c0993cf3 -timeCreated: 1459332966 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/DataStructures/ThreadSafeDictionary.cs.meta b/DataStructures/ThreadSafeDictionary.cs.meta deleted file mode 100644 index 07fdea7..0000000 --- a/DataStructures/ThreadSafeDictionary.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: db7c720ce4e437f48b1380223ba08192 -timeCreated: 1470829214 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/DataStructures/ThreadSafeQueue.cs.meta b/DataStructures/ThreadSafeQueue.cs.meta deleted file mode 100644 index 4b4d365..0000000 --- a/DataStructures/ThreadSafeQueue.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 57d029cda5232f8468d50d4eb3bf5489 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/DataStructures/WeakReference.cs.meta b/DataStructures/WeakReference.cs.meta deleted file mode 100644 index c9d3693..0000000 --- a/DataStructures/WeakReference.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 205cba76ee94d0e47aba9510ca92c540 -timeCreated: 1452175408 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS.meta b/ECS.meta deleted file mode 100644 index e1b48eb..0000000 --- a/ECS.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 5015ea56c030d6542bd4daa46f59e549 -folderAsset: yes -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Dispatcher.meta b/ECS/Dispatcher.meta deleted file mode 100644 index 41b7ff9..0000000 --- a/ECS/Dispatcher.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 2eae335fd33e33c4f951bf28bbf4914f -folderAsset: yes -timeCreated: 1462445195 -licenseType: Pro -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Dispatcher/DispatchOnChange.cs.meta b/ECS/Dispatcher/DispatchOnChange.cs.meta deleted file mode 100644 index ec4d3e7..0000000 --- a/ECS/Dispatcher/DispatchOnChange.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 908688d3b784d644e88a06e20f9ea159 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/ECS/Dispatcher/DispatcherOnSet.cs.meta b/ECS/Dispatcher/DispatcherOnSet.cs.meta deleted file mode 100644 index d868b59..0000000 --- a/ECS/Dispatcher/DispatcherOnSet.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: cbb1d54b291794b4686526222ee2bbb6 -timeCreated: 1471250507 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/EngineNodeDB.cs.meta b/ECS/EngineNodeDB.cs.meta deleted file mode 100644 index 3bc56aa..0000000 --- a/ECS/EngineNodeDB.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: b8aebbeeaf3d65d438359008c1f5d351 -timeCreated: 1459422025 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/EnginesRoot.cs.meta b/ECS/EnginesRoot.cs.meta deleted file mode 100644 index aa7b562..0000000 --- a/ECS/EnginesRoot.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 89361a8514a38544ebb87df0bd766dc5 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/ECS/EntityDescriptor.cs.meta b/ECS/EntityDescriptor.cs.meta deleted file mode 100644 index 0fdabbc..0000000 --- a/ECS/EntityDescriptor.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 42ab9afd9889862468f4afdac4fffd8b -timeCreated: 1457096903 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/GenericEntityDescriptor.cs.meta b/ECS/GenericEntityDescriptor.cs.meta deleted file mode 100644 index 840728d..0000000 --- a/ECS/GenericEntityDescriptor.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: fd70d1b3107162f4790b1b71a129818f -timeCreated: 1484485852 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/GenericEntityDescriptorHolder.cs.meta b/ECS/GenericEntityDescriptorHolder.cs.meta deleted file mode 100644 index fc5bfc6..0000000 --- a/ECS/GenericEntityDescriptorHolder.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: f2bc0783e8d4a7b49a84705c55d8b255 -timeCreated: 1498225965 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/ICallBackOnAddEngine.cs.meta b/ECS/ICallBackOnAddEngine.cs.meta deleted file mode 100644 index 80e5f96..0000000 --- a/ECS/ICallBackOnAddEngine.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 3928de9a08e5b534ab857ea8b5bebdaf -timeCreated: 1497524074 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/IEngine.cs.meta b/ECS/IEngine.cs.meta deleted file mode 100644 index 8ee8df3..0000000 --- a/ECS/IEngine.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 26f6a5fa5638d86448dd3f2d11d62f5c -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/ECS/IEngineNodeDB.cs.meta b/ECS/IEngineNodeDB.cs.meta deleted file mode 100644 index c346d94..0000000 --- a/ECS/IEngineNodeDB.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 44c24b91989f46048abc15039fd070bc -timeCreated: 1459422024 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/IEnginesRoot.cs.meta b/ECS/IEnginesRoot.cs.meta deleted file mode 100644 index b73c9f1..0000000 --- a/ECS/IEnginesRoot.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: b0078c1edf75425478b89366d5fe3bae -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/ECS/IEntityDescriptorHolder.cs.meta b/ECS/IEntityDescriptorHolder.cs.meta deleted file mode 100644 index bf596a5..0000000 --- a/ECS/IEntityDescriptorHolder.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 0badb413a22f42a4b9f68e356e88b07f -timeCreated: 1463438461 -licenseType: Free -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/INode.cs.meta b/ECS/INode.cs.meta deleted file mode 100644 index bd3f81b..0000000 --- a/ECS/INode.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: fc6bea8c56bd7284693db26502c6b65b -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/ECS/IRemoveEntityComponent.cs.meta b/ECS/IRemoveEntityComponent.cs.meta deleted file mode 100644 index d449680..0000000 --- a/ECS/IRemoveEntityComponent.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: bb9e778a1f85b0d46a065bbd5b549acd -timeCreated: 1462977663 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler.meta b/ECS/Profiler.meta deleted file mode 100644 index 3a39d53..0000000 --- a/ECS/Profiler.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 8d07544bb8b417f4a9eaefe0d4771d89 -folderAsset: yes -timeCreated: 1462355668 -licenseType: Pro -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/Editor.meta b/ECS/Profiler/Editor.meta deleted file mode 100644 index 48dd9b3..0000000 --- a/ECS/Profiler/Editor.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 71a4fc836cd9bde4bbb936a073804ec5 -folderAsset: yes -timeCreated: 1480683133 -licenseType: Pro -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/Editor/EngineProfiler.meta b/ECS/Profiler/Editor/EngineProfiler.meta deleted file mode 100644 index b802d05..0000000 --- a/ECS/Profiler/Editor/EngineProfiler.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 777a9420fd80746428f9d2c5b718fd2f -folderAsset: yes -timeCreated: 1462351213 -licenseType: Pro -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs.meta b/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs.meta deleted file mode 100644 index 02c6f19..0000000 --- a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerInspector.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: a2202d1747b86dc428310091a9c1a7ef -timeCreated: 1462469401 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs.meta b/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs.meta deleted file mode 100644 index b487da4..0000000 --- a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: e7b6bbeaaa16ab84aaa99c3311199efa -timeCreated: 1462351229 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs.meta b/ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs.meta deleted file mode 100644 index aee00e5..0000000 --- a/ECS/Profiler/Editor/EngineProfiler/EnginesMonitor.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 30f9f7f6468a96d4da2525c65ecfe637 -timeCreated: 1467633311 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs.meta b/ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs.meta deleted file mode 100644 index 11f6ff4..0000000 --- a/ECS/Profiler/Editor/EngineProfiler/ProfilerEditorLayout.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: de0de03babf2e9d4db95c2be94eb8c95 -timeCreated: 1462527509 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/EngineInfo.cs.meta b/ECS/Profiler/EngineInfo.cs.meta deleted file mode 100644 index 2463af8..0000000 --- a/ECS/Profiler/EngineInfo.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 93c5ba48b51186e44b7094eef7028c90 -timeCreated: 1462357591 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/EngineProfiler.cs.meta b/ECS/Profiler/EngineProfiler.cs.meta deleted file mode 100644 index 7c2b637..0000000 --- a/ECS/Profiler/EngineProfiler.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 74b59045fe5033b4b98facadd4d6b114 -timeCreated: 1462355668 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Profiler/EngineProfilerBehaviour.cs.meta b/ECS/Profiler/EngineProfilerBehaviour.cs.meta deleted file mode 100644 index 17446f2..0000000 --- a/ECS/Profiler/EngineProfilerBehaviour.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 688f5cf68b171ef4fa0f6aab49644c48 -timeCreated: 1462469401 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/Sequencer.cs.meta b/ECS/Sequencer.cs.meta deleted file mode 100644 index 87596cb..0000000 --- a/ECS/Sequencer.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 4e1f40937ca5027428ed7193729be1a5 -timeCreated: 1484487023 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/SingleNodeEngine.cs.meta b/ECS/SingleNodeEngine.cs.meta deleted file mode 100644 index cdb2bea..0000000 --- a/ECS/SingleNodeEngine.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 406a5e818b179b743b582c8fec087ac1 -timeCreated: 1469806920 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/ECS/note.txt.meta b/ECS/note.txt.meta deleted file mode 100644 index 9b67328..0000000 --- a/ECS/note.txt.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 11a3defaf51bc2147904eb737af5efb7 -TextScriptImporter: - userData: diff --git a/Factories.meta b/Factories.meta deleted file mode 100644 index 8a250da..0000000 --- a/Factories.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 7f7896118ef3c4949898b5c30aea0c47 -folderAsset: yes -timeCreated: 1484044925 -licenseType: Pro -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Factories/IGameObjectFactory.cs.meta b/Factories/IGameObjectFactory.cs.meta deleted file mode 100644 index dc6c4b9..0000000 --- a/Factories/IGameObjectFactory.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f3720a403a14c51489b5250365b7185c -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Factories/IMonoBehaviourFactory.cs.meta b/Factories/IMonoBehaviourFactory.cs.meta deleted file mode 100644 index 1a2f1b4..0000000 --- a/Factories/IMonoBehaviourFactory.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 22ba598cf1fd5124dbb4b999af89a0c5 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/LICENSE.meta b/LICENSE.meta deleted file mode 100644 index 0999b4e..0000000 --- a/LICENSE.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: ab819523a7b1394499edac4ffa37556b -timeCreated: 1440946962 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/README.md.meta b/README.md.meta deleted file mode 100644 index cabd763..0000000 --- a/README.md.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e772c63482a119748ba160ed807765a3 -timeCreated: 1440946962 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Utilities.meta b/Utilities.meta deleted file mode 100644 index d093762..0000000 --- a/Utilities.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: b7374ca2eb247d44c8783d7d23f9b89e -folderAsset: yes -timeCreated: 1484394896 -licenseType: Pro -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Utilities/DesignByContract.cs.meta b/Utilities/DesignByContract.cs.meta deleted file mode 100644 index 729468b..0000000 --- a/Utilities/DesignByContract.cs.meta +++ /dev/null @@ -1,10 +0,0 @@ -fileFormatVersion: 2 -guid: 5a6942e14a8d33d46a05b33d50392652 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Utilities/Print.cs.meta b/Utilities/Print.cs.meta deleted file mode 100644 index 121f044..0000000 --- a/Utilities/Print.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 1f5eede659a66c64a9af2ec703db2691 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Utilities/WeakActionStruct.cs.meta b/Utilities/WeakActionStruct.cs.meta deleted file mode 100644 index 49656b3..0000000 --- a/Utilities/WeakActionStruct.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 1662357721652524593d7b0f731aef45 -timeCreated: 1484483913 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Utilities/WeakEvent.cs.meta b/Utilities/WeakEvent.cs.meta deleted file mode 100644 index 884293e..0000000 --- a/Utilities/WeakEvent.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: e2ee3763e7dffd4459c588eda6867ddd -timeCreated: 1484480295 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: From d023d2fe467e8bf93ebbfa8dfe47c216eb831b54 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sat, 1 Jul 2017 16:11:21 +0100 Subject: [PATCH 3/7] ignore meta files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index f1249a2..ac529bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /EntitySystem/note.txt /EntitySystem/note.txt.meta +/*.meta +*.meta From 01d015a77031cbba04e9f231e9bf8814c794540c Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sun, 2 Jul 2017 16:49:44 +0100 Subject: [PATCH 4/7] remove file --- ECS/note.txt | 111 --------------------------------------------------- 1 file changed, 111 deletions(-) delete mode 100644 ECS/note.txt diff --git a/ECS/note.txt b/ECS/note.txt deleted file mode 100644 index c041193..0000000 --- a/ECS/note.txt +++ /dev/null @@ -1,111 +0,0 @@ -systems do not hold component data, but only system states -systems cannot be injected -systems are SRP and OCP -systems communicates between component, mediators, producer/consumer, observers. producer/consumer and observers must be defined in the layer of the engine. -systems can have injected dependencies - -components don't have logic -components can have only getter and setter -components cannot define patterns that requires logic. -components cannot issues commands - -High Cohesion[edit] -Main article: Cohesion (computer science) -High Cohesion is an evaluative pattern that attempts to keep objects appropriately focused, manageable and understandable. High cohesion is generally used in support of Low Coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system. Alternatively, low cohesion is a situation in which a given element has too many unrelated responsibilities. Elements with low cohesion often suffer from being hard to comprehend, hard to reuse, hard to maintain and averse to change.[3] - -Low Coupling[edit] -Main article: Loose coupling -Low Coupling is an evaluative pattern, which dictates how to assign responsibilities to support: - -lower dependency between the classes, -change in one class having lower impact on other classes, -higher reuse potential. - -events, observers and mediators have the inconvience to hold the reference to the engine, which forces to use cleanup if the engine must be removed. -Observers are easy to clean up from the engine. Mediators needs to be integrated to the framework to be simple to clean up. Component events need the clean up function. -producer/consumer has the inconvienent to force check the number of jobs available everyframe - -Engine can't be removed, they can only be disabled, but the logic of disabling must be handled by the engine itself - -Should components have just one element? Should engines use just nodes? Components are ditacted by the entities and Nodes by the engines - -http://thelinuxlich.github.io/artemis_CSharp/ - -differences: components no events, everthing must be update -give more responsabiltiy to the user, semplicity - -https://github.com/sschmid/Entitas-CSharp/wiki/Overview - -no groups, no queries - -http://entity-systems.wikidot.com/es-articles - -http://www.ashframework.org/ - -it's very important to give a namespace to the engines. In this way it's impossible to create semantically wrong nodes (PlayerNode Vs TargetNode) - -ToDo: - -it's not safe to remove an engine without having called being denitialised internal states. A special ClearOnRemove function must be added for each engine - -namespace GameFramework.RayCast -{ - public class RayCastEngineEngine - { - public RayCastEngine(RayCastEmployer jobList) - { - jobList.onJobassigned += OnRaycastRequested; - } - - public void Add(IComponent obj) - {} - - public void Remove(IComponent obj) - {} - - void OnRaycastRequested(RayCastJob job) - { - RaycastHit shootHit; - - Physics.Raycast(job.rayVector, out shootHit, job.range, _enemyMask); - - job.Done(shootHit); - } - - RayCastEmployer _employer; - - int _enemyMask; - } - - public struct RayCastJob - { - readonly public Ray rayVector; - readonly public float range; - readonly public Action Done; - - public RayCastJob(Ray direction, float distance, Action OnDone) - { - rayVector = direction; - range = distance; - Done = OnDone; - } - } - - public class RayCastEmployer - { - public event Action onJobassigned; - - public void AssignJob(RayCastJob data, Action onJobdone) - { - onJobassigned(data); - } - } -} - -if your code can be read as - -A tells B to do something is direct -A register B event is indirect -althoggh if B tells A something through event is direct again. B must say something like I don't know who you are, but this just happened. you say B.SomethingHappenedToMe() not B.YouMustDoThis(); - -un engine non deve mai avere concetti di un altro engine. dire all'engine sonoro suona morte � sbagliato. � l'engine death che triggera l'evento e l'engine sound ad ascoltarlo. From a2f1f384fa8969d205de5b2474dd61708b809109 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Tue, 26 Sep 2017 00:38:38 +0100 Subject: [PATCH 5/7] working on something new --- DataStructures/FasterList.cs | 33 ++- .../Priority Queue/HeapPriorityQueue.cs | 32 +-- DataStructures/ThreadSafeDictionary.cs | 247 ++++++++---------- ECS/EngineNodeDB.cs | 54 ++-- ECS/EnginesRoot.cs | 179 +++++++------ ECS/EntityDescriptor.cs | 28 +- ECS/IEngine.cs | 20 +- ECS/IEngineNodeDB.cs | 2 + ECS/NodeEngineWrapper.cs | 66 +++++ ECS/NodeSubmissionScheduler.cs | 9 + .../EngineProfiler/EngineProfilerMenuItem.cs | 2 +- ECS/Profiler/EngineProfiler.cs | 4 +- ECS/SingleNodeEngine.cs | 6 +- .../Unity/UnitySumbmissionNodeScheduler.cs | 38 +++ Utilities/DesignByContract.cs | 30 +-- 15 files changed, 465 insertions(+), 285 deletions(-) create mode 100644 ECS/NodeEngineWrapper.cs create mode 100644 ECS/NodeSubmissionScheduler.cs create mode 100644 Extensions/Unity/UnitySumbmissionNodeScheduler.cs diff --git a/DataStructures/FasterList.cs b/DataStructures/FasterList.cs index ae44d60..bc96c16 100644 --- a/DataStructures/FasterList.cs +++ b/DataStructures/FasterList.cs @@ -193,7 +193,8 @@ namespace Svelto.DataStructures { public FasterListThreadSafe(FasterList list) { - _list = list; + if (list == null) throw new ArgumentException("invalid list"); + _list = list; _lockQ = new ReaderWriterLockSlim(); } @@ -288,14 +289,14 @@ namespace Svelto.DataStructures public void CopyTo(T[] array, int arrayIndex) { - _lockQ.EnterWriteLock(); + _lockQ.EnterReadLock(); try { _list.CopyTo(array, arrayIndex); } finally { - _lockQ.ExitWriteLock(); + _lockQ.ExitReadLock(); } } @@ -351,6 +352,19 @@ namespace Svelto.DataStructures } } + public void UnorderredRemoveAt(int index) + { + _lockQ.EnterWriteLock(); + try + { + _list.UnorderredRemoveAt(index); + } + finally + { + _lockQ.ExitWriteLock(); + } + } + IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException(); @@ -368,8 +382,6 @@ namespace Svelto.DataStructures public struct FasterReadOnlyListCast : IList where U:T { - public static FasterList DefaultList = new FasterList(); - public int Count { get { return _list.Count; } } public bool IsReadOnly { get { return true; } } @@ -402,7 +414,7 @@ namespace Svelto.DataStructures public void CopyTo(U[] array, int arrayIndex) { - throw new NotImplementedException(); + Array.Copy(_list.ToArrayFast(), 0, array, arrayIndex, _list.Count); } public bool Remove(U item) @@ -440,6 +452,8 @@ namespace Svelto.DataStructures public class FasterList : IList { + public static FasterList DefaultList = new FasterList(); + const int MIN_SIZE = 4; public int Count @@ -752,14 +766,15 @@ namespace Svelto.DataStructures Resize(_count); } - public bool Reuse(int index, out T result) + public bool Reuse(int index, out U result) + where U:class, T { - result = default(T); + result = default(U); if (index >= _buffer.Length) return false; - result = _buffer[index]; + result = (U)_buffer[index]; return result != null; } diff --git a/DataStructures/Priority Queue/HeapPriorityQueue.cs b/DataStructures/Priority Queue/HeapPriorityQueue.cs index c30e06d..2774d57 100644 --- a/DataStructures/Priority Queue/HeapPriorityQueue.cs +++ b/DataStructures/Priority Queue/HeapPriorityQueue.cs @@ -13,9 +13,9 @@ namespace Svelto.DataStructures public sealed class HeapPriorityQueue : IPriorityQueue where T : PriorityQueueNode { - private int _numNodes; - private readonly FasterList _nodes; - private long _numNodesEverEnqueued; + int _numNodes; + private readonly FasterList _nodes; + long _numNodesEverEnqueued; /// /// Instantiate a new Priority Queue @@ -101,10 +101,10 @@ namespace Svelto.DataStructures CascadeUp(_nodes[_numNodes]); } - #if NET_VERSION_4_5 +#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - private void Swap(T node1, T node2) +#endif + void Swap(T node1, T node2) { //Swap the nodes _nodes[node1.QueueIndex] = node2; @@ -117,14 +117,14 @@ namespace Svelto.DataStructures } //Performance appears to be slightly better when this is NOT inlined o_O - private void CascadeUp(T node) + void CascadeUp(T node) { //aka Heapify-up int parent = node.QueueIndex / 2; - while(parent >= 1) + while (parent >= 1) { T parentNode = _nodes[parent]; - if(HasHigherPriority(parentNode, node)) + if (HasHigherPriority(parentNode, node)) break; //Node has lower priority value, so move it up the heap @@ -134,9 +134,9 @@ namespace Svelto.DataStructures } } - #if NET_VERSION_4_5 +#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif +#endif private void CascadeDown(T node) { //aka Heapify-down @@ -198,10 +198,10 @@ namespace Svelto.DataStructures /// Returns true if 'higher' has higher priority than 'lower', false otherwise. /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false /// - #if NET_VERSION_4_5 +#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] - #endif - private bool HasHigherPriority(T higher, T lower) +#endif + bool HasHigherPriority(T higher, T lower) { return (higher.Priority < lower.Priority || (higher.Priority == lower.Priority && higher.InsertionIndex < lower.InsertionIndex)); @@ -242,13 +242,13 @@ namespace Svelto.DataStructures OnNodeUpdated(node); } - private void OnNodeUpdated(T node) + void OnNodeUpdated(T node) { //Bubble the updated node up or down as appropriate int parentIndex = node.QueueIndex / 2; T parentNode = _nodes[parentIndex]; - if(parentIndex > 0 && HasHigherPriority(node, parentNode)) + if (parentIndex > 0 && HasHigherPriority(node, parentNode)) { CascadeUp(node); } diff --git a/DataStructures/ThreadSafeDictionary.cs b/DataStructures/ThreadSafeDictionary.cs index 1505547..0bfb662 100644 --- a/DataStructures/ThreadSafeDictionary.cs +++ b/DataStructures/ThreadSafeDictionary.cs @@ -31,10 +31,15 @@ namespace Svelto.DataStructures { get { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return dict.Count; } + finally + { + LockQ.ExitReadLock(); + } } } @@ -42,10 +47,15 @@ namespace Svelto.DataStructures { get { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return dict.IsReadOnly; } + finally + { + LockQ.ExitReadLock(); + } } } @@ -53,10 +63,15 @@ namespace Svelto.DataStructures { get { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return new FasterList(dict.Keys); } + finally + { + LockQ.ExitReadLock(); + } } } @@ -64,10 +79,15 @@ namespace Svelto.DataStructures { get { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return new FasterList(dict.Values); } + finally + { + LockQ.ExitReadLock(); + } } } @@ -75,91 +95,146 @@ namespace Svelto.DataStructures { get { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return dict[key]; } + finally + { + LockQ.ExitReadLock(); + } } set { - using (new WriteLock(dictionaryLock)) + LockQ.EnterWriteLock(); + try { dict[key] = value; } + finally + { + LockQ.ExitWriteLock(); + } } } public virtual void Add(KeyValuePair item) { - using (new WriteLock(dictionaryLock)) + LockQ.EnterWriteLock(); + try { dict.Add(item); } + finally + { + LockQ.ExitWriteLock(); + } } public virtual void Clear() { - using (new WriteLock(dictionaryLock)) + LockQ.EnterWriteLock(); + try { dict.Clear(); } + finally + { + LockQ.ExitWriteLock(); + } } public virtual bool Contains(KeyValuePair item) { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return dict.Contains(item); } + finally + { + LockQ.ExitReadLock(); + } } public virtual void CopyTo(KeyValuePair[] array, int arrayIndex) { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { dict.CopyTo(array, arrayIndex); } + finally + { + LockQ.ExitReadLock(); + } } public virtual bool Remove(KeyValuePair item) { - using (new WriteLock(dictionaryLock)) + LockQ.EnterWriteLock(); + try { return dict.Remove(item); } + finally + { + LockQ.ExitWriteLock(); + } } public virtual void Add(TKey key, TValue value) { - using (new WriteLock(dictionaryLock)) + LockQ.EnterWriteLock(); + try { dict.Add(key, value); } + finally + { + LockQ.ExitWriteLock(); + } } public virtual bool ContainsKey(TKey key) { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return dict.ContainsKey(key); } + finally + { + LockQ.ExitReadLock(); + } } public virtual bool Remove(TKey key) { - using (new WriteLock(dictionaryLock)) + LockQ.EnterWriteLock(); + try { return dict.Remove(key); } + finally + { + LockQ.ExitWriteLock(); + } } public virtual bool TryGetValue(TKey key, out TValue value) { - using (new ReadOnlyLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { return dict.TryGetValue(key, out value); } + finally + { + LockQ.ExitReadLock(); + } } /// @@ -169,7 +244,8 @@ namespace Svelto.DataStructures /// New Value public void MergeSafe(TKey key, TValue newValue) { - using (new WriteLock(dictionaryLock)) + LockQ.EnterWriteLock(); + try { // take a writelock immediately since we will always be writing if (dict.ContainsKey(key)) @@ -177,6 +253,10 @@ namespace Svelto.DataStructures dict.Add(key, newValue); } + finally + { + LockQ.ExitWriteLock(); + } } /// @@ -185,132 +265,29 @@ namespace Svelto.DataStructures /// Key to remove public void RemoveSafe(TKey key) { - using (new ReadLock(dictionaryLock)) + LockQ.EnterReadLock(); + try { if (dict.ContainsKey(key)) - using (new WriteLock(dictionaryLock)) - { - dict.Remove(key); - } + LockQ.EnterWriteLock(); + try + { + dict.Remove(key); + } + finally + { + LockQ.ExitWriteLock(); + } + } + finally + { + LockQ.ExitReadLock(); } } // This is the internal dictionary that we are wrapping readonly IDictionary dict; - [NonSerialized] readonly ReaderWriterLockSlim dictionaryLock = Locks.GetLockInstance(LockRecursionPolicy.NoRecursion); - } - - public static class Locks - { - public static ReaderWriterLockSlim GetLockInstance() - { - return GetLockInstance(LockRecursionPolicy.SupportsRecursion); - } - - public static ReaderWriterLockSlim GetLockInstance(LockRecursionPolicy recursionPolicy) - { - return new ReaderWriterLockSlim(recursionPolicy); - } - - public static void GetReadLock(ReaderWriterLockSlim locks) - { - var lockAcquired = false; - while (!lockAcquired) - lockAcquired = locks.TryEnterUpgradeableReadLock(1); - } - - public static void GetReadOnlyLock(ReaderWriterLockSlim locks) - { - var lockAcquired = false; - while (!lockAcquired) - lockAcquired = locks.TryEnterReadLock(1); - } - - public static void GetWriteLock(ReaderWriterLockSlim locks) - { - var lockAcquired = false; - while (!lockAcquired) - lockAcquired = locks.TryEnterWriteLock(1); - } - - public static void ReleaseLock(ReaderWriterLockSlim locks) - { - ReleaseWriteLock(locks); - ReleaseReadLock(locks); - ReleaseReadOnlyLock(locks); - } - - public static void ReleaseReadLock(ReaderWriterLockSlim locks) - { - if (locks.IsUpgradeableReadLockHeld) - locks.ExitUpgradeableReadLock(); - } - - public static void ReleaseReadOnlyLock(ReaderWriterLockSlim locks) - { - if (locks.IsReadLockHeld) - locks.ExitReadLock(); - } - - public static void ReleaseWriteLock(ReaderWriterLockSlim locks) - { - if (locks.IsWriteLockHeld) - locks.ExitWriteLock(); - } - } - - public abstract class BaseLock : IDisposable - { - protected ReaderWriterLockSlim _Locks; - - public BaseLock(ReaderWriterLockSlim locks) - { - _Locks = locks; - } - - public abstract void Dispose(); - } - - public class ReadLock : BaseLock - { - public ReadLock(ReaderWriterLockSlim locks) - : base(locks) - { - Locks.GetReadLock(_Locks); - } - - public override void Dispose() - { - Locks.ReleaseReadLock(_Locks); - } - } - - public class ReadOnlyLock : BaseLock - { - public ReadOnlyLock(ReaderWriterLockSlim locks) - : base(locks) - { - Locks.GetReadOnlyLock(_Locks); - } - - public override void Dispose() - { - Locks.ReleaseReadOnlyLock(_Locks); - } - } - - public class WriteLock : BaseLock - { - public WriteLock(ReaderWriterLockSlim locks) - : base(locks) - { - Locks.GetWriteLock(_Locks); - } - - public override void Dispose() - { - Locks.ReleaseWriteLock(_Locks); - } + readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim(); } } diff --git a/ECS/EngineNodeDB.cs b/ECS/EngineNodeDB.cs index 8c73fa2..4a31542 100644 --- a/ECS/EngineNodeDB.cs +++ b/ECS/EngineNodeDB.cs @@ -10,29 +10,39 @@ namespace Svelto.ECS Dictionary> nodesDBdic, Dictionary> nodesDBgroups) { - _nodesDB = nodesDB; - _nodesDBdic = nodesDBdic; - _nodesDBgroups = nodesDBgroups; + _nodesDB = new DataStructures.WeakReference>>(nodesDB); + _nodesDBdic = new DataStructures.WeakReference>>(nodesDBdic); + _nodesDBgroups = new DataStructures.WeakReference>>(nodesDBgroups); } public FasterReadOnlyListCast QueryNodes() where T:INode { var type = typeof(T); - if (_nodesDB.ContainsKey(type) == false) + if (_nodesDB.IsValid == false || _nodesDB.Target.ContainsKey(type) == false) return RetrieveEmptyNodeList(); - return new FasterReadOnlyListCast(_nodesDB[type]); + return new FasterReadOnlyListCast(_nodesDB.Target[type]); } + /* public FasterReadOnlyList QueryStructNodes() where T:struct + { + var type = typeof(T); + + if (_nodesDBStructs.ContainsKey(type) == false) + return RetrieveEmptyStructNodeList(); + + return new FasterReadOnlyList(((StructNodeList)(_nodesDBStructs[type])).list); + }*/ + public ReadOnlyDictionary QueryIndexableNodes() where T:INode { var type = typeof(T); - if (_nodesDBdic.ContainsKey(type) == false) + if (_nodesDB.IsValid == false || _nodesDBdic.Target.ContainsKey(type) == false) return _defaultEmptyNodeDict; - return new ReadOnlyDictionary(_nodesDBdic[type]); + return new ReadOnlyDictionary(_nodesDBdic.Target[type]); } public T QueryNodeFromGroup(int groupID) where T : INode @@ -49,10 +59,10 @@ namespace Svelto.ECS { var type = typeof(T); - if (_nodesDBgroups.ContainsKey(type) == false) + if (_nodesDBgroups.IsValid == false || _nodesDBgroups.Target.ContainsKey(type) == false) return RetrieveEmptyNodeList(); - return new FasterReadOnlyListCast(_nodesDBgroups[type]); + return new FasterReadOnlyListCast(_nodesDBgroups.Target[type]); } public bool QueryNode(int ID, out T node) where T:INode @@ -61,7 +71,7 @@ namespace Svelto.ECS INode internalNode; - if (_nodesDBdic.ContainsKey(type) && _nodesDBdic[type].TryGetValue(ID, out internalNode)) + if (_nodesDBdic.IsValid && _nodesDBdic.Target.ContainsKey(type) && _nodesDBdic.Target[type].TryGetValue(ID, out internalNode)) { node = (T)internalNode; @@ -79,7 +89,7 @@ namespace Svelto.ECS INode internalNode; - if (_nodesDBdic.ContainsKey(type) && _nodesDBdic[type].TryGetValue(ID, out internalNode)) + if (_nodesDBdic.IsValid && _nodesDBdic.Target.ContainsKey(type) && _nodesDBdic.Target[type].TryGetValue(ID, out internalNode)) return (T)internalNode; throw new Exception("Node Not Found"); @@ -87,17 +97,31 @@ namespace Svelto.ECS static FasterReadOnlyListCast RetrieveEmptyNodeList() where T : INode { - return new FasterReadOnlyListCast(FasterReadOnlyListCast.DefaultList); + return new FasterReadOnlyListCast(FasterList.DefaultList); + } + + static FasterReadOnlyList RetrieveEmptyStructNodeList() where T : struct + { + return new FasterReadOnlyList(FasterList.DefaultList); } - Dictionary> _nodesDB; - Dictionary> _nodesDBdic; - Dictionary> _nodesDBgroups; + Svelto.DataStructures.WeakReference>> _nodesDB; + Svelto.DataStructures.WeakReference>> _nodesDBdic; + Svelto.DataStructures.WeakReference>> _nodesDBgroups; +// Dictionary _nodesDBStructs; //Dictionary> _nodesDB; //Dictionary> _nodesDBdic; // Dictionary> _nodesDBgroups; ReadOnlyDictionary _defaultEmptyNodeDict = new ReadOnlyDictionary(new Dictionary()); + + class StructNodeList + { } + + class StructNodeList : StructNodeList where T : struct + { + public FasterList list = new FasterList(); + } } } diff --git a/ECS/EnginesRoot.cs b/ECS/EnginesRoot.cs index d3af55c..0807d13 100644 --- a/ECS/EnginesRoot.cs +++ b/ECS/EnginesRoot.cs @@ -4,7 +4,8 @@ using System.Collections.Generic; using Svelto.DataStructures; using UnityEngine; using WeakReference = Svelto.DataStructures.WeakReference; - +using Svelto.ECS.NodeSchedulers; +using Svelto.ECS.Internal; #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR using Svelto.ECS.Profiler; #endif @@ -14,26 +15,11 @@ using System.Reflection; namespace Svelto.ECS { - class Scheduler : MonoBehaviour - { - IEnumerator Start() - { - while (true) - { - yield return new WaitForEndOfFrame(); - - OnTick(); - } - } - - internal Action OnTick; - } - public sealed class EnginesRoot : IEnginesRoot, IEntityFactory { - public EnginesRoot() + public EnginesRoot(NodeSubmissionScheduler nodeScheduler) { - _nodeEngines = new Dictionary>>(); + _nodeEngines = new Dictionary>(); _engineRootWeakReference = new WeakReference(this); _otherEnginesReferences = new FasterList(); @@ -45,9 +31,8 @@ namespace Svelto.ECS _nodesDBgroups = new Dictionary>(); - GameObject go = new GameObject("ECSScheduler"); - - go.AddComponent().OnTick += SubmitNodes; + _scheduler = nodeScheduler; + _scheduler.Schedule(SubmitNodes); #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR GameObject debugEngineObject = new GameObject("Engine Debugger"); @@ -109,6 +94,28 @@ namespace Svelto.ECS _groupNodesToAdd.Clear(); } + public void AddEngine(INodeEngine engine) where T:class, INode + { + AddEngine(new NodeEngineWrapper(engine)); + + if (engine is IQueryableNodeEngine) + (engine as IQueryableNodeEngine).nodesDB = new EngineNodeDB(_nodesDB, _nodesDBdic, _nodesDBgroups); + } + + public void AddEngine(INodeEngine engine) where T:class, INode where U:class, INode + { + AddEngine(new NodeEngineWrapper(engine)); + AddEngine((INodeEngine)(engine)); + } + + public void AddEngine(INodeEngine engine) where T:class, INode + where U:class, INode + where V:class, INode + { + AddEngine(new NodeEngineWrapper(engine)); + AddEngine((INodeEngine)(engine)); + } + public void AddEngine(IEngine engine) { #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR @@ -125,9 +132,7 @@ namespace Svelto.ECS } else { - var engineType = engine.GetType(); -// Type baseInterface = null; #if !NETFX_CORE var baseType = engineType.BaseType; @@ -138,12 +143,28 @@ namespace Svelto.ECS if (baseType.IsConstructedGenericType #endif - && baseType.GetGenericTypeDefinition() == typeof (SingleNodeEngine<>)) + && baseType.GetGenericTypeDefinition() == typeof(SingleNodeEngine<>)) { - AddEngine(engine as INodeEngine, baseType.GetGenericArguments(), _nodeEngines); + AddEngine(engine as INodeEngine, baseType.GetGenericArguments(), _nodeEngines); } else - _otherEnginesReferences.Add(engine); + { + bool found = false; + + for (int i = 0, maxLength = engineType.GetInterfaces().Length; i < maxLength; i++) + { + var type = engineType.GetInterfaces()[i]; + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(INodeEngine<>)) + { + AddEngine(engine as INodeEngine, type.GetGenericArguments(), _nodeEngines); + + found = true; + } + } + + if (found == false) + _otherEnginesReferences.Add(engine); + } } if (engine is ICallBackOnAddEngine) @@ -152,10 +173,10 @@ namespace Svelto.ECS public void BuildEntity(int ID, EntityDescriptor ed) { - var entityNodes = ed.BuildNodes(ID, (node) => + var entityNodes = ed.BuildNodes(ID, (nodes) => { if (_engineRootWeakReference.IsValid == true) - InternalRemove(node); + InternalRemove(nodes); }); _nodesToAdd.AddRange(entityNodes); @@ -176,26 +197,26 @@ namespace Svelto.ECS /// public void BuildEntityGroup(int groupID, EntityDescriptor ed) { - var entityNodes = ed.BuildNodes(groupID, (node) => + var entityNodes = ed.BuildNodes(groupID, (nodes) => { if (_engineRootWeakReference.IsValid == true) - InternalGroupRemove(node); + InternalGroupRemove(nodes); }); _groupNodesToAdd.AddRange(entityNodes); } - static void AddEngine(T engine, Type[] types, Dictionary>> engines) where T : INodeEngine + static void AddEngine(INodeEngine engine, Type[] types, Dictionary> engines) { for (int i = 0; i < types.Length; i++) { - FasterList> list; + FasterList list; var type = types[i]; if (engines.TryGetValue(type, out list) == false) { - list = new FasterList>(); + list = new FasterList(); engines.Add(type, list); } @@ -215,7 +236,7 @@ namespace Svelto.ECS AddNodeToNodesDictionary(node, nodeType); } - void AddNodeToTheDB(T node, Type nodeType) where T : INode + void AddNodeToTheDB(INode node, Type nodeType) { FasterList nodes; if (_nodesDB.TryGetValue(nodeType, out nodes) == false) @@ -226,7 +247,7 @@ namespace Svelto.ECS AddNodeToNodesDictionary(node, nodeType); } - void AddNodeToNodesDictionary(T node, Type nodeType) where T : INode + void AddNodeToNodesDictionary(INode node, Type nodeType) { if (node is NodeWithID) { @@ -238,9 +259,9 @@ namespace Svelto.ECS } } - void AddNodeToTheSuitableEngines(T node, Type nodeType) where T : INode + void AddNodeToTheSuitableEngines(INode node, Type nodeType) { - FasterList> enginesForNode; + FasterList enginesForNode; if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) { @@ -255,91 +276,85 @@ namespace Svelto.ECS } } - void RemoveNodeFromTheDB(T node, Type nodeType) where T : INode - { - FasterList nodes; - if (_nodesDB.TryGetValue(nodeType, out nodes) == true) - nodes.UnorderredRemove(node); //should I remove it from the dictionary if length is zero? - - RemoveNodeFromNodesDictionary(node, nodeType); - } - - void RemoveNodeFromNodesDictionary(T node, Type nodeType) where T : INode + void RemoveNodesFromDB(Dictionary> DB, FasterReadOnlyList nodes) { - if (node is NodeWithID) + for (int i = 0; i < nodes.Count; i++) { - Dictionary nodesDic; + FasterList nodesInDB; - if (_nodesDBdic.TryGetValue(nodeType, out nodesDic)) - nodesDic.Remove((node as NodeWithID).ID); - } - } + var node = nodes[i]; + var nodeType = node.GetType(); + + if (DB.TryGetValue(nodeType, out nodesInDB) == true) + nodesInDB.UnorderredRemove(node); //should I remove it from the dictionary if length is zero? - void RemoveNodeFromGroupDB(T node, Type nodeType) where T : INode - { - FasterList nodes; - if (_nodesDBgroups.TryGetValue(nodeType, out nodes) == true) - nodes.UnorderredRemove(node); //should I remove it from the dictionary if length is zero? + if (node is NodeWithID) + { + Dictionary nodesDic; - RemoveNodeFromNodesDictionary(node, nodeType); + if (_nodesDBdic.TryGetValue(nodeType, out nodesDic)) + nodesDic.Remove((node as NodeWithID).ID); + } + } } - void RemoveNodeFromEngines(T node, Type nodeType) where T : INode + void RemoveNodesFromEngines(FasterReadOnlyList nodes) { - FasterList> enginesForNode; - - if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) + for (int i = 0; i < nodes.Count; i++) { - for (int j = 0; j < enginesForNode.Count; j++) + FasterList enginesForNode; + var node = nodes[i]; + + if (_nodeEngines.TryGetValue(node.GetType(), out enginesForNode)) { + for (int j = 0; j < enginesForNode.Count; j++) + { #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, enginesForNode[j], node); + EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, enginesForNode[j], node); #else - enginesForNode[j].Remove(node); + enginesForNode[j].Remove(node); #endif + } } } } #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - void AddNodeToEngine(INodeEngine engine, INode node) + static void AddNodeToEngine(INodeEngine engine, INode node) { engine.Add(node); } - void RemoveNodeFromEngine(INodeEngine engine, INode node) + static void RemoveNodeFromEngine(INodeEngine engine, INode node) { engine.Remove(node); } #endif - - void InternalRemove(T node) where T : INode - { - Type nodeType = node.GetType(); - RemoveNodeFromEngines(node, nodeType); - RemoveNodeFromTheDB(node, node.GetType()); + void InternalRemove(FasterReadOnlyList nodes) + { + RemoveNodesFromEngines(nodes); + RemoveNodesFromDB(_nodesDB, nodes); } - void InternalGroupRemove(T node) where T : INode + void InternalGroupRemove(FasterReadOnlyList nodes) { - Type nodeType = node.GetType(); - - RemoveNodeFromEngines(node, nodeType); - RemoveNodeFromGroupDB(node, node.GetType()); + RemoveNodesFromEngines(nodes); + RemoveNodesFromDB(_nodesDBgroups, nodes); } - Dictionary>> _nodeEngines; + Dictionary> _nodeEngines; FasterList _otherEnginesReferences; Dictionary> _nodesDB; - Dictionary> _nodesDBdic; - Dictionary> _nodesDBgroups; + Dictionary> _nodesDBdic; + FasterList _nodesToAdd; FasterList _groupNodesToAdd; WeakReference _engineRootWeakReference; + NodeSubmissionScheduler _scheduler; } } diff --git a/ECS/EntityDescriptor.cs b/ECS/EntityDescriptor.cs index 7dab7ee..d818dce 100644 --- a/ECS/EntityDescriptor.cs +++ b/ECS/EntityDescriptor.cs @@ -15,6 +15,11 @@ namespace Svelto.ECS _nodesToBuild = nodesToBuild; } + /* protected EntityDescriptor(IStructNodeBuilder[] structNodesToBuild) + { + _structNodesToBuild = structNodesToBuild; + }*/ + public void AddImplementors(params object[] componentsImplementor) { var implementors = new object[componentsImplementor.Length + _implementors.Length]; @@ -25,23 +30,22 @@ namespace Svelto.ECS _implementors = implementors; } - public virtual FasterList BuildNodes(int ID, Action removeAction) + public virtual FasterList BuildNodes(int ID, Action> removeAction) { var nodes = new FasterList(); - for (int index = 0; index < _nodesToBuild.Length; index++) + for (int index = _nodesToBuild.Length - 1; index >= 0; index--) { var nodeBuilder = _nodesToBuild[index]; var node = FillNode(nodeBuilder.Build(ID), () => { - for (int i = 0; i < nodes.Count; i++) - removeAction(nodes[i]); + removeAction(new FasterReadOnlyList()); nodes.Clear(); } ); - nodes.Add (node); + nodes.Add(node); } return nodes; @@ -88,7 +92,8 @@ namespace Svelto.ECS object[] _implementors; - readonly INodeBuilder[] _nodesToBuild; + readonly INodeBuilder[] _nodesToBuild; + // readonly IStructNodeBuilder[] _structNodesToBuild; } public interface INodeBuilder @@ -105,4 +110,15 @@ namespace Svelto.ECS return (NodeType)node; } } +/* + public interface IStructNodeBuilder + {} + + public class StructNodeBuilder : IStructNodeBuilder where NodeType : struct + { + public NodeType Build() + { + return new NodeType(); + } + }*/ } diff --git a/ECS/IEngine.cs b/ECS/IEngine.cs index 5bddc66..3d67fcd 100644 --- a/ECS/IEngine.cs +++ b/ECS/IEngine.cs @@ -9,7 +9,25 @@ namespace Svelto.ECS void Remove(TNodeType obj); } - public interface INodesEngine : INodeEngine + public interface INodeEngine:INodeEngine where T:INode where U:INode + { + void Add(T obj); + void Remove(T obj); + } + + public interface INodeEngine:INodeEngine where T:INode where U:INode where V:INode + { + void Add(T obj); + void Remove(T obj); + } + + public interface INodeEngine:IEngine + { + void Add(INode obj); + void Remove(INode obj); + } + + public interface INodesEngine : INodeEngine { System.Type[] AcceptedNodes(); } diff --git a/ECS/IEngineNodeDB.cs b/ECS/IEngineNodeDB.cs index 069d532..6103ad0 100644 --- a/ECS/IEngineNodeDB.cs +++ b/ECS/IEngineNodeDB.cs @@ -11,6 +11,8 @@ namespace Svelto.ECS FasterReadOnlyListCast QueryNodes() where T:INode; +// FasterReadOnlyList QueryStructNodes() where T : struct; + bool QueryNodeFromGroup(int ID, out T node) where T : INode; T QueryNodeFromGroup(int ID) where T : INode; FasterReadOnlyListCast QueryNodesFromGroups() where T : INode; diff --git a/ECS/NodeEngineWrapper.cs b/ECS/NodeEngineWrapper.cs new file mode 100644 index 0000000..49ec673 --- /dev/null +++ b/ECS/NodeEngineWrapper.cs @@ -0,0 +1,66 @@ +using System; + +namespace Svelto.ECS.Internal +{ + class NodeEngineWrapper : SingleNodeEngine where T : class, INode + { + INodeEngine engine; + + public NodeEngineWrapper(INodeEngine engine) + { + this.engine = engine; + } + + protected override void Add(T node) + { + engine.Add((T)node); + } + + protected override void Remove(T node) + { + engine.Remove((T)node); + } + } + + class NodeEngineWrapper: SingleNodeEngine where T : class, INode where U : class, INode + { + INodeEngine engine; + + public NodeEngineWrapper(INodeEngine engine) + { + this.engine = engine; + } + + protected override void Add(T node) + { + engine.Add((T)node); + } + + protected override void Remove(T node) + { + engine.Remove((T)node); + } + } + + class NodeEngineWrapper: SingleNodeEngine where T : class, INode + where U : class, INode + where V : class, INode + { + INodeEngine engine; + + public NodeEngineWrapper(INodeEngine engine) + { + this.engine = engine; + } + + protected override void Add(T node) + { + engine.Add((T)node); + } + + protected override void Remove(T node) + { + engine.Remove((T)node); + } + } +} \ No newline at end of file diff --git a/ECS/NodeSubmissionScheduler.cs b/ECS/NodeSubmissionScheduler.cs new file mode 100644 index 0000000..7f04648 --- /dev/null +++ b/ECS/NodeSubmissionScheduler.cs @@ -0,0 +1,9 @@ +using System; + +namespace Svelto.ECS.NodeSchedulers +{ + public abstract class NodeSubmissionScheduler + { + abstract public void Schedule(Action submitNodes); + } +} \ No newline at end of file diff --git a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs b/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs index 2c20e59..d7c6b93 100644 --- a/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs +++ b/ECS/Profiler/Editor/EngineProfiler/EngineProfilerMenuItem.cs @@ -5,7 +5,7 @@ using UnityEditor; namespace Svelto.ECS.Profiler { - internal class EngineProfilerMenuItem + class EngineProfilerMenuItem { [MenuItem("Engines/Enable Profiler")] public static void EnableProfiler() diff --git a/ECS/Profiler/EngineProfiler.cs b/ECS/Profiler/EngineProfiler.cs index f055f3d..53e7296 100644 --- a/ECS/Profiler/EngineProfiler.cs +++ b/ECS/Profiler/EngineProfiler.cs @@ -11,7 +11,7 @@ namespace Svelto.ECS.Profiler { static readonly Stopwatch _stopwatch = new Stopwatch(); - public static void MonitorAddDuration(Action, INode> addingFunc, INodeEngine engine, INode node) + public static void MonitorAddDuration(Action addingFunc, INodeEngine engine, INode node) { EngineInfo info; if (engineInfos.TryGetValue(engine.GetType(), out info)) @@ -25,7 +25,7 @@ namespace Svelto.ECS.Profiler } } - public static void MonitorRemoveDuration(Action, INode> removeFunc, INodeEngine engine, INode node) + public static void MonitorRemoveDuration(Action removeFunc, INodeEngine engine, INode node) { EngineInfo info; if (engineInfos.TryGetValue(engine.GetType(), out info)) diff --git a/ECS/SingleNodeEngine.cs b/ECS/SingleNodeEngine.cs index 6b43243..d92b840 100644 --- a/ECS/SingleNodeEngine.cs +++ b/ECS/SingleNodeEngine.cs @@ -1,13 +1,13 @@ namespace Svelto.ECS { - public abstract class SingleNodeEngine : INodeEngine where TNodeType : class, INode + public abstract class SingleNodeEngine : INodeEngine where TNodeType : class, INode { - void INodeEngine.Add(INode obj) + void INodeEngine.Add(INode obj) { Add(obj as TNodeType); } - void INodeEngine.Remove(INode obj) + void INodeEngine.Remove(INode obj) { Remove(obj as TNodeType); } diff --git a/Extensions/Unity/UnitySumbmissionNodeScheduler.cs b/Extensions/Unity/UnitySumbmissionNodeScheduler.cs new file mode 100644 index 0000000..e79a425 --- /dev/null +++ b/Extensions/Unity/UnitySumbmissionNodeScheduler.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections; +using UnityEngine; + +namespace Svelto.ECS.NodeSchedulers +{ + public class UnitySumbmissionNodeScheduler : NodeSubmissionScheduler + { + public UnitySumbmissionNodeScheduler() + { + GameObject go = new GameObject("ECSScheduler"); + + _scheduler = go.AddComponent(); + } + + public override void Schedule(Action submitNodes) + { + _scheduler.OnTick += submitNodes; + } + + class Scheduler : MonoBehaviour + { + IEnumerator Start() + { + while (true) + { + yield return new WaitForEndOfFrame(); + + OnTick(); + } + } + + internal Action OnTick; + } + + Scheduler _scheduler; + } +} diff --git a/Utilities/DesignByContract.cs b/Utilities/DesignByContract.cs index d34861e..9a76411 100644 --- a/Utilities/DesignByContract.cs +++ b/Utilities/DesignByContract.cs @@ -324,18 +324,18 @@ namespace DesignByContract useAssertions = value; } } - - #endregion // Interface - #region Implementation + #endregion // Interface - // No creation - private Check() {} + #region Implementation - /// - /// Is exception handling being used? - /// - private static bool UseExceptions + // No creation + Check() { } + + /// + /// Is exception handling being used? + /// + private static bool UseExceptions { get { @@ -343,15 +343,15 @@ namespace DesignByContract } } - // Are trace assertion statements being used? - // Default is to use exception handling. - private static bool useAssertions = false; + // Are trace assertion statements being used? + // Default is to use exception handling. + static bool useAssertions = false; - #endregion // Implementation + #endregion // Implementation - } // End Check + } // End Check - internal class Trace + class Trace { internal static void Assert(bool assertion, string v) { From b24be7d2669c09d7770bf1730adeb8797bccb95f Mon Sep 17 00:00:00 2001 From: sebas77 Date: Mon, 9 Oct 2017 11:57:20 +0100 Subject: [PATCH 6/7] local commit --- DataStructures/CircularBufferIndexer.cs | 2 +- DataStructures/FasterList.cs | 27 +- .../Priority Queue/HeapPriorityQueue.cs | 32 +- ECS/EngineNodeDB.cs | 88 ++- ECS/EnginesRoot.cs | 527 ++++++++++++------ ECS/EntityDescriptor.cs | 171 ++++-- .../Unity/UnitySumbmissionNodeScheduler.cs | 7 +- ECS/GenericEntityDescriptor.cs | 150 ++++- ECS/ICallBackOnAddEngine.cs | 4 +- ECS/IEngine.cs | 37 +- ECS/IEngineNodeDB.cs | 10 +- ECS/IEnginesRoot.cs | 6 +- ECS/INode.cs | 17 +- ECS/IRemoveEntityComponent.cs | 10 + ECS/MultipleNodesEngine.cs | 47 ++ ECS/NodeEngineWrapper.cs | 66 --- ECS/Profiler/EngineProfiler.cs | 1 + ECS/Profiler/EngineProfilerBehaviour.cs | 2 +- ECS/SingleNodeEngine.cs | 15 +- ECS/StructNodes.cs | 74 +++ ECS/note.txt | 111 ++++ Utilities/DesignByContract.cs | 30 +- Utilities/Print.cs | 7 +- Utilities/WeakActionStruct.cs | 2 +- Utilities/WeakEvent.cs | 7 +- 25 files changed, 1004 insertions(+), 446 deletions(-) rename {Extensions => ECS/Extensions}/Unity/UnitySumbmissionNodeScheduler.cs (82%) create mode 100644 ECS/MultipleNodesEngine.cs delete mode 100644 ECS/NodeEngineWrapper.cs create mode 100644 ECS/StructNodes.cs create mode 100644 ECS/note.txt diff --git a/DataStructures/CircularBufferIndexer.cs b/DataStructures/CircularBufferIndexer.cs index cc9d397..a01d8ba 100644 --- a/DataStructures/CircularBufferIndexer.cs +++ b/DataStructures/CircularBufferIndexer.cs @@ -9,7 +9,7 @@ namespace Svelto.DataStructures // isn't taken into account (we would have to do a shift in both arrays) // Could be added as an option? - class CircularBufferIndexer : IDictionary + public class CircularBufferIndexer : IDictionary { public ICollection Keys { diff --git a/DataStructures/FasterList.cs b/DataStructures/FasterList.cs index bc96c16..40407e4 100644 --- a/DataStructures/FasterList.cs +++ b/DataStructures/FasterList.cs @@ -352,12 +352,12 @@ namespace Svelto.DataStructures } } - public void UnorderredRemoveAt(int index) + public void UnorderedRemoveAt(int index) { _lockQ.EnterWriteLock(); try { - _list.UnorderredRemoveAt(index); + _list.UnorderedRemoveAt(index); } finally { @@ -450,10 +450,12 @@ namespace Svelto.DataStructures readonly FasterList _list; } - public class FasterList : IList + public interface IFasterList + {} + + public class FasterList : IList, IFasterList { public static FasterList DefaultList = new FasterList(); - const int MIN_SIZE = 4; public int Count @@ -567,6 +569,11 @@ namespace Svelto.DataStructures _count += count; } + public void AddRange(T[] items) + { + AddRange(items, items.Length); + } + public FasterReadOnlyList AsReadOnly() { return new FasterReadOnlyList(this); @@ -703,32 +710,30 @@ namespace Svelto.DataStructures return _buffer; } - public bool UnorderredRemove(T item) + public bool UnorderedRemove(T item) { var index = IndexOf(item); if (index == -1) return false; - UnorderredRemoveAt(index); + UnorderedRemoveAt(index); return true; } - public T UnorderredRemoveAt(int index) + public bool UnorderedRemoveAt(int index) { DesignByContract.Check.Require(index < _count && _count > 0, "out of bound index"); - T item = _buffer[index]; - if (index == --_count) - return item; + return false; T swap = _buffer[index]; _buffer[index] = _buffer[_count]; _buffer[_count] = swap; - return item; + return true; } IEnumerator IEnumerable.GetEnumerator() diff --git a/DataStructures/Priority Queue/HeapPriorityQueue.cs b/DataStructures/Priority Queue/HeapPriorityQueue.cs index 2774d57..c30e06d 100644 --- a/DataStructures/Priority Queue/HeapPriorityQueue.cs +++ b/DataStructures/Priority Queue/HeapPriorityQueue.cs @@ -13,9 +13,9 @@ namespace Svelto.DataStructures public sealed class HeapPriorityQueue : IPriorityQueue where T : PriorityQueueNode { - int _numNodes; - private readonly FasterList _nodes; - long _numNodesEverEnqueued; + private int _numNodes; + private readonly FasterList _nodes; + private long _numNodesEverEnqueued; /// /// Instantiate a new Priority Queue @@ -101,10 +101,10 @@ namespace Svelto.DataStructures CascadeUp(_nodes[_numNodes]); } -#if NET_VERSION_4_5 + #if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - void Swap(T node1, T node2) + #endif + private void Swap(T node1, T node2) { //Swap the nodes _nodes[node1.QueueIndex] = node2; @@ -117,14 +117,14 @@ namespace Svelto.DataStructures } //Performance appears to be slightly better when this is NOT inlined o_O - void CascadeUp(T node) + private void CascadeUp(T node) { //aka Heapify-up int parent = node.QueueIndex / 2; - while (parent >= 1) + while(parent >= 1) { T parentNode = _nodes[parent]; - if (HasHigherPriority(parentNode, node)) + if(HasHigherPriority(parentNode, node)) break; //Node has lower priority value, so move it up the heap @@ -134,9 +134,9 @@ namespace Svelto.DataStructures } } -#if NET_VERSION_4_5 + #if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif + #endif private void CascadeDown(T node) { //aka Heapify-down @@ -198,10 +198,10 @@ namespace Svelto.DataStructures /// Returns true if 'higher' has higher priority than 'lower', false otherwise. /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false /// -#if NET_VERSION_4_5 + #if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif - bool HasHigherPriority(T higher, T lower) + #endif + private bool HasHigherPriority(T higher, T lower) { return (higher.Priority < lower.Priority || (higher.Priority == lower.Priority && higher.InsertionIndex < lower.InsertionIndex)); @@ -242,13 +242,13 @@ namespace Svelto.DataStructures OnNodeUpdated(node); } - void OnNodeUpdated(T node) + private void OnNodeUpdated(T node) { //Bubble the updated node up or down as appropriate int parentIndex = node.QueueIndex / 2; T parentNode = _nodes[parentIndex]; - if (parentIndex > 0 && HasHigherPriority(node, parentNode)) + if(parentIndex > 0 && HasHigherPriority(node, parentNode)) { CascadeUp(node); } diff --git a/ECS/EngineNodeDB.cs b/ECS/EngineNodeDB.cs index 4a31542..36bef54 100644 --- a/ECS/EngineNodeDB.cs +++ b/ECS/EngineNodeDB.cs @@ -1,77 +1,71 @@ using System; using System.Collections.Generic; using Svelto.DataStructures; +using Svelto.ECS.Internal; namespace Svelto.ECS { - class EngineNodeDB : IEngineNodeDB + public class EngineNodeDB : IEngineNodeDB { internal EngineNodeDB( Dictionary> nodesDB, Dictionary> nodesDBdic, - Dictionary> nodesDBgroups) + Dictionary> metaNodesDB, + Dictionary structNodesDB) { - _nodesDB = new DataStructures.WeakReference>>(nodesDB); - _nodesDBdic = new DataStructures.WeakReference>>(nodesDBdic); - _nodesDBgroups = new DataStructures.WeakReference>>(nodesDBgroups); + _nodesDB = nodesDB; + _nodesDBdic = nodesDBdic; + _metaNodesDB = metaNodesDB; + _structNodesDB = structNodesDB; } public FasterReadOnlyListCast QueryNodes() where T:INode { var type = typeof(T); - if (_nodesDB.IsValid == false || _nodesDB.Target.ContainsKey(type) == false) + if (_nodesDB.ContainsKey(type) == false) return RetrieveEmptyNodeList(); - return new FasterReadOnlyListCast(_nodesDB.Target[type]); + return new FasterReadOnlyListCast(_nodesDB[type]); } - /* public FasterReadOnlyList QueryStructNodes() where T:struct - { - var type = typeof(T); - - if (_nodesDBStructs.ContainsKey(type) == false) - return RetrieveEmptyStructNodeList(); - - return new FasterReadOnlyList(((StructNodeList)(_nodesDBStructs[type])).list); - }*/ - public ReadOnlyDictionary QueryIndexableNodes() where T:INode { var type = typeof(T); - if (_nodesDB.IsValid == false || _nodesDBdic.Target.ContainsKey(type) == false) + if (_nodesDBdic.ContainsKey(type) == false) return _defaultEmptyNodeDict; - return new ReadOnlyDictionary(_nodesDBdic.Target[type]); + return new ReadOnlyDictionary(_nodesDBdic[type]); } - public T QueryNodeFromGroup(int groupID) where T : INode + public T QueryMetaNode(int metaEntityID) where T : INode { - return QueryNode(groupID); + return QueryNode(metaEntityID); } - public bool QueryNodeFromGroup(int groupID, out T node) where T : INode + public bool TryQueryMetaNode(int metaEntityID, out T node) where T : INode { - return QueryNode(groupID, out node); + return TryQueryNode(metaEntityID, out node); } - public FasterReadOnlyListCast QueryNodesFromGroups() where T : INode + public FasterReadOnlyListCast QueryMetaNodes() where T : INode { var type = typeof(T); - if (_nodesDBgroups.IsValid == false || _nodesDBgroups.Target.ContainsKey(type) == false) + if (_metaNodesDB.ContainsKey(type) == false) return RetrieveEmptyNodeList(); - return new FasterReadOnlyListCast(_nodesDBgroups.Target[type]); + return new FasterReadOnlyListCast(_metaNodesDB[type]); } - public bool QueryNode(int ID, out T node) where T:INode + public bool TryQueryNode(int ID, out T node) where T:INode { var type = typeof(T); INode internalNode; - if (_nodesDBdic.IsValid && _nodesDBdic.Target.ContainsKey(type) && _nodesDBdic.Target[type].TryGetValue(ID, out internalNode)) + if (_nodesDBdic.ContainsKey(type) && + _nodesDBdic[type].TryGetValue(ID, out internalNode)) { node = (T)internalNode; @@ -89,39 +83,33 @@ namespace Svelto.ECS INode internalNode; - if (_nodesDBdic.IsValid && _nodesDBdic.Target.ContainsKey(type) && _nodesDBdic.Target[type].TryGetValue(ID, out internalNode)) + if (_nodesDBdic.ContainsKey(type) && + _nodesDBdic[type].TryGetValue(ID, out internalNode)) return (T)internalNode; throw new Exception("Node Not Found"); } - static FasterReadOnlyListCast RetrieveEmptyNodeList() where T : INode + public FasterReadOnlyListCast QueryGroupNodes(int groupID) where T : INode { - return new FasterReadOnlyListCast(FasterList.DefaultList); + var type = typeof(T); + + if (_nodesDB.ContainsKey(type) == false) + return RetrieveEmptyNodeList(); + + return new FasterReadOnlyListCast(_nodesDB[type]); } - static FasterReadOnlyList RetrieveEmptyStructNodeList() where T : struct + static FasterReadOnlyListCast RetrieveEmptyNodeList() where T : INode { - return new FasterReadOnlyList(FasterList.DefaultList); + return new FasterReadOnlyListCast(FasterList.DefaultList); } - Svelto.DataStructures.WeakReference>> _nodesDB; - Svelto.DataStructures.WeakReference>> _nodesDBdic; - Svelto.DataStructures.WeakReference>> _nodesDBgroups; -// Dictionary _nodesDBStructs; - - //Dictionary> _nodesDB; - //Dictionary> _nodesDBdic; -// Dictionary> _nodesDBgroups; + readonly Dictionary> _nodesDB; + readonly Dictionary> _nodesDBdic; + readonly Dictionary> _metaNodesDB; + readonly Dictionary _structNodesDB; - ReadOnlyDictionary _defaultEmptyNodeDict = new ReadOnlyDictionary(new Dictionary()); - - class StructNodeList - { } - - class StructNodeList : StructNodeList where T : struct - { - public FasterList list = new FasterList(); - } + readonly ReadOnlyDictionary _defaultEmptyNodeDict = new ReadOnlyDictionary(new Dictionary()); } } diff --git a/ECS/EnginesRoot.cs b/ECS/EnginesRoot.cs index 0807d13..a70807b 100644 --- a/ECS/EnginesRoot.cs +++ b/ECS/EnginesRoot.cs @@ -2,10 +2,11 @@ using System; using System.Collections; using System.Collections.Generic; using Svelto.DataStructures; +using Svelto.ECS.Internal; +using Svelto.ECS.NodeSchedulers; using UnityEngine; using WeakReference = Svelto.DataStructures.WeakReference; -using Svelto.ECS.NodeSchedulers; -using Svelto.ECS.Internal; + #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR using Svelto.ECS.Profiler; #endif @@ -15,25 +16,54 @@ using System.Reflection; namespace Svelto.ECS { + class Scheduler : MonoBehaviour + { + IEnumerator Start() + { + while (true) + { + yield return _waitForEndOfFrame; + + OnTick(); + } + } + + internal Action OnTick; + + readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame(); + } + public sealed class EnginesRoot : IEnginesRoot, IEntityFactory { public EnginesRoot(NodeSubmissionScheduler nodeScheduler) { - _nodeEngines = new Dictionary>(); + _nodeEngines = new Dictionary>(); + _activableEngines = new Dictionary>(); + _otherEngines = new FasterList(); + _engineRootWeakReference = new WeakReference(this); - _otherEnginesReferences = new FasterList(); _nodesDB = new Dictionary>(); _nodesDBdic = new Dictionary>(); _nodesToAdd = new FasterList(); - _groupNodesToAdd = new FasterList(); + _metaNodesToAdd = new FasterList(); + + _metaNodesDB = new Dictionary>(); + _structNodesDB = new Dictionary(); - _nodesDBgroups = new Dictionary>(); + _internalRemove = InternalRemove; + _internalDisable = InternalDisable; + _internalEnable = InternalEnable; + _internalMetaRemove = InternalMetaRemove; _scheduler = nodeScheduler; _scheduler.Schedule(SubmitNodes); + _activableNodeEngineType = typeof(IActivableNodeEngine<>); + + _implementedInterfaceTypes = new Dictionary(); + #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR GameObject debugEngineObject = new GameObject("Engine Debugger"); debugEngineObject.gameObject.AddComponent(); @@ -42,28 +72,38 @@ namespace Svelto.ECS void SubmitNodes() { - int groupNodesCount; - int nodesCount; + int metaNodesCount = _metaNodesToAdd.Count; + int nodesCount = _nodesToAdd.Count; + + if (metaNodesCount + nodesCount == 0) return; + bool newNodesHaveBeenAddedWhileIterating; int startNodes = 0; - int startGroupNodes = 0; + int startMetaNodes = 0; int numberOfReenteringLoops = 0; do { - groupNodesCount = _groupNodesToAdd.Count; - nodesCount = _nodesToAdd.Count; - for (int i = startNodes; i < nodesCount; i++) { var node = _nodesToAdd[i]; - AddNodeToTheDB(node, node.GetType()); + var nodeType = node.GetType(); + + AddNodeToTheDB(node, nodeType); + var nodeWithId = node as INodeWithID; + if (nodeWithId != null) + AddNodeToNodesDictionary(nodeWithId, nodeType); } - for (int i = startGroupNodes; i < groupNodesCount; i++) + for (int i = startMetaNodes; i < metaNodesCount; i++) { - var node = _groupNodesToAdd[i]; - AddNodeToGroupDB(node, node.GetType()); + var node = _metaNodesToAdd[i]; + var nodeType = node.GetType(); + + AddNodeToMetaDB(node, nodeType); + var nodeWithId = node as INodeWithID; + if (nodeWithId != null) + AddNodeToNodesDictionary(nodeWithId, nodeType); } for (int i = startNodes; i < nodesCount; i++) @@ -72,151 +112,223 @@ namespace Svelto.ECS AddNodeToTheSuitableEngines(node, node.GetType()); } - for (int i = startGroupNodes; i < groupNodesCount; i++) + for (int i = startMetaNodes; i < metaNodesCount; i++) { - var node = _groupNodesToAdd[i]; + var node = _metaNodesToAdd[i]; AddNodeToTheSuitableEngines(node, node.GetType()); } - newNodesHaveBeenAddedWhileIterating = _groupNodesToAdd.Count > groupNodesCount || _nodesToAdd.Count > nodesCount; + newNodesHaveBeenAddedWhileIterating = + _metaNodesToAdd.Count > metaNodesCount || + _nodesToAdd.Count > nodesCount; startNodes = nodesCount; - startGroupNodes = groupNodesCount; + startMetaNodes = metaNodesCount; if (numberOfReenteringLoops > 5) throw new Exception("possible infinite loop found creating Entities inside INodesEngine Add method, please consider building entities outside INodesEngine Add method"); - numberOfReenteringLoops++; + numberOfReenteringLoops++; + + metaNodesCount = _metaNodesToAdd.Count; + nodesCount = _nodesToAdd.Count; } while (newNodesHaveBeenAddedWhileIterating); _nodesToAdd.Clear(); - _groupNodesToAdd.Clear(); + _metaNodesToAdd.Clear(); } - public void AddEngine(INodeEngine engine) where T:class, INode + public void AddEngine(IEngine engine) { - AddEngine(new NodeEngineWrapper(engine)); +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR + EngineProfiler.AddEngine(engine); +#endif + var queryableNodeEngine = engine as IQueryableNodeEngine; + if (queryableNodeEngine != null) + queryableNodeEngine.nodesDB = + new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB, _structNodesDB); - if (engine is IQueryableNodeEngine) - (engine as IQueryableNodeEngine).nodesDB = new EngineNodeDB(_nodesDB, _nodesDBdic, _nodesDBgroups); - } + var engineType = engine.GetType(); + var implementedInterfaces = engineType.GetInterfaces(); - public void AddEngine(INodeEngine engine) where T:class, INode where U:class, INode - { - AddEngine(new NodeEngineWrapper(engine)); - AddEngine((INodeEngine)(engine)); + CollectImplementedInterfaces(implementedInterfaces); + + var engineAdded = CheckGenericEngines(engine); + + if (CheckLegacyNodesEngine(engine, ref engineAdded) == false) + CheckNodesEngine(engine, engineType, ref engineAdded); + + if (engineAdded == false) + _otherEngines.Add(engine); + + var callBackOnAddEngine = engine as ICallBackOnAddEngine; + if (callBackOnAddEngine != null) + callBackOnAddEngine.Ready(); } - public void AddEngine(INodeEngine engine) where T:class, INode - where U:class, INode - where V:class, INode + void CollectImplementedInterfaces(Type[] implementedInterfaces) { - AddEngine(new NodeEngineWrapper(engine)); - AddEngine((INodeEngine)(engine)); + _implementedInterfaceTypes.Clear(); + + for (int index = 0; index < implementedInterfaces.Length; index++) + { + var interfaceType = implementedInterfaces[index]; +#if !NETFX_CORE + + if (false == interfaceType.IsGenericType) +#else + if (false == interfaceType.IsConstructedGenericType) +#endif + { + continue; + } + + var genericTypeDefinition = interfaceType.GetGenericTypeDefinition(); + var a = interfaceType.GetGenericArguments(); + var b = genericTypeDefinition.GetGenericArguments(); + + _implementedInterfaceTypes.Add(genericTypeDefinition, + interfaceType.GetGenericArguments()); + } } - public void AddEngine(IEngine engine) + bool CheckGenericEngines(IEngine engine) { -#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.AddEngine(engine); -#endif - if (engine is IQueryableNodeEngine) - (engine as IQueryableNodeEngine).nodesDB = new EngineNodeDB(_nodesDB, _nodesDBdic, _nodesDBgroups); + if (_implementedInterfaceTypes.Count == 0) return false; - if (engine is INodesEngine) + bool engineAdded = false; + + Type[] arguments; + if (_implementedInterfaceTypes.TryGetValue(_activableNodeEngineType, + out arguments)) { - var nodesEngine = engine as INodesEngine; + AddEngine(engine, arguments, _activableEngines); - AddEngine(nodesEngine, nodesEngine.AcceptedNodes(), _nodeEngines); + engineAdded = true; } - else + + return engineAdded; + } + + bool CheckLegacyNodesEngine(IEngine engine, ref bool engineAdded) + { + var nodesEngine = engine as INodesEngine; + if (nodesEngine != null) { - var engineType = engine.GetType(); + AddEngine(nodesEngine, nodesEngine.AcceptedNodes(), _nodeEngines); -#if !NETFX_CORE - var baseType = engineType.BaseType; + engineAdded = true; + + return true; + } + + return false; + } - if (baseType.IsGenericType + bool CheckNodesEngine(IEngine engine, Type engineType, ref bool engineAdded) + { +#if !NETFX_CORE + var baseType = engineType.BaseType; + + if (baseType.IsGenericType #else var baseType = engineType.GetTypeInfo().BaseType; if (baseType.IsConstructedGenericType #endif - && baseType.GetGenericTypeDefinition() == typeof(SingleNodeEngine<>)) - { - AddEngine(engine as INodeEngine, baseType.GetGenericArguments(), _nodeEngines); - } - else - { - bool found = false; - - for (int i = 0, maxLength = engineType.GetInterfaces().Length; i < maxLength; i++) - { - var type = engineType.GetInterfaces()[i]; - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(INodeEngine<>)) - { - AddEngine(engine as INodeEngine, type.GetGenericArguments(), _nodeEngines); + && engine is INodeEngine) + { + AddEngine(engine as INodeEngine, baseType.GetGenericArguments(), _nodeEngines); - found = true; - } - } + engineAdded = true; - if (found == false) - _otherEnginesReferences.Add(engine); - } + return true; } - - if (engine is ICallBackOnAddEngine) - (engine as ICallBackOnAddEngine).Ready(); + + return false; } public void BuildEntity(int ID, EntityDescriptor ed) { - var entityNodes = ed.BuildNodes(ID, (nodes) => - { - if (_engineRootWeakReference.IsValid == true) - InternalRemove(nodes); - }); - + var entityNodes = ed.BuildNodes(ID, + _internalRemove, + _internalEnable, + _internalDisable + ); + _nodesToAdd.AddRange(entityNodes); } /// - /// An entity group is a meta entity. It's a way to create a set of entitites that - /// are not easily queriable otherwise. For example you may group existing entities - /// by size and type and then use the groupID to retrieve a single node that is shared - /// among the single entities of the same type and size. This willwd prevent the scenario - /// where the coder is forced to parse all the entities to find the ones of the same - /// size and type. Since the entity group is managed through the shared node, the same + /// A meta entity is a way to manage a set of entitites that are not easily + /// queriable otherwise. For example you may want to group existing entities + /// by size and type and then use the meta entity node to manage the data + /// shared among the single entities of the same type and size. This will + /// prevent the scenario where the coder is forced to parse all the entities to + /// find the ones of the same size and type. + /// Since the entities are managed through the shared node, the same /// shared node must be found on the single entities of the same type and size. - /// The shared node is then used by engines that are meant to manage a group of entities - /// through a single node. The same engine can manage several groups of entitites. + /// The shared node of the meta entity is then used by engines that are meant + /// to manage a group of entities through a single node. + /// The same engine can manage several meta entities nodes too. + /// The Engine manages the logic of the Meta Node data and other engines + /// can read back this data through the normal entity as the shared node + /// will be present in their descriptor too. + /// + /// + /// + public void BuildMetaEntity(int metaEntityID, EntityDescriptor ed) + { + var entityNodes = ed.BuildNodes(metaEntityID, + _internalMetaRemove, + _internalEnable, + _internalDisable + ); + + _metaNodesToAdd.AddRange(entityNodes); + } + + /// + /// Using this function is like building a normal entity, but the nodes + /// are grouped by groupID to be better processed inside engines and + /// improve cache locality. Only IGroupStructNodeWithID nodes are grouped + /// other nodes are managed as usual. /// + /// /// /// - public void BuildEntityGroup(int groupID, EntityDescriptor ed) + public void BuildEntityInGroup(int entityID, int groupID, + EntityDescriptor ed) { - var entityNodes = ed.BuildNodes(groupID, (nodes) => - { - if (_engineRootWeakReference.IsValid == true) - InternalGroupRemove(nodes); - }); + var entityNodes = ed.BuildNodes(entityID, + _internalRemove, + _internalEnable, + _internalDisable + ); + + _nodesToAdd.AddRange(entityNodes); - _groupNodesToAdd.AddRange(entityNodes); + for (int i = 0; i < entityNodes.Count; i++) + { + var groupNode = entityNodes[i] as IGroupedStructNodeWithID; + if (groupNode != null) + groupNode.groupID = groupID; + } } - static void AddEngine(INodeEngine engine, Type[] types, Dictionary> engines) + static void AddEngine(IEngine engine, Type[] types, + Dictionary> engines) { for (int i = 0; i < types.Length; i++) { - FasterList list; + FasterList list; var type = types[i]; if (engines.TryGetValue(type, out list) == false) { - list = new FasterList(); + list = new FasterList(); engines.Add(type, list); } @@ -225,136 +337,223 @@ namespace Svelto.ECS } } - void AddNodeToGroupDB(INode node, Type nodeType) + void AddNodeToMetaDB(INode node, Type nodeType) { FasterList nodes; - if (_nodesDBgroups.TryGetValue(nodeType, out nodes) == false) - nodes = _nodesDBgroups[nodeType] = new FasterList(); + if (_metaNodesDB.TryGetValue(nodeType, out nodes) == false) + nodes = _metaNodesDB[nodeType] = new FasterList(); nodes.Add(node); - - AddNodeToNodesDictionary(node, nodeType); } - void AddNodeToTheDB(INode node, Type nodeType) + void AddNodeToTheDB(T node, Type nodeType) where T : INode { FasterList nodes; - if (_nodesDB.TryGetValue(nodeType, out nodes) == false) - nodes = _nodesDB[nodeType] = new FasterList(); - nodes.Add(node); + if (node is IStructNodeWithID == false) + { + if (_nodesDB.TryGetValue(nodeType, out nodes) == false) + nodes = _nodesDB[nodeType] = new FasterList(); - AddNodeToNodesDictionary(node, nodeType); + nodes.Add(node); + } + else + { + if (_nodesDB.TryGetValue(nodeType, out nodes) == false) + nodes = _nodesDB[nodeType] = new FasterList(); + } } - void AddNodeToNodesDictionary(INode node, Type nodeType) + void AddNodeToNodesDictionary(T node, Type nodeType) where T : INodeWithID { - if (node is NodeWithID) - { - Dictionary nodesDic; - if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false) - nodesDic = _nodesDBdic[nodeType] = new Dictionary(); + Dictionary nodesDic; - nodesDic[(node as NodeWithID).ID] = node; - } + if (_nodesDBdic.TryGetValue(nodeType, out nodesDic) == false) + nodesDic = _nodesDBdic[nodeType] = new Dictionary(); + + nodesDic.Add(node.ID, node); } void AddNodeToTheSuitableEngines(INode node, Type nodeType) { - FasterList enginesForNode; + FasterList enginesForNode; if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) { for (int j = 0; j < enginesForNode.Count; j++) { #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.MonitorAddDuration(AddNodeToEngine, enginesForNode[j], node); + EngineProfiler.MonitorAddDuration(AddNodeToEngine, enginesForNode[j] as INodeEngine, node); #else - enginesForNode[j].Add(node); + (enginesForNode[j] as INodeEngine).Add(node); #endif } } } - void RemoveNodesFromDB(Dictionary> DB, FasterReadOnlyList nodes) + void RemoveNodeFromTheDB(T node, Type nodeType) where T : INode { - for (int i = 0; i < nodes.Count; i++) - { - FasterList nodesInDB; + FasterList nodes; + if (_nodesDB.TryGetValue(nodeType, out nodes) == true) + nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero? + } - var node = nodes[i]; - var nodeType = node.GetType(); - - if (DB.TryGetValue(nodeType, out nodesInDB) == true) - nodesInDB.UnorderredRemove(node); //should I remove it from the dictionary if length is zero? + void RemoveNodeFromMetaDB(T node, Type nodeType) where T : INode + { + FasterList nodes; + if (_metaNodesDB.TryGetValue(nodeType, out nodes) == true) + nodes.UnorderedRemove(node); //should I remove it from the dictionary if length is zero? + } - if (node is NodeWithID) - { - Dictionary nodesDic; + void RemoveNodeFromNodesDictionary(T node, Type nodeType) where T : INodeWithID + { + Dictionary nodesDic; - if (_nodesDBdic.TryGetValue(nodeType, out nodesDic)) - nodesDic.Remove((node as NodeWithID).ID); - } - } + if (_nodesDBdic.TryGetValue(nodeType, out nodesDic)) + nodesDic.Remove(node.ID); } - void RemoveNodesFromEngines(FasterReadOnlyList nodes) + void RemoveNodeFromEngines(T node, Type nodeType) where T : INode { - for (int i = 0; i < nodes.Count; i++) - { - FasterList enginesForNode; - var node = nodes[i]; + FasterList enginesForNode; - if (_nodeEngines.TryGetValue(node.GetType(), out enginesForNode)) + if (_nodeEngines.TryGetValue(nodeType, out enginesForNode)) + { + for (int j = 0; j < enginesForNode.Count; j++) { - for (int j = 0; j < enginesForNode.Count; j++) - { #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, enginesForNode[j], node); + EngineProfiler.MonitorRemoveDuration(RemoveNodeFromEngine, (enginesForNode[j] as INodeEngine), node); #else - enginesForNode[j].Remove(node); + (enginesForNode[j] as INodeEngine).Remove(node); #endif - } + } + } + } + + void DisableNodeFromEngines(INode node, Type nodeType) + { + FasterList enginesForNode; + + if (_activableEngines.TryGetValue(nodeType, out enginesForNode)) + { + for (int j = 0; j < enginesForNode.Count; j++) + { + (enginesForNode[j] as IActivableNodeEngine).Disable(node); + } + } + } + + void EnableNodeFromEngines(INode node, Type nodeType) + { + FasterList enginesForNode; + + if (_activableEngines.TryGetValue(nodeType, out enginesForNode)) + { + for (int j = 0; j < enginesForNode.Count; j++) + { + (enginesForNode[j] as IActivableNodeEngine).Enable(node); } } } #if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - static void AddNodeToEngine(INodeEngine engine, INode node) + void AddNodeToEngine(IEngine engine, INode node) { - engine.Add(node); + (engine as INodeEngine).Add(node); } - static void RemoveNodeFromEngine(INodeEngine engine, INode node) + void RemoveNodeFromEngine(IEngine engine, INode node) { - engine.Remove(node); + (engine as INodeEngine).Remove(node); } #endif - void InternalRemove(FasterReadOnlyList nodes) + void InternalDisable(FasterList nodes) + { + if (_engineRootWeakReference.IsValid == false) + return; + + for (int i = 0; i < nodes.Count; i++) + { + var node = nodes[i]; + Type nodeType = node.GetType(); + DisableNodeFromEngines(node, nodeType); + } + } + + void InternalEnable(FasterList nodes) + { + if (_engineRootWeakReference.IsValid == false) + return; + + for (int i = 0; i < nodes.Count; i++) + { + var node = nodes[i]; + Type nodeType = node.GetType(); + EnableNodeFromEngines(node, nodeType); + } + } + + void InternalRemove(FasterList nodes) { - RemoveNodesFromEngines(nodes); - RemoveNodesFromDB(_nodesDB, nodes); + if (_engineRootWeakReference.IsValid == false) + return; + + for (int i = 0; i < nodes.Count; i++) + { + var node = nodes[i]; + Type nodeType = node.GetType(); + + RemoveNodeFromEngines(node, nodeType); + RemoveNodeFromTheDB(node, node.GetType()); + + var nodeWithId = node as INodeWithID; + if (nodeWithId != null) + RemoveNodeFromNodesDictionary(nodeWithId, nodeType); + } } - void InternalGroupRemove(FasterReadOnlyList nodes) + void InternalMetaRemove(FasterList nodes) { - RemoveNodesFromEngines(nodes); - RemoveNodesFromDB(_nodesDBgroups, nodes); + for (int i = 0; i < nodes.Count; i++) + { + var node = nodes[i]; + Type nodeType = node.GetType(); + + RemoveNodeFromEngines(node, nodeType); + RemoveNodeFromMetaDB(node, nodeType); + + var nodeWithId = node as INodeWithID; + if (nodeWithId != null) + RemoveNodeFromNodesDictionary(nodeWithId, nodeType); + } } - Dictionary> _nodeEngines; - FasterList _otherEnginesReferences; + readonly Dictionary> _nodeEngines; + readonly Dictionary> _activableEngines; + + readonly FasterList _otherEngines; + + readonly Dictionary> _nodesDB; + readonly Dictionary> _metaNodesDB; + readonly Dictionary _structNodesDB; + + readonly Dictionary> _nodesDBdic; + + readonly FasterList _nodesToAdd; + readonly FasterList _metaNodesToAdd; + + readonly WeakReference _engineRootWeakReference; - Dictionary> _nodesDB; - Dictionary> _nodesDBgroups; + readonly NodeSubmissionScheduler _scheduler; - Dictionary> _nodesDBdic; + readonly Action> _internalRemove; + readonly Action> _internalEnable; + readonly Action> _internalDisable; + readonly Action> _internalMetaRemove; - FasterList _nodesToAdd; - FasterList _groupNodesToAdd; + readonly Type _activableNodeEngineType; - WeakReference _engineRootWeakReference; - NodeSubmissionScheduler _scheduler; + readonly Dictionary _implementedInterfaceTypes; } } diff --git a/ECS/EntityDescriptor.cs b/ECS/EntityDescriptor.cs index d818dce..1550f60 100644 --- a/ECS/EntityDescriptor.cs +++ b/ECS/EntityDescriptor.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Reflection; using Svelto.DataStructures; #if NETFX_CORE @@ -11,39 +12,53 @@ namespace Svelto.ECS { protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor) { - _implementors = componentsImplementor; - _nodesToBuild = nodesToBuild; + _nodesToBuild = new FasterList(nodesToBuild); + + ProcessImplementors(componentsImplementor); } - /* protected EntityDescriptor(IStructNodeBuilder[] structNodesToBuild) + public void AddImplementors(params object[] componentsImplementor) { - _structNodesToBuild = structNodesToBuild; - }*/ + ProcessImplementors(componentsImplementor); + } - public void AddImplementors(params object[] componentsImplementor) + void ProcessImplementors(object[] implementors) { - var implementors = new object[componentsImplementor.Length + _implementors.Length]; + for (int index = 0; index < implementors.Length; index++) + { + var implementor = implementors[index]; + if (implementor is IRemoveEntityComponent) + _removingImplementors.Add(implementor as IRemoveEntityComponent); + if (implementor is IDisableEntityComponent) + _disablingImplementors.Add(implementor as IDisableEntityComponent); + if (implementor is IEnableEntityComponent) + _enablingImplementors.Add(implementor as IEnableEntityComponent); - Array.Copy(_implementors, implementors, _implementors.Length); - Array.Copy(componentsImplementor, 0, implementors, _implementors.Length, componentsImplementor.Length); + var interfaces = implementor.GetType().GetInterfaces(); - _implementors = implementors; + for (int iindex = 0; iindex < interfaces.Length; iindex++) + { + _implementorsByType[interfaces[iindex]] = implementor; + } + } + } + + public void AddNodes(params INodeBuilder[] nodesWithID) + { + _nodesToBuild.AddRange(nodesWithID); } - public virtual FasterList BuildNodes(int ID, Action> removeAction) + public virtual FasterList BuildNodes(int ID) { var nodes = new FasterList(); - for (int index = _nodesToBuild.Length - 1; index >= 0; index--) + for (int index = 0; index < _nodesToBuild.Count; index++) { var nodeBuilder = _nodesToBuild[index]; - var node = FillNode(nodeBuilder.Build(ID), () => - { - removeAction(new FasterReadOnlyList()); + var node = nodeBuilder.Build(ID); - nodes.Clear(); - } - ); + if (nodeBuilder.reflects != FillNodeMode.None) + node = FillNode(node, nodeBuilder.reflects); nodes.Add(node); } @@ -51,74 +66,116 @@ namespace Svelto.ECS return nodes; } - TNode FillNode(TNode node, Action removeAction) where TNode: INode + internal FasterList BuildNodes(int ID, + Action> removeEntity, + Action> enableEntity, + Action> disableEntity) { - var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); - - for (int i = fields.Length - 1; i >=0 ; --i) - { - var field = fields[i]; - Type fieldType = field.FieldType; - object component = null; + var nodes = BuildNodes(ID); - for (int j = 0; j < _implementors.Length; j++) - { - var implementor = _implementors[j]; + SetupImplementors(removeEntity, enableEntity, disableEntity, nodes); - if (implementor != null && fieldType.IsAssignableFrom(implementor.GetType())) - { - component = implementor; + return nodes; + } - if (fieldType.IsAssignableFrom(typeof(IRemoveEntityComponent))) - (component as IRemoveEntityComponent).removeEntity = removeAction; + void SetupImplementors( + Action> removeEntity, + Action> enableEntity, + Action> disableEntity, + FasterList nodes) + { + Action removeEntityAction = () => + { removeEntity(nodes); nodes.Clear(); }; + Action disableEntityAction = () => + { disableEntity(nodes); }; + Action enableEntityAction = () => + { enableEntity(nodes); }; + + for (int index = 0; index < _removingImplementors.Count; index++) + _removingImplementors[index].removeEntity = removeEntityAction; + for (int index = 0; index < _disablingImplementors.Count; index++) + _disablingImplementors[index].disableEntity = disableEntityAction; + for (int index = 0; index < _enablingImplementors.Count; index++) + _enablingImplementors[index].enableEntity = enableEntityAction; + } - break; - } - } + INode FillNode(INode node, FillNodeMode mode) + { + var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); - if (component == null) + for (int i = fields.Length - 1; i >= 0; --i) + { + var field = fields[i]; + Type fieldType = field.FieldType; + object component; + + if ((_implementorsByType.TryGetValue(fieldType, out component)) == false) { - Exception e = new Exception("Svelto.ECS: Implementor not found for a Node. " + - "Implementor Type: " + field.FieldType.Name + " - Node: " + node.GetType().Name + " - EntityDescriptor " + this); + if (mode == FillNodeMode.Strict) + { + Exception e = + new Exception("Svelto.ECS: Implementor not found for a Node. " + "Implementor Type: " + + field.FieldType.Name + " - Node: " + node.GetType().Name + + " - EntityDescriptor " + this); - throw e; + throw e; + } } - - field.SetValue(node, component); + else + field.SetValue(node, component); } return node; } - object[] _implementors; - - readonly INodeBuilder[] _nodesToBuild; - // readonly IStructNodeBuilder[] _structNodesToBuild; + readonly FasterList _disablingImplementors = new FasterList(); + readonly FasterList _removingImplementors = new FasterList(); + readonly FasterList _enablingImplementors = new FasterList(); + + readonly Dictionary _implementorsByType = new Dictionary(); + readonly FasterList _nodesToBuild; } public interface INodeBuilder { - NodeWithID Build(int ID); + INodeWithID Build(int ID); + + FillNodeMode reflects { get; } } - public class NodeBuilder : INodeBuilder where NodeType:NodeWithID, new() + public class NodeBuilder : INodeBuilder where NodeType : NodeWithID, new() { - public NodeWithID Build(int ID) + public INodeWithID Build(int ID) { NodeWithID node = NodeWithID.BuildNode(ID); return (NodeType)node; } + + public FillNodeMode reflects { get { return FillNodeMode.Strict; } } } -/* - public interface IStructNodeBuilder - {} - public class StructNodeBuilder : IStructNodeBuilder where NodeType : struct + //To Do: Probably I will need to add an + //FastStructNodeBuilder where reflects is false + public class StructNodeBuilder : INodeBuilder + where NodeType : struct, IStructNodeWithID { - public NodeType Build() + public INodeWithID Build(int ID) { - return new NodeType(); + IStructNodeWithID node = default(NodeType); + node.ID = ID; + + return node; } - }*/ + + public FillNodeMode reflects { get { return FillNodeMode.Relaxed; } } + } + + public enum FillNodeMode + { + Strict, + Relaxed, + + None + } } diff --git a/Extensions/Unity/UnitySumbmissionNodeScheduler.cs b/ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs similarity index 82% rename from Extensions/Unity/UnitySumbmissionNodeScheduler.cs rename to ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs index e79a425..c211f73 100644 --- a/Extensions/Unity/UnitySumbmissionNodeScheduler.cs +++ b/ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs @@ -1,4 +1,5 @@ -using System; +#if UNITY_5 || UNITY_5_3_OR_NEWER +using System; using System.Collections; using UnityEngine; @@ -24,15 +25,17 @@ namespace Svelto.ECS.NodeSchedulers { while (true) { - yield return new WaitForEndOfFrame(); + yield return _wait; OnTick(); } } internal Action OnTick; + WaitForEndOfFrame _wait = new WaitForEndOfFrame(); } Scheduler _scheduler; } } +#endif \ No newline at end of file diff --git a/ECS/GenericEntityDescriptor.cs b/ECS/GenericEntityDescriptor.cs index 62ddd73..1be1793 100644 --- a/ECS/GenericEntityDescriptor.cs +++ b/ECS/GenericEntityDescriptor.cs @@ -1,6 +1,6 @@ namespace Svelto.ECS { - class GenericEntityDescriptor : EntityDescriptor + public class GenericEntityDescriptor : EntityDescriptor where T : NodeWithID, new() { static GenericEntityDescriptor() @@ -10,10 +10,10 @@ public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) {} - static INodeBuilder[] _nodesToBuild; + static readonly INodeBuilder[] _nodesToBuild; } - class GenericEntityDescriptor : EntityDescriptor + public class GenericEntityDescriptor : EntityDescriptor where T : NodeWithID, new() where U : NodeWithID, new() { @@ -29,10 +29,10 @@ public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) {} - static INodeBuilder[] _nodesToBuild; + static readonly INodeBuilder[] _nodesToBuild; } - class GenericEntityDescriptor : EntityDescriptor + public class GenericEntityDescriptor : EntityDescriptor where T : NodeWithID, new() where U : NodeWithID, new() where V : NodeWithID, new() @@ -47,12 +47,12 @@ }; } public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - { - } - static INodeBuilder[] _nodesToBuild; + {} + + static readonly INodeBuilder[] _nodesToBuild; } - class GenericEntityDescriptor : EntityDescriptor + public class GenericEntityDescriptor : EntityDescriptor where T : NodeWithID, new() where U : NodeWithID, new() where V : NodeWithID, new() @@ -69,12 +69,12 @@ }; } public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - { - } - static INodeBuilder[] _nodesToBuild; + {} + + static readonly INodeBuilder[] _nodesToBuild; } - class GenericEntityDescriptor : EntityDescriptor + public class GenericEntityDescriptor : EntityDescriptor where T : NodeWithID, new() where U : NodeWithID, new() where V : NodeWithID, new() @@ -93,11 +93,12 @@ }; } public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) - { - } - static INodeBuilder[] _nodesToBuild; + {} + + static readonly INodeBuilder[] _nodesToBuild; } - class GenericEntityDescriptor : EntityDescriptor + + public class GenericEntityDescriptor : EntityDescriptor where T : NodeWithID, new() where U : NodeWithID, new() where V : NodeWithID, new() @@ -118,8 +119,121 @@ }; } public GenericEntityDescriptor(params object[] componentsImplementor) : base(_nodesToBuild, componentsImplementor) + {} + + static readonly INodeBuilder[] _nodesToBuild; + } + + public class GenericMixedEntityDescriptor : EntityDescriptor + where T : INodeBuilder, new() + { + static GenericMixedEntityDescriptor() + { + _nodesToBuild = new INodeBuilder[] + { + new T(), + }; + } + public GenericMixedEntityDescriptor(params object[] componentsImplementor) : + base(_nodesToBuild, componentsImplementor) + { } + + static readonly INodeBuilder[] _nodesToBuild; + } + + public class GenericMixedEntityDescriptor : EntityDescriptor + where T : INodeBuilder, new() + where U : INodeBuilder, new() + where V : INodeBuilder, new() + { + static GenericMixedEntityDescriptor() + { + _nodesToBuild = new INodeBuilder[] + { + new T(), + new U(), + new V() + }; + } + public GenericMixedEntityDescriptor(params object[] componentsImplementor) : + base(_nodesToBuild, componentsImplementor) + { } + + static readonly INodeBuilder[] _nodesToBuild; + } + + public class GenericMixedEntityDescriptor : EntityDescriptor + where T : INodeBuilder, new() + where U : INodeBuilder, new() + where V : INodeBuilder, new() + where W : INodeBuilder, new() + { + static GenericMixedEntityDescriptor() { + _nodesToBuild = new INodeBuilder[] + { + new T(), + new U(), + new V(), + new W() + }; } - static INodeBuilder[] _nodesToBuild; + public GenericMixedEntityDescriptor(params object[] componentsImplementor) : + base(_nodesToBuild, componentsImplementor) + { } + + static readonly INodeBuilder[] _nodesToBuild; + } + + public class GenericMixedEntityDescriptor : EntityDescriptor + where T : INodeBuilder, new() + where U : INodeBuilder, new() + where V : INodeBuilder, new() + where W : INodeBuilder, new() + where X : INodeBuilder, new() + { + static GenericMixedEntityDescriptor() + { + _nodesToBuild = new INodeBuilder[] + { + new T(), + new U(), + new V(), + new W(), + new X() + }; + } + public GenericMixedEntityDescriptor(params object[] componentsImplementor) : + base(_nodesToBuild, componentsImplementor) + { } + + static readonly INodeBuilder[] _nodesToBuild; + } + + public class GenericMixedEntityDescriptor : EntityDescriptor + where T : INodeBuilder, new() + where U : INodeBuilder, new() + where V : INodeBuilder, new() + where W : INodeBuilder, new() + where X : INodeBuilder, new() + where Y : INodeBuilder, new() + { + static GenericMixedEntityDescriptor() + { + _nodesToBuild = new INodeBuilder[] + { + new T(), + new U(), + new V(), + new W(), + new X(), + new Y() + }; + } + public GenericMixedEntityDescriptor(params object[] componentsImplementor) : + base(_nodesToBuild, componentsImplementor) + { } + + static readonly INodeBuilder[] _nodesToBuild; } } diff --git a/ECS/ICallBackOnAddEngine.cs b/ECS/ICallBackOnAddEngine.cs index 30ac6de..815d59d 100644 --- a/ECS/ICallBackOnAddEngine.cs +++ b/ECS/ICallBackOnAddEngine.cs @@ -1,7 +1,7 @@ namespace Svelto.ECS { - interface ICallBackOnAddEngine + public interface ICallBackOnAddEngine { void Ready(); } -} \ No newline at end of file +} diff --git a/ECS/IEngine.cs b/ECS/IEngine.cs index 3d67fcd..b39e4df 100644 --- a/ECS/IEngine.cs +++ b/ECS/IEngine.cs @@ -1,27 +1,14 @@ -namespace Svelto.ECS -{ - public interface IEngine - {} - - public interface INodeEngine:IEngine where TNodeType:INode - { - void Add(TNodeType obj); - void Remove(TNodeType obj); - } - - public interface INodeEngine:INodeEngine where T:INode where U:INode - { - void Add(T obj); - void Remove(T obj); - } +using Svelto.ECS.Internal; - public interface INodeEngine:INodeEngine where T:INode where U:INode where V:INode +namespace Svelto.ECS.Internal +{ + public interface IActivableNodeEngine : IEngine { - void Add(T obj); - void Remove(T obj); + void Enable(INode obj); + void Disable(INode obj); } - public interface INodeEngine:IEngine + public interface INodeEngine : IEngine { void Add(INode obj); void Remove(INode obj); @@ -31,9 +18,19 @@ namespace Svelto.ECS { System.Type[] AcceptedNodes(); } +} + +namespace Svelto.ECS +{ + public interface IEngine + {} + + public interface IActivableNodeEngine : IActivableNodeEngine where TNodeType : INode + { } public interface IQueryableNodeEngine:IEngine { IEngineNodeDB nodesDB { set; } } } + diff --git a/ECS/IEngineNodeDB.cs b/ECS/IEngineNodeDB.cs index 6103ad0..5e8a154 100644 --- a/ECS/IEngineNodeDB.cs +++ b/ECS/IEngineNodeDB.cs @@ -6,16 +6,14 @@ namespace Svelto.ECS { ReadOnlyDictionary QueryIndexableNodes() where T:INode; - bool QueryNode(int ID, out T node) where T:INode; + bool TryQueryNode(int ID, out T node) where T:INode; T QueryNode(int ID) where T:INode; FasterReadOnlyListCast QueryNodes() where T:INode; -// FasterReadOnlyList QueryStructNodes() where T : struct; - - bool QueryNodeFromGroup(int ID, out T node) where T : INode; - T QueryNodeFromGroup(int ID) where T : INode; - FasterReadOnlyListCast QueryNodesFromGroups() where T : INode; + bool TryQueryMetaNode(int metaEntityID, out T node) where T : INode; + T QueryMetaNode(int metaEntityID) where T : INode; + FasterReadOnlyListCast QueryMetaNodes() where T : INode; } } diff --git a/ECS/IEnginesRoot.cs b/ECS/IEnginesRoot.cs index 72c317a..5535222 100644 --- a/ECS/IEnginesRoot.cs +++ b/ECS/IEnginesRoot.cs @@ -1,3 +1,5 @@ +using Svelto.ECS.Internal; + namespace Svelto.ECS { public interface IEnginesRoot @@ -9,6 +11,8 @@ namespace Svelto.ECS { void BuildEntity(int ID, EntityDescriptor ED); - void BuildEntityGroup(int ID, EntityDescriptor ED); + void BuildMetaEntity(int metaEntityID, EntityDescriptor ED); + + void BuildEntityInGroup(int entityID, int groupID, EntityDescriptor ED); } } diff --git a/ECS/INode.cs b/ECS/INode.cs index 30abb9f..ac85ef8 100644 --- a/ECS/INode.cs +++ b/ECS/INode.cs @@ -3,7 +3,22 @@ namespace Svelto.ECS public interface INode {} - public class NodeWithID: INode + public interface INodeWithID:INode + { + int ID { get; } + } + + public interface IStructNodeWithID : INodeWithID + { + new int ID { get; set; } + } + + public interface IGroupedStructNodeWithID : IStructNodeWithID + { + int groupID { get; set; } + } + + public class NodeWithID: INodeWithID { public static TNodeType BuildNode(int ID) where TNodeType: NodeWithID, new() { diff --git a/ECS/IRemoveEntityComponent.cs b/ECS/IRemoveEntityComponent.cs index a3f1525..5a3ee3b 100644 --- a/ECS/IRemoveEntityComponent.cs +++ b/ECS/IRemoveEntityComponent.cs @@ -6,4 +6,14 @@ namespace Svelto.ECS { Action removeEntity { get; set; } } + + public interface IDisableEntityComponent + { + Action disableEntity { get; set; } + } + + public interface IEnableEntityComponent + { + Action enableEntity { get; set; } + } } diff --git a/ECS/MultipleNodesEngine.cs b/ECS/MultipleNodesEngine.cs new file mode 100644 index 0000000..70586c1 --- /dev/null +++ b/ECS/MultipleNodesEngine.cs @@ -0,0 +1,47 @@ +using Svelto.ECS.Internal; + +namespace Svelto.ECS.Internal +{ + public abstract class MultiNodesEngine + where T : INode + { + protected internal abstract void Add(T node); + protected internal abstract void Remove(T node); + } +} + +namespace Svelto.ECS +{ + public abstract class MultiNodesEngine : INodesEngine + { + public abstract System.Type[] AcceptedNodes(); + + public abstract void Add(INode node); + public abstract void Remove(INode node); + } + + public abstract class MultiNodesEngine : MultiNodesEngine, + INodeEngine + where T : INode + where U : INode + { + protected abstract void Add(T node); + protected abstract void Remove(T node); + + public void Add(INode node) + { + if (node is T) + Add((T) node); + else + ((MultiNodesEngine)(this)).Add((U)node); + } + + public void Remove(INode node) + { + if (node is T) + Remove((T)node); + else + ((MultiNodesEngine)(this)).Remove((U)node); + } + } +} \ No newline at end of file diff --git a/ECS/NodeEngineWrapper.cs b/ECS/NodeEngineWrapper.cs deleted file mode 100644 index 49ec673..0000000 --- a/ECS/NodeEngineWrapper.cs +++ /dev/null @@ -1,66 +0,0 @@ -using System; - -namespace Svelto.ECS.Internal -{ - class NodeEngineWrapper : SingleNodeEngine where T : class, INode - { - INodeEngine engine; - - public NodeEngineWrapper(INodeEngine engine) - { - this.engine = engine; - } - - protected override void Add(T node) - { - engine.Add((T)node); - } - - protected override void Remove(T node) - { - engine.Remove((T)node); - } - } - - class NodeEngineWrapper: SingleNodeEngine where T : class, INode where U : class, INode - { - INodeEngine engine; - - public NodeEngineWrapper(INodeEngine engine) - { - this.engine = engine; - } - - protected override void Add(T node) - { - engine.Add((T)node); - } - - protected override void Remove(T node) - { - engine.Remove((T)node); - } - } - - class NodeEngineWrapper: SingleNodeEngine where T : class, INode - where U : class, INode - where V : class, INode - { - INodeEngine engine; - - public NodeEngineWrapper(INodeEngine engine) - { - this.engine = engine; - } - - protected override void Add(T node) - { - engine.Add((T)node); - } - - protected override void Remove(T node) - { - engine.Remove((T)node); - } - } -} \ No newline at end of file diff --git a/ECS/Profiler/EngineProfiler.cs b/ECS/Profiler/EngineProfiler.cs index 53e7296..0612925 100644 --- a/ECS/Profiler/EngineProfiler.cs +++ b/ECS/Profiler/EngineProfiler.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using Svelto.ECS.Internal; //This profiler is based on the Entitas Visual Debugging tool //https://github.com/sschmid/Entitas-CSharp diff --git a/ECS/Profiler/EngineProfilerBehaviour.cs b/ECS/Profiler/EngineProfilerBehaviour.cs index 9039a2a..c924d6c 100644 --- a/ECS/Profiler/EngineProfilerBehaviour.cs +++ b/ECS/Profiler/EngineProfilerBehaviour.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using UnityEngine; diff --git a/ECS/SingleNodeEngine.cs b/ECS/SingleNodeEngine.cs index d92b840..3d7a45f 100644 --- a/ECS/SingleNodeEngine.cs +++ b/ECS/SingleNodeEngine.cs @@ -1,15 +1,18 @@ -namespace Svelto.ECS +using Svelto.ECS.Internal; + +namespace Svelto.ECS { - public abstract class SingleNodeEngine : INodeEngine where TNodeType : class, INode + public abstract class SingleNodeEngine : INodeEngine + where TNodeType : class, INode { - void INodeEngine.Add(INode obj) + public void Add(INode obj) { - Add(obj as TNodeType); + Add((TNodeType) obj); } - void INodeEngine.Remove(INode obj) + public void Remove(INode obj) { - Remove(obj as TNodeType); + Remove((TNodeType) obj); } protected abstract void Add(TNodeType node); diff --git a/ECS/StructNodes.cs b/ECS/StructNodes.cs new file mode 100644 index 0000000..aa708f4 --- /dev/null +++ b/ECS/StructNodes.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using Svelto.DataStructures; +using Svelto.ECS.Internal; + +namespace Svelto.ECS +{ + public class StructNodes: IStructNodes where T:struct, IStructNodeWithID + { + public FasterList list + { + get + { + return _internalList; + } + } + + public StructNodes() + { + _internalList = new FasterList(); + } + + public void Add(T node) + { + T convert = (T)node; + + _internalList.Add(convert); + } + + readonly FasterList _internalList; + } + + public class StructGroupNodes: IStructGroupNodes + where T : struct, IGroupedStructNodeWithID + { + public void Add(int groupID, T node) + { + T convert = (T)node; + + var fasterList = GetList(groupID); + _indices[node.ID] = fasterList.Count; + + fasterList.Add(convert); + } + + public void Remove(int groupID, T node) + { + var fasterList = GetList(groupID); + var index = _indices[node.ID]; + _indices.Remove(node.ID); + + if (fasterList.UnorderedRemoveAt(index)) + _indices[fasterList[index].ID] = index; + } + + public FasterList GetList(int groupID) + { + return _nodes[groupID]; + } + + readonly Dictionary _indices = new Dictionary(); + Dictionary> _nodes = new Dictionary>(); + } +} + +namespace Svelto.ECS.Internal +{ + public interface IStructGroupNodes + { + } + + public interface IStructNodes + { + } +} \ No newline at end of file diff --git a/ECS/note.txt b/ECS/note.txt new file mode 100644 index 0000000..c041193 --- /dev/null +++ b/ECS/note.txt @@ -0,0 +1,111 @@ +systems do not hold component data, but only system states +systems cannot be injected +systems are SRP and OCP +systems communicates between component, mediators, producer/consumer, observers. producer/consumer and observers must be defined in the layer of the engine. +systems can have injected dependencies + +components don't have logic +components can have only getter and setter +components cannot define patterns that requires logic. +components cannot issues commands + +High Cohesion[edit] +Main article: Cohesion (computer science) +High Cohesion is an evaluative pattern that attempts to keep objects appropriately focused, manageable and understandable. High cohesion is generally used in support of Low Coupling. High cohesion means that the responsibilities of a given element are strongly related and highly focused. Breaking programs into classes and subsystems is an example of activities that increase the cohesive properties of a system. Alternatively, low cohesion is a situation in which a given element has too many unrelated responsibilities. Elements with low cohesion often suffer from being hard to comprehend, hard to reuse, hard to maintain and averse to change.[3] + +Low Coupling[edit] +Main article: Loose coupling +Low Coupling is an evaluative pattern, which dictates how to assign responsibilities to support: + +lower dependency between the classes, +change in one class having lower impact on other classes, +higher reuse potential. + +events, observers and mediators have the inconvience to hold the reference to the engine, which forces to use cleanup if the engine must be removed. +Observers are easy to clean up from the engine. Mediators needs to be integrated to the framework to be simple to clean up. Component events need the clean up function. +producer/consumer has the inconvienent to force check the number of jobs available everyframe + +Engine can't be removed, they can only be disabled, but the logic of disabling must be handled by the engine itself + +Should components have just one element? Should engines use just nodes? Components are ditacted by the entities and Nodes by the engines + +http://thelinuxlich.github.io/artemis_CSharp/ + +differences: components no events, everthing must be update +give more responsabiltiy to the user, semplicity + +https://github.com/sschmid/Entitas-CSharp/wiki/Overview + +no groups, no queries + +http://entity-systems.wikidot.com/es-articles + +http://www.ashframework.org/ + +it's very important to give a namespace to the engines. In this way it's impossible to create semantically wrong nodes (PlayerNode Vs TargetNode) + +ToDo: + +it's not safe to remove an engine without having called being denitialised internal states. A special ClearOnRemove function must be added for each engine + +namespace GameFramework.RayCast +{ + public class RayCastEngineEngine + { + public RayCastEngine(RayCastEmployer jobList) + { + jobList.onJobassigned += OnRaycastRequested; + } + + public void Add(IComponent obj) + {} + + public void Remove(IComponent obj) + {} + + void OnRaycastRequested(RayCastJob job) + { + RaycastHit shootHit; + + Physics.Raycast(job.rayVector, out shootHit, job.range, _enemyMask); + + job.Done(shootHit); + } + + RayCastEmployer _employer; + + int _enemyMask; + } + + public struct RayCastJob + { + readonly public Ray rayVector; + readonly public float range; + readonly public Action Done; + + public RayCastJob(Ray direction, float distance, Action OnDone) + { + rayVector = direction; + range = distance; + Done = OnDone; + } + } + + public class RayCastEmployer + { + public event Action onJobassigned; + + public void AssignJob(RayCastJob data, Action onJobdone) + { + onJobassigned(data); + } + } +} + +if your code can be read as + +A tells B to do something is direct +A register B event is indirect +althoggh if B tells A something through event is direct again. B must say something like I don't know who you are, but this just happened. you say B.SomethingHappenedToMe() not B.YouMustDoThis(); + +un engine non deve mai avere concetti di un altro engine. dire all'engine sonoro suona morte � sbagliato. � l'engine death che triggera l'evento e l'engine sound ad ascoltarlo. diff --git a/Utilities/DesignByContract.cs b/Utilities/DesignByContract.cs index 9a76411..d34861e 100644 --- a/Utilities/DesignByContract.cs +++ b/Utilities/DesignByContract.cs @@ -324,18 +324,18 @@ namespace DesignByContract useAssertions = value; } } + + #endregion // Interface - #endregion // Interface - - #region Implementation + #region Implementation - // No creation - Check() { } + // No creation + private Check() {} - /// - /// Is exception handling being used? - /// - private static bool UseExceptions + /// + /// Is exception handling being used? + /// + private static bool UseExceptions { get { @@ -343,15 +343,15 @@ namespace DesignByContract } } - // Are trace assertion statements being used? - // Default is to use exception handling. - static bool useAssertions = false; + // Are trace assertion statements being used? + // Default is to use exception handling. + private static bool useAssertions = false; - #endregion // Implementation + #endregion // Implementation - } // End Check + } // End Check - class Trace + internal class Trace { internal static void Assert(bool assertion, string v) { diff --git a/Utilities/Print.cs b/Utilities/Print.cs index 0d7e601..095c110 100644 --- a/Utilities/Print.cs +++ b/Utilities/Print.cs @@ -136,7 +136,7 @@ namespace Utility logger.Log(txt); } - public static void LogError(string txt, bool showCurrentStack = true) + public static void LogError(string txt) { string toPrint; @@ -148,11 +148,8 @@ namespace Utility toPrint = _stringBuilder.ToString(); } -#if !NETFX_CORE - logger.Log(toPrint, showCurrentStack == true ? new StackTrace().ToString() : null, LogType.Error); -#else + logger.Log(toPrint, null, LogType.Error); -#endif } public static void LogError(string txt, string stack) diff --git a/Utilities/WeakActionStruct.cs b/Utilities/WeakActionStruct.cs index dff59f6..318027b 100644 --- a/Utilities/WeakActionStruct.cs +++ b/Utilities/WeakActionStruct.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; diff --git a/Utilities/WeakEvent.cs b/Utilities/WeakEvent.cs index e912490..91aa235 100644 --- a/Utilities/WeakEvent.cs +++ b/Utilities/WeakEvent.cs @@ -1,5 +1,6 @@ using Svelto.DataStructures; using System; +using System.Collections.Generic; namespace BetterWeakEvents { @@ -13,7 +14,7 @@ namespace BetterWeakEvents public static WeakEvent operator-(WeakEvent c1, Action x) { - c1._subscribers.UnorderredRemove(new WeakAction(x)); + c1._subscribers.UnorderedRemove(new WeakAction(x)); return c1; } @@ -21,7 +22,7 @@ namespace BetterWeakEvents { for (int i = 0; i < _subscribers.Count; i++) if (_subscribers[i].Invoke(arg1, arg2) == false) - _subscribers.UnorderredRemoveAt(i--); + _subscribers.UnorderedRemoveAt(i--); } ~WeakEvent() @@ -32,4 +33,4 @@ namespace BetterWeakEvents protected FasterList> _subscribers = new FasterList>(); } -} \ No newline at end of file +} From 345392dff547d245b28224e43cd9bea923d1da40 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sat, 21 Oct 2017 20:01:48 +0100 Subject: [PATCH 7/7] - Added new features to be able to handle nodes as pure structs - FasterList Clear has been renamed to FastClear. The standard Clear will clean the array like the normal List does - An engine can now receive callback for when nodes are disabled and enabled - --- DataStructures/FasterList.cs | 30 +++- DataStructures/LockFreeQueue.cs | 142 ++++++++++++++++++ .../Priority Queue/HeapPriorityQueue.cs | 2 +- DataStructures/ThreadSafeDictionary.cs | 2 - ECS/EngineNodeDB.cs | 8 +- ECS/EnginesRoot.cs | 74 +++++---- ECS/EntityDescriptor.cs | 38 ++--- ECS/IEngine.cs | 26 ++++ ECS/IEnginesRoot.cs | 2 +- ECS/INode.cs | 6 +- ...ipleNodesEngine.cs => MultiNodesEngine.cs} | 20 +-- ECS/SingleNodeEngine.cs | 2 +- ECS/StructNodes.cs | 110 +++++++++++--- Utilities/DesignByContract.cs | 6 +- 14 files changed, 353 insertions(+), 115 deletions(-) create mode 100644 DataStructures/LockFreeQueue.cs rename ECS/{MultipleNodesEngine.cs => MultiNodesEngine.cs} (62%) diff --git a/DataStructures/FasterList.cs b/DataStructures/FasterList.cs index 40407e4..6828af0 100644 --- a/DataStructures/FasterList.cs +++ b/DataStructures/FasterList.cs @@ -121,6 +121,8 @@ namespace Svelto.DataStructures public struct FasterReadOnlyList : IList { + public static FasterReadOnlyList DefaultList = new FasterReadOnlyList(new FasterList()); + public int Count { get { return _list.Count; } } public bool IsReadOnly { get { return true; } } @@ -274,6 +276,19 @@ namespace Svelto.DataStructures } } + public void FastClear() + { + _lockQ.EnterWriteLock(); + try + { + _list.FastClear(); + } + finally + { + _lockQ.ExitWriteLock(); + } + } + public bool Contains(T item) { _lockQ.EnterReadLock(); @@ -382,6 +397,8 @@ namespace Svelto.DataStructures public struct FasterReadOnlyListCast : IList where U:T { + public static FasterReadOnlyListCast DefaultList = new FasterReadOnlyListCast(new FasterList()); + public int Count { get { return _list.Count; } } public bool IsReadOnly { get { return true; } } @@ -455,7 +472,6 @@ namespace Svelto.DataStructures public class FasterList : IList, IFasterList { - public static FasterList DefaultList = new FasterList(); const int MIN_SIZE = 4; public int Count @@ -529,7 +545,7 @@ namespace Svelto.DataStructures for (int i = 0; i < initialSize; i++) list.Add(new U()); - list.Clear(); + list._count = 0; return list; } @@ -583,12 +599,12 @@ namespace Svelto.DataStructures /// Careful, you could keep on holding references you don't want to hold to anymore /// Use DeepClear in case. /// - public void Clear() + public void FastClear() { _count = 0; } - public void DeepClear() + public void Clear() { Array.Clear(_buffer, 0, _buffer.Length); @@ -727,11 +743,13 @@ namespace Svelto.DataStructures DesignByContract.Check.Require(index < _count && _count > 0, "out of bound index"); if (index == --_count) + { + _buffer[_count] = default(T); return false; + } - T swap = _buffer[index]; _buffer[index] = _buffer[_count]; - _buffer[_count] = swap; + _buffer[_count] = default(T); return true; } diff --git a/DataStructures/LockFreeQueue.cs b/DataStructures/LockFreeQueue.cs new file mode 100644 index 0000000..01ae6e5 --- /dev/null +++ b/DataStructures/LockFreeQueue.cs @@ -0,0 +1,142 @@ +using System.Collections.Generic; +using System.Threading; + +//from unify wiki +namespace Svelto.DataStructures +{ + public class SingleLinkNode + { + // Note; the Next member cannot be a property since + // it participates in many CAS operations + public SingleLinkNode Next; + public T Item; + } + + public static class SyncMethods + { + public static bool CAS(ref T location, T comparand, T newValue) where T : class + { + return + (object)comparand == + (object)Interlocked.CompareExchange(ref location, newValue, comparand); + } + } + + public class LockFreeLinkPool + { + private SingleLinkNode head; + + public LockFreeLinkPool() + { + head = new SingleLinkNode(); + } + + public void Push(SingleLinkNode newNode) + { + newNode.Item = default(T); + do + { + newNode.Next = head.Next; + } while (!SyncMethods.CAS>(ref head.Next, newNode.Next, newNode)); + return; + } + + public bool Pop(out SingleLinkNode node) + { + do + { + node = head.Next; + if (node == null) + { + return false; + } + } while (!SyncMethods.CAS>(ref head.Next, node, node.Next)); + return true; + } + } + + public class LockFreeQueue + { + + SingleLinkNode head; + SingleLinkNode tail; + LockFreeLinkPool trash; + + public LockFreeQueue() + { + head = new SingleLinkNode(); + tail = head; + trash = new LockFreeLinkPool(); + } + + public void Enqueue(T item) + { + SingleLinkNode oldTail = null; + SingleLinkNode oldTailNext; + + SingleLinkNode newNode; + if (!trash.Pop(out newNode)) + { + newNode = new SingleLinkNode(); + } + else + { + newNode.Next = null; + } + newNode.Item = item; + + bool newNodeWasAdded = false; + while (!newNodeWasAdded) + { + oldTail = tail; + oldTailNext = oldTail.Next; + + if (tail == oldTail) + { + if (oldTailNext == null) + newNodeWasAdded = SyncMethods.CAS>(ref tail.Next, null, newNode); + else + SyncMethods.CAS>(ref tail, oldTail, oldTailNext); + } + } + SyncMethods.CAS>(ref tail, oldTail, newNode); + } + + public bool Dequeue(out T item) + { + item = default(T); + SingleLinkNode oldHead = null; + + bool haveAdvancedHead = false; + while (!haveAdvancedHead) + { + + oldHead = head; + SingleLinkNode oldTail = tail; + SingleLinkNode oldHeadNext = oldHead.Next; + + if (oldHead == head) + { + if (oldHead == oldTail) + { + if (oldHeadNext == null) + { + return false; + } + SyncMethods.CAS>(ref tail, oldTail, oldHeadNext); + } + else + { + item = oldHeadNext.Item; + haveAdvancedHead = SyncMethods.CAS>(ref head, oldHead, oldHeadNext); + if (haveAdvancedHead) + { + trash.Push(oldHead); + } + } + } + } + return true; + } + } +} \ No newline at end of file diff --git a/DataStructures/Priority Queue/HeapPriorityQueue.cs b/DataStructures/Priority Queue/HeapPriorityQueue.cs index c30e06d..606acd5 100644 --- a/DataStructures/Priority Queue/HeapPriorityQueue.cs +++ b/DataStructures/Priority Queue/HeapPriorityQueue.cs @@ -66,7 +66,7 @@ namespace Svelto.DataStructures #endif public void Clear() { - _nodes.Clear(); + _nodes.FastClear(); _numNodes = 0; } diff --git a/DataStructures/ThreadSafeDictionary.cs b/DataStructures/ThreadSafeDictionary.cs index 0bfb662..19e72e4 100644 --- a/DataStructures/ThreadSafeDictionary.cs +++ b/DataStructures/ThreadSafeDictionary.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; using System.Threading; -//note, rewrite like ThreadSafeQueue - namespace Svelto.DataStructures { /// diff --git a/ECS/EngineNodeDB.cs b/ECS/EngineNodeDB.cs index 36bef54..c10540f 100644 --- a/ECS/EngineNodeDB.cs +++ b/ECS/EngineNodeDB.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using Svelto.DataStructures; -using Svelto.ECS.Internal; namespace Svelto.ECS { @@ -9,13 +8,11 @@ namespace Svelto.ECS { internal EngineNodeDB( Dictionary> nodesDB, Dictionary> nodesDBdic, - Dictionary> metaNodesDB, - Dictionary structNodesDB) + Dictionary> metaNodesDB) { _nodesDB = nodesDB; _nodesDBdic = nodesDBdic; _metaNodesDB = metaNodesDB; - _structNodesDB = structNodesDB; } public FasterReadOnlyListCast QueryNodes() where T:INode @@ -102,13 +99,12 @@ namespace Svelto.ECS static FasterReadOnlyListCast RetrieveEmptyNodeList() where T : INode { - return new FasterReadOnlyListCast(FasterList.DefaultList); + return FasterReadOnlyListCast.DefaultList; } readonly Dictionary> _nodesDB; readonly Dictionary> _nodesDBdic; readonly Dictionary> _metaNodesDB; - readonly Dictionary _structNodesDB; readonly ReadOnlyDictionary _defaultEmptyNodeDict = new ReadOnlyDictionary(new Dictionary()); } diff --git a/ECS/EnginesRoot.cs b/ECS/EnginesRoot.cs index a70807b..4aa482a 100644 --- a/ECS/EnginesRoot.cs +++ b/ECS/EnginesRoot.cs @@ -16,23 +16,6 @@ using System.Reflection; namespace Svelto.ECS { - class Scheduler : MonoBehaviour - { - IEnumerator Start() - { - while (true) - { - yield return _waitForEndOfFrame; - - OnTick(); - } - } - - internal Action OnTick; - - readonly WaitForEndOfFrame _waitForEndOfFrame = new WaitForEndOfFrame(); - } - public sealed class EnginesRoot : IEnginesRoot, IEntityFactory { public EnginesRoot(NodeSubmissionScheduler nodeScheduler) @@ -50,7 +33,8 @@ namespace Svelto.ECS _metaNodesToAdd = new FasterList(); _metaNodesDB = new Dictionary>(); - _structNodesDB = new Dictionary(); + _sharedStructNodeLists = new SharedStructNodeLists(); + _sharedGroupedStructNodeLists = new SharedGroupedStructNodesLists(); _internalRemove = InternalRemove; _internalDisable = InternalDisable; @@ -60,6 +44,8 @@ namespace Svelto.ECS _scheduler = nodeScheduler; _scheduler.Schedule(SubmitNodes); + _structNodeEngineType = typeof(IStructNodeEngine<>); + _groupedStructNodesEngineType = typeof(IGroupedStructNodesEngine<>); _activableNodeEngineType = typeof(IActivableNodeEngine<>); _implementedInterfaceTypes = new Dictionary(); @@ -84,9 +70,11 @@ namespace Svelto.ECS do { + var nodesToAdd = _nodesToAdd.ToArrayFast(); + for (int i = startNodes; i < nodesCount; i++) { - var node = _nodesToAdd[i]; + var node = nodesToAdd[i]; var nodeType = node.GetType(); AddNodeToTheDB(node, nodeType); @@ -95,9 +83,11 @@ namespace Svelto.ECS AddNodeToNodesDictionary(nodeWithId, nodeType); } + var metaNodesToAdd = _metaNodesToAdd.ToArrayFast(); + for (int i = startMetaNodes; i < metaNodesCount; i++) { - var node = _metaNodesToAdd[i]; + var node = metaNodesToAdd[i]; var nodeType = node.GetType(); AddNodeToMetaDB(node, nodeType); @@ -108,13 +98,13 @@ namespace Svelto.ECS for (int i = startNodes; i < nodesCount; i++) { - var node = _nodesToAdd[i]; + var node = nodesToAdd[i]; AddNodeToTheSuitableEngines(node, node.GetType()); } for (int i = startMetaNodes; i < metaNodesCount; i++) { - var node = _metaNodesToAdd[i]; + var node = metaNodesToAdd[i]; AddNodeToTheSuitableEngines(node, node.GetType()); } @@ -147,7 +137,7 @@ namespace Svelto.ECS var queryableNodeEngine = engine as IQueryableNodeEngine; if (queryableNodeEngine != null) queryableNodeEngine.nodesDB = - new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB, _structNodesDB); + new EngineNodeDB(_nodesDB, _nodesDBdic, _metaNodesDB); var engineType = engine.GetType(); var implementedInterfaces = engineType.GetInterfaces(); @@ -185,8 +175,6 @@ namespace Svelto.ECS } var genericTypeDefinition = interfaceType.GetGenericTypeDefinition(); - var a = interfaceType.GetGenericArguments(); - var b = genericTypeDefinition.GetGenericArguments(); _implementedInterfaceTypes.Add(genericTypeDefinition, interfaceType.GetGenericArguments()); @@ -199,6 +187,18 @@ namespace Svelto.ECS bool engineAdded = false; + if (_implementedInterfaceTypes.ContainsKey(_structNodeEngineType)) + { + ((IStructNodeEngine)engine).CreateStructNodes + (_sharedStructNodeLists); + } + + if (_implementedInterfaceTypes.ContainsKey(_groupedStructNodesEngineType)) + { + ((IGroupedStructNodesEngine)engine).CreateStructNodes + (_sharedGroupedStructNodeLists); + } + Type[] arguments; if (_implementedInterfaceTypes.TryGetValue(_activableNodeEngineType, out arguments)) @@ -298,7 +298,7 @@ namespace Svelto.ECS /// /// /// - public void BuildEntityInGroup(int entityID, int groupID, + public void BuildEntityInGroup(short entityID, short groupID, EntityDescriptor ed) { var entityNodes = ed.BuildNodes(entityID, @@ -349,19 +349,10 @@ namespace Svelto.ECS void AddNodeToTheDB(T node, Type nodeType) where T : INode { FasterList nodes; + if (_nodesDB.TryGetValue(nodeType, out nodes) == false) + nodes = _nodesDB[nodeType] = new FasterList(); - if (node is IStructNodeWithID == false) - { - if (_nodesDB.TryGetValue(nodeType, out nodes) == false) - nodes = _nodesDB[nodeType] = new FasterList(); - - nodes.Add(node); - } - else - { - if (_nodesDB.TryGetValue(nodeType, out nodes) == false) - nodes = _nodesDB[nodeType] = new FasterList(); - } + nodes.Add(node); } void AddNodeToNodesDictionary(T node, Type nodeType) where T : INodeWithID @@ -535,14 +526,15 @@ namespace Svelto.ECS readonly Dictionary> _nodesDB; readonly Dictionary> _metaNodesDB; - readonly Dictionary _structNodesDB; readonly Dictionary> _nodesDBdic; readonly FasterList _nodesToAdd; readonly FasterList _metaNodesToAdd; - readonly WeakReference _engineRootWeakReference; + readonly WeakReference _engineRootWeakReference; + readonly SharedStructNodeLists _sharedStructNodeLists; + readonly SharedGroupedStructNodesLists _sharedGroupedStructNodeLists; readonly NodeSubmissionScheduler _scheduler; @@ -551,6 +543,8 @@ namespace Svelto.ECS readonly Action> _internalDisable; readonly Action> _internalMetaRemove; + readonly Type _structNodeEngineType; + readonly Type _groupedStructNodesEngineType; readonly Type _activableNodeEngineType; readonly Dictionary _implementedInterfaceTypes; diff --git a/ECS/EntityDescriptor.cs b/ECS/EntityDescriptor.cs index 1550f60..946e1a8 100644 --- a/ECS/EntityDescriptor.cs +++ b/ECS/EntityDescriptor.cs @@ -10,10 +10,12 @@ namespace Svelto.ECS { public class EntityDescriptor { - protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor) + protected EntityDescriptor(INodeBuilder[] nodesToBuild) { _nodesToBuild = new FasterList(nodesToBuild); - + } + protected EntityDescriptor(INodeBuilder[] nodesToBuild, params object[] componentsImplementor):this(nodesToBuild) + { ProcessImplementors(componentsImplementor); } @@ -84,12 +86,9 @@ namespace Svelto.ECS Action> disableEntity, FasterList nodes) { - Action removeEntityAction = () => - { removeEntity(nodes); nodes.Clear(); }; - Action disableEntityAction = () => - { disableEntity(nodes); }; - Action enableEntityAction = () => - { enableEntity(nodes); }; + Action removeEntityAction = () => { removeEntity(nodes); nodes.Clear(); }; + Action disableEntityAction = () => disableEntity(nodes); + Action enableEntityAction = () => enableEntity(nodes); for (int index = 0; index < _removingImplementors.Count; index++) _removingImplementors[index].removeEntity = removeEntityAction; @@ -99,7 +98,7 @@ namespace Svelto.ECS _enablingImplementors[index].enableEntity = enableEntityAction; } - INode FillNode(INode node, FillNodeMode mode) + TNode FillNode(TNode node, FillNodeMode mode) where TNode : INode { var fields = node.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance); @@ -131,21 +130,21 @@ namespace Svelto.ECS readonly FasterList _disablingImplementors = new FasterList(); readonly FasterList _removingImplementors = new FasterList(); readonly FasterList _enablingImplementors = new FasterList(); - readonly Dictionary _implementorsByType = new Dictionary(); + readonly FasterList _nodesToBuild; } public interface INodeBuilder { - INodeWithID Build(int ID); + INode Build(int ID); FillNodeMode reflects { get; } } public class NodeBuilder : INodeBuilder where NodeType : NodeWithID, new() { - public INodeWithID Build(int ID) + public INode Build(int ID) { NodeWithID node = NodeWithID.BuildNode(ID); @@ -155,20 +154,25 @@ namespace Svelto.ECS public FillNodeMode reflects { get { return FillNodeMode.Strict; } } } - //To Do: Probably I will need to add an - //FastStructNodeBuilder where reflects is false public class StructNodeBuilder : INodeBuilder where NodeType : struct, IStructNodeWithID { - public INodeWithID Build(int ID) + public INode Build(int ID) { + var shortID = (short)ID; IStructNodeWithID node = default(NodeType); - node.ID = ID; + node.ID = shortID; return node; } - public FillNodeMode reflects { get { return FillNodeMode.Relaxed; } } + public virtual FillNodeMode reflects { get { return FillNodeMode.Relaxed; } } + } + + public class FastStructNodeBuilder : StructNodeBuilder + where NodeType : struct, IStructNodeWithID + { + public override FillNodeMode reflects { get { return FillNodeMode.None; } } } public enum FillNodeMode diff --git a/ECS/IEngine.cs b/ECS/IEngine.cs index b39e4df..d811e9a 100644 --- a/ECS/IEngine.cs +++ b/ECS/IEngine.cs @@ -2,6 +2,16 @@ using Svelto.ECS.Internal; namespace Svelto.ECS.Internal { + public interface IStructNodeEngine : IEngine + { + void CreateStructNodes(SharedStructNodeLists sharedStructNodeLists); + } + + public interface IGroupedStructNodesEngine : IEngine + { + void CreateStructNodes(SharedGroupedStructNodesLists sharedStructNodeLists); + } + public interface IActivableNodeEngine : IEngine { void Enable(INode obj); @@ -32,5 +42,21 @@ namespace Svelto.ECS { IEngineNodeDB nodesDB { set; } } + + /// + /// The engines can receive and store INodes structs + /// Unboxing will happen during the Add, but the + /// data will then be stored and processed as stucts + /// + public interface IStructNodeEngine : IStructNodeEngine where T:struct, IStructNodeWithID + { } + + /// + /// same as above, but the nodes are grouped by ID + /// usually the ID is the owner of the nodes of that + /// group + /// + public interface IGroupedStructNodesEngine : IGroupedStructNodesEngine where T:struct, IGroupedStructNodeWithID + { } } diff --git a/ECS/IEnginesRoot.cs b/ECS/IEnginesRoot.cs index 5535222..544fbc6 100644 --- a/ECS/IEnginesRoot.cs +++ b/ECS/IEnginesRoot.cs @@ -13,6 +13,6 @@ namespace Svelto.ECS void BuildMetaEntity(int metaEntityID, EntityDescriptor ED); - void BuildEntityInGroup(int entityID, int groupID, EntityDescriptor ED); + void BuildEntityInGroup(short entityID, short groupID, EntityDescriptor ED); } } diff --git a/ECS/INode.cs b/ECS/INode.cs index ac85ef8..3f3999c 100644 --- a/ECS/INode.cs +++ b/ECS/INode.cs @@ -8,14 +8,14 @@ namespace Svelto.ECS int ID { get; } } - public interface IStructNodeWithID : INodeWithID + public interface IStructNodeWithID : INode { - new int ID { get; set; } + short ID { get; set; } } public interface IGroupedStructNodeWithID : IStructNodeWithID { - int groupID { get; set; } + short groupID { get; set; } } public class NodeWithID: INodeWithID diff --git a/ECS/MultipleNodesEngine.cs b/ECS/MultiNodesEngine.cs similarity index 62% rename from ECS/MultipleNodesEngine.cs rename to ECS/MultiNodesEngine.cs index 70586c1..2907917 100644 --- a/ECS/MultipleNodesEngine.cs +++ b/ECS/MultiNodesEngine.cs @@ -5,8 +5,8 @@ namespace Svelto.ECS.Internal public abstract class MultiNodesEngine where T : INode { - protected internal abstract void Add(T node); - protected internal abstract void Remove(T node); + protected abstract void AddNode(T node); + protected abstract void RemoveNode(T node); } } @@ -20,28 +20,28 @@ namespace Svelto.ECS public abstract void Remove(INode node); } - public abstract class MultiNodesEngine : MultiNodesEngine, + public abstract class MultiNodesEngine : MultiNodesEngine, INodeEngine - where T : INode + where T : INode where U : INode { - protected abstract void Add(T node); - protected abstract void Remove(T node); + protected abstract void AddNode(U node); + protected abstract void RemoveNode(U node); public void Add(INode node) { if (node is T) - Add((T) node); + AddNode((T)node); else - ((MultiNodesEngine)(this)).Add((U)node); + AddNode((U)node); } public void Remove(INode node) { if (node is T) - Remove((T)node); + RemoveNode((T)node); else - ((MultiNodesEngine)(this)).Remove((U)node); + RemoveNode((U)node); } } } \ No newline at end of file diff --git a/ECS/SingleNodeEngine.cs b/ECS/SingleNodeEngine.cs index 3d7a45f..e641f32 100644 --- a/ECS/SingleNodeEngine.cs +++ b/ECS/SingleNodeEngine.cs @@ -3,7 +3,7 @@ namespace Svelto.ECS { public abstract class SingleNodeEngine : INodeEngine - where TNodeType : class, INode + where TNodeType : INode { public void Add(INode obj) { diff --git a/ECS/StructNodes.cs b/ECS/StructNodes.cs index aa708f4..582abab 100644 --- a/ECS/StructNodes.cs +++ b/ECS/StructNodes.cs @@ -1,22 +1,21 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Svelto.DataStructures; using Svelto.ECS.Internal; namespace Svelto.ECS { - public class StructNodes: IStructNodes where T:struct, IStructNodeWithID + public class StructNodes where T:struct, IStructNodeWithID { - public FasterList list + public T[] GetList(out int numberOfItems) { - get - { - return _internalList; - } + numberOfItems = _internalList.Count; + return _internalList.ToArrayFast(); } - public StructNodes() + public StructNodes(SharedStructNodeLists container) { - _internalList = new FasterList(); + _internalList = container.GetList(); } public void Add(T node) @@ -29,46 +28,107 @@ namespace Svelto.ECS readonly FasterList _internalList; } - public class StructGroupNodes: IStructGroupNodes + public class StructGroupNodes where T : struct, IGroupedStructNodeWithID { + public StructGroupNodes(SharedGroupedStructNodesLists container) + { + _container = container; + } + public void Add(int groupID, T node) { T convert = (T)node; - var fasterList = GetList(groupID); - _indices[node.ID] = fasterList.Count; + var fasterList = (_container.GetList(groupID) as FasterList); + indices[node.ID] = fasterList.Count; fasterList.Add(convert); } public void Remove(int groupID, T node) { - var fasterList = GetList(groupID); - var index = _indices[node.ID]; - _indices.Remove(node.ID); + var fasterList = (_container.GetList(groupID) as FasterList); + var index = indices[node.ID]; + indices.Remove(node.ID); if (fasterList.UnorderedRemoveAt(index)) - _indices[fasterList[index].ID] = index; + indices[fasterList[index].ID] = index; } - public FasterList GetList(int groupID) + public T[] GetList(int groupID, out int numberOfItems) { - return _nodes[groupID]; + var fasterList = (_container.GetList(groupID) as FasterList); + numberOfItems = fasterList.Count; + return fasterList.ToArrayFast(); } - readonly Dictionary _indices = new Dictionary(); - Dictionary> _nodes = new Dictionary>(); + readonly SharedGroupedStructNodesLists _container; + readonly Dictionary indices = new Dictionary(); } -} -namespace Svelto.ECS.Internal -{ - public interface IStructGroupNodes + public class SharedStructNodeLists { + readonly Dictionary _collection; + + internal SharedStructNodeLists() + { + _collection = new Dictionary(); + } + + internal FasterList GetList() where T:struct + { + IFasterList list; + if (_collection.TryGetValue(typeof (T), out list)) + { + return list as FasterList; + } + + list = new FasterList(); + + _collection.Add(typeof (T), list); + + return (FasterList) list; + } } - public interface IStructNodes + public class SharedGroupedStructNodesLists { + internal SharedGroupedStructNodesLists() + { + _collection = new Dictionary>(); + } + + internal IFasterList GetList(int groupID) where T : struct + { + Dictionary dic = GetGroup(); + IFasterList localList; + + if (dic.TryGetValue(groupID, out localList)) + return localList; + + localList = new FasterList(); + dic.Add(groupID, localList); + + return localList; + } + + internal Dictionary GetGroup() where T : struct + { + Dictionary dic; + + if (_collection.TryGetValue(typeof(T), out dic)) + { + return dic; + } + + dic = new Dictionary(); + + _collection.Add(typeof(T), dic); + + return dic; + } + + readonly Dictionary> _collection; } } \ No newline at end of file diff --git a/Utilities/DesignByContract.cs b/Utilities/DesignByContract.cs index d34861e..0ac9bf8 100644 --- a/Utilities/DesignByContract.cs +++ b/Utilities/DesignByContract.cs @@ -26,10 +26,10 @@ // // Alternatively, you can define these in the project properties dialog. -#if UNITY_EDITOR || ROBO_TEST_BUILD -#define DBC_CHECK_ALL +#if DEBUG && !PROFILER +#define DBC_CHECK_ALL #endif - + using System; using System.Diagnostics;