mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-09-27 10:46:17 +00:00
提交
This commit is contained in:
3
JNFrame2/Assets/Plugins/JNGame/Runtime/Entitas.meta
Normal file
3
JNFrame2/Assets/Plugins/JNGame/Runtime/Entitas.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2dc2b025cc73430e8ca2ddb34aff461d
|
||||
timeCreated: 1715159440
|
3
JNFrame2/Assets/Plugins/JNGame/Runtime/Entitas/Core.meta
Normal file
3
JNFrame2/Assets/Plugins/JNGame/Runtime/Entitas/Core.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36445c10f96840848b0a286dcfe054d1
|
||||
timeCreated: 1720699079
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 110a927b13d93f440acd8271d6c8e28d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18d28ad812b25de4487b5bb2f1f3ac22
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
|
||||
public class CleanupAttribute : Attribute
|
||||
{
|
||||
public readonly CleanupMode cleanupMode;
|
||||
|
||||
public CleanupAttribute(CleanupMode cleanupMode)
|
||||
{
|
||||
this.cleanupMode = cleanupMode;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CleanupMode
|
||||
{
|
||||
RemoveComponent,
|
||||
DestroyEntity
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b30c1f54c5881874194ac30ebf4fcb53
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
|
||||
public class ComponentNameAttribute : Attribute
|
||||
{
|
||||
public readonly string[] componentNames;
|
||||
|
||||
public ComponentNameAttribute(params string[] componentNames)
|
||||
{
|
||||
this.componentNames = componentNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[Obsolete("Use [ComponentName] instead", false)]
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
|
||||
public class CustomComponentNameAttribute : Attribute
|
||||
{
|
||||
public readonly string[] componentNames;
|
||||
|
||||
public CustomComponentNameAttribute(params string[] componentNames)
|
||||
{
|
||||
this.componentNames = componentNames;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91438c4a9d7e43d4bb93f70d97aab1af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true)]
|
||||
public class ContextAttribute : Attribute
|
||||
{
|
||||
public readonly string contextName;
|
||||
|
||||
public ContextAttribute(string contextName)
|
||||
{
|
||||
this.contextName = contextName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d71ffb2dcbd5f74db6ed1c155550869
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class)]
|
||||
public class CustomEntityIndexAttribute : Attribute
|
||||
{
|
||||
public readonly Type contextType;
|
||||
|
||||
public CustomEntityIndexAttribute(Type contextType)
|
||||
{
|
||||
this.contextType = contextType;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a6ace52d57684a4ba332408572c445f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
|
||||
public class DontGenerateAttribute : Attribute
|
||||
{
|
||||
public readonly bool generateIndex;
|
||||
|
||||
public DontGenerateAttribute(bool generateIndex = true)
|
||||
{
|
||||
this.generateIndex = generateIndex;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a5c7a560fbe67641942f827dd8c3ee3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultTargetFramework)</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58d2df893a4de1b42aba52402241032e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7070af680c0e054587249160ec2ed4f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
public abstract class AbstractEntityIndexAttribute : Attribute
|
||||
{
|
||||
public readonly EntityIndexType entityIndexType;
|
||||
|
||||
protected AbstractEntityIndexAttribute(EntityIndexType entityIndexType)
|
||||
{
|
||||
this.entityIndexType = entityIndexType;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 328654a052ab586468aca6796b64660f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class)]
|
||||
public class EntityIndexAttribute : AbstractEntityIndexAttribute
|
||||
{
|
||||
public EntityIndexAttribute() : base(EntityIndexType.EntityIndex) { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94e47cb2ce2aa81409d8bbdd8f5f2f1e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class EntityIndexGetMethodAttribute : Attribute { }
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 126d23e5686b9f94d8adba76e51b4825
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
public enum EntityIndexType
|
||||
{
|
||||
EntityIndex,
|
||||
PrimaryEntityIndex
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1a4ae2d181ed328408e34f5519dd54c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class)]
|
||||
public class PrimaryEntityIndexAttribute : AbstractEntityIndexAttribute
|
||||
{
|
||||
public PrimaryEntityIndexAttribute() : base(EntityIndexType.PrimaryEntityIndex) { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f9d37872e44a5f4429058c7ee98bc617
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true)]
|
||||
public class EventAttribute : Attribute
|
||||
{
|
||||
public readonly EventTarget eventTarget;
|
||||
public readonly EventType eventType;
|
||||
public readonly int priority;
|
||||
|
||||
public EventAttribute(EventTarget eventTarget, EventType eventType = EventType.Added, int priority = 0)
|
||||
{
|
||||
this.eventTarget = eventTarget;
|
||||
this.eventType = eventType;
|
||||
this.priority = priority;
|
||||
}
|
||||
}
|
||||
|
||||
public enum EventTarget
|
||||
{
|
||||
Any,
|
||||
Self
|
||||
}
|
||||
|
||||
public enum EventType
|
||||
{
|
||||
Added,
|
||||
Removed
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18e9505d0ba252c428346e532badefbd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
|
||||
public class FlagPrefixAttribute : Attribute
|
||||
{
|
||||
public readonly string prefix;
|
||||
|
||||
public FlagPrefixAttribute(string prefix)
|
||||
{
|
||||
this.prefix = prefix;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 65a79b4eb4b023749b382aa64d65ec59
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class PostConstructorAttribute : Attribute { }
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5375902151f26647a3d3db944058d7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.CodeGeneration.Attributes
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
|
||||
public class UniqueAttribute : Attribute { }
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7d8e600a008fe094fb6d65d56cf5b331
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3f4eb29e226c684e8ff681fb81f8fe7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6d375afdf3bbc9044a480918c9383b92
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.Unity
|
||||
{
|
||||
public class EntityLink : MonoBehaviour
|
||||
{
|
||||
public IEntity entity => _entity;
|
||||
|
||||
IEntity _entity;
|
||||
bool _applicationIsQuitting;
|
||||
|
||||
public void Link(IEntity entity)
|
||||
{
|
||||
if (_entity != null)
|
||||
throw new Exception($"EntityLink is already linked to {_entity}!");
|
||||
|
||||
_entity = entity;
|
||||
_entity.Retain(this);
|
||||
}
|
||||
|
||||
public void Unlink()
|
||||
{
|
||||
if (_entity == null)
|
||||
throw new Exception("EntityLink is already unlinked!");
|
||||
|
||||
_entity.Release(this);
|
||||
_entity = null;
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (!_applicationIsQuitting && _entity != null)
|
||||
Debug.LogWarning($"EntityLink got destroyed but is still linked to {_entity}!\nPlease call gameObject.Unlink() before it is destroyed.");
|
||||
}
|
||||
|
||||
void OnApplicationQuit() => _applicationIsQuitting = true;
|
||||
|
||||
public override string ToString() => $"EntityLink({gameObject.name})";
|
||||
}
|
||||
|
||||
public static class EntityLinkExtension
|
||||
{
|
||||
public static EntityLink GetEntityLink(this GameObject gameObject) => gameObject.GetComponent<EntityLink>();
|
||||
|
||||
public static EntityLink Link(this GameObject gameObject, IEntity entity)
|
||||
{
|
||||
var link = gameObject.GetEntityLink();
|
||||
if (link == null)
|
||||
link = gameObject.AddComponent<EntityLink>();
|
||||
|
||||
link.Link(entity);
|
||||
return link;
|
||||
}
|
||||
|
||||
public static void Unlink(this GameObject gameObject) =>
|
||||
gameObject.GetEntityLink().Unlink();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1059f230d9860f34ebfaf4818117d9bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10a91f1ea10230740b8e7a33f16e0c43
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18e04d324d7065944b7459a0f87cb397
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70754482b572b6f45a45b88319aea14a
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
public class ContextObserver
|
||||
{
|
||||
public IContext context => _context;
|
||||
public IGroup[] groups => _groups.ToArray();
|
||||
public GameObject gameObject => _gameObject;
|
||||
|
||||
readonly IContext _context;
|
||||
readonly List<IGroup> _groups;
|
||||
readonly GameObject _gameObject;
|
||||
readonly Stack<EntityBehaviour> _entityBehaviourPool = new Stack<EntityBehaviour>();
|
||||
readonly StringBuilder _toStringBuilder = new StringBuilder();
|
||||
|
||||
public ContextObserver(IContext context)
|
||||
{
|
||||
_context = context;
|
||||
_groups = new List<IGroup>();
|
||||
_gameObject = new GameObject();
|
||||
_gameObject.AddComponent<ContextObserverBehaviour>().Init(this);
|
||||
|
||||
_context.OnEntityCreated += onEntityCreated;
|
||||
_context.OnGroupCreated += onGroupCreated;
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
_context.OnEntityCreated -= onEntityCreated;
|
||||
_context.OnGroupCreated -= onGroupCreated;
|
||||
}
|
||||
|
||||
void onEntityCreated(IContext context, IEntity entity)
|
||||
{
|
||||
var entityBehaviour = _entityBehaviourPool.Count > 0
|
||||
? _entityBehaviourPool.Pop()
|
||||
: new GameObject().AddComponent<EntityBehaviour>();
|
||||
|
||||
entityBehaviour.Init(context, entity, _entityBehaviourPool);
|
||||
entityBehaviour.transform.SetParent(_gameObject.transform, false);
|
||||
entityBehaviour.transform.SetAsLastSibling();
|
||||
}
|
||||
|
||||
void onGroupCreated(IContext context, IGroup group) => _groups.Add(group);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
_toStringBuilder.Length = 0;
|
||||
_toStringBuilder
|
||||
.Append(_context.contextInfo.name).Append(" (")
|
||||
.Append(_context.count).Append(" entities, ")
|
||||
.Append(_context.reusableEntitiesCount).Append(" reusable, ");
|
||||
|
||||
if (_context.retainedEntitiesCount != 0)
|
||||
{
|
||||
_toStringBuilder
|
||||
.Append(_context.retainedEntitiesCount).Append(" retained, ");
|
||||
}
|
||||
|
||||
_toStringBuilder
|
||||
.Append(_groups.Count)
|
||||
.Append(" groups)");
|
||||
|
||||
var str = _toStringBuilder.ToString();
|
||||
_gameObject.name = str;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44106a1d7aa42a645b422dd242c67232
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,28 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class ContextObserverBehaviour : MonoBehaviour
|
||||
{
|
||||
public ContextObserver contextObserver => _contextObserver;
|
||||
|
||||
ContextObserver _contextObserver;
|
||||
|
||||
public void Init(ContextObserver contextObserver)
|
||||
{
|
||||
_contextObserver = contextObserver;
|
||||
Update();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (_contextObserver == null)
|
||||
gameObject.DestroyGameObject();
|
||||
else if (_contextObserver.gameObject != null)
|
||||
_contextObserver.gameObject.name = _contextObserver.ToString();
|
||||
}
|
||||
|
||||
void OnDestroy() => _contextObserver.Deactivate();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 351d49c00c4f09940929062a5cfb321b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,20 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
public static class ContextObserverExtension
|
||||
{
|
||||
public static ContextObserverBehaviour FindContextObserver(this IContext context)
|
||||
{
|
||||
var observers = Object.FindObjectsOfType<ContextObserverBehaviour>();
|
||||
for (var i = 0; i < observers.Length; i++)
|
||||
{
|
||||
var observer = observers[i];
|
||||
if (observer.contextObserver.context == context)
|
||||
return observer;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ebb82ef8ef760a143803e1ea2eb001c8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 033043b62f1e4df46a8e4c816b695a8e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,267 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
public enum AvgResetInterval
|
||||
{
|
||||
Always = 1,
|
||||
VeryFast = 30,
|
||||
Fast = 60,
|
||||
Normal = 120,
|
||||
Slow = 300,
|
||||
Never = int.MaxValue
|
||||
}
|
||||
|
||||
public class DebugSystems : Systems
|
||||
{
|
||||
public static AvgResetInterval avgResetInterval = AvgResetInterval.Never;
|
||||
|
||||
public int totalInitializeSystemsCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var system in _initializeSystems)
|
||||
total += system is DebugSystems debugSystems ? debugSystems.totalInitializeSystemsCount : 1;
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public int totalExecuteSystemsCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var system in _executeSystems)
|
||||
total += system is DebugSystems debugSystems ? debugSystems.totalExecuteSystemsCount : 1;
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public int totalCleanupSystemsCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var system in _cleanupSystems)
|
||||
total += system is DebugSystems debugSystems ? debugSystems.totalCleanupSystemsCount : 1;
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public int totalTearDownSystemsCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var system in _tearDownSystems)
|
||||
total += system is DebugSystems debugSystems ? debugSystems.totalTearDownSystemsCount : 1;
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public int totalSystemsCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var system in _systems)
|
||||
total += system is DebugSystems debugSystems ? debugSystems.totalSystemsCount : 1;
|
||||
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public int initializeSystemsCount => _initializeSystems.Count;
|
||||
public int executeSystemsCount => _executeSystems.Count;
|
||||
public int cleanupSystemsCount => _cleanupSystems.Count;
|
||||
public int tearDownSystemsCount => _tearDownSystems.Count;
|
||||
|
||||
public string name => _name;
|
||||
public GameObject gameObject => _gameObject;
|
||||
public SystemInfo systemInfo => _systemInfo;
|
||||
public double executeDuration => _executeDuration;
|
||||
public double cleanupDuration => _cleanupDuration;
|
||||
|
||||
public SystemInfo[] initializeSystemInfos => _initializeSystemInfos.ToArray();
|
||||
public SystemInfo[] executeSystemInfos => _executeSystemInfos.ToArray();
|
||||
public SystemInfo[] syncSystemInfos => _syncSystemInfos.ToArray();
|
||||
public SystemInfo[] cleanupSystemInfos => _cleanupSystemInfos.ToArray();
|
||||
public SystemInfo[] tearDownSystemInfos => _tearDownSystemInfos.ToArray();
|
||||
|
||||
public bool paused;
|
||||
|
||||
string _name;
|
||||
|
||||
List<ISystem> _systems;
|
||||
GameObject _gameObject;
|
||||
SystemInfo _systemInfo;
|
||||
|
||||
List<SystemInfo> _initializeSystemInfos;
|
||||
List<SystemInfo> _executeSystemInfos;
|
||||
List<SystemInfo> _syncSystemInfos;
|
||||
List<SystemInfo> _cleanupSystemInfos;
|
||||
List<SystemInfo> _tearDownSystemInfos;
|
||||
|
||||
Stopwatch _stopwatch;
|
||||
|
||||
public Stopwatch StopWatch;
|
||||
|
||||
double _executeDuration;
|
||||
double _cleanupDuration;
|
||||
public double SyncDuration;
|
||||
|
||||
public DebugSystems(string name)
|
||||
{
|
||||
initialize(name);
|
||||
}
|
||||
|
||||
protected DebugSystems(bool noInit) { }
|
||||
|
||||
protected void initialize(string name)
|
||||
{
|
||||
_name = name;
|
||||
_gameObject = new GameObject(name);
|
||||
_gameObject.AddComponent<DebugSystemsBehaviour>().Init(this);
|
||||
|
||||
_systemInfo = new SystemInfo(this);
|
||||
|
||||
_systems = new List<ISystem>();
|
||||
_initializeSystemInfos = new List<SystemInfo>();
|
||||
_executeSystemInfos = new List<SystemInfo>();
|
||||
_syncSystemInfos = new List<SystemInfo>();
|
||||
_cleanupSystemInfos = new List<SystemInfo>();
|
||||
_tearDownSystemInfos = new List<SystemInfo>();
|
||||
|
||||
_stopwatch = new Stopwatch();
|
||||
}
|
||||
|
||||
public override Systems Add(ISystem system)
|
||||
{
|
||||
_systems.Add(system);
|
||||
|
||||
SystemInfo childSystemInfo;
|
||||
|
||||
if (system is DebugSystems debugSystems)
|
||||
{
|
||||
childSystemInfo = debugSystems.systemInfo;
|
||||
debugSystems.gameObject.transform.SetParent(_gameObject.transform, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
childSystemInfo = new SystemInfo(system);
|
||||
}
|
||||
|
||||
childSystemInfo.parentSystemInfo = _systemInfo;
|
||||
|
||||
if (childSystemInfo.isInitializeSystems) _initializeSystemInfos.Add(childSystemInfo);
|
||||
if (childSystemInfo.isExecuteSystems || childSystemInfo.isReactiveSystems) _executeSystemInfos.Add(childSystemInfo);
|
||||
if (childSystemInfo.isSyncSystems) _syncSystemInfos.Add(childSystemInfo);
|
||||
if (childSystemInfo.isCleanupSystems) _cleanupSystemInfos.Add(childSystemInfo);
|
||||
if (childSystemInfo.isTearDownSystems) _tearDownSystemInfos.Add(childSystemInfo);
|
||||
|
||||
return base.Add(system);
|
||||
}
|
||||
|
||||
public void ResetDurations()
|
||||
{
|
||||
foreach (var systemInfo in _executeSystemInfos)
|
||||
systemInfo.ResetDurations();
|
||||
|
||||
foreach (var system in _systems)
|
||||
if (system is DebugSystems debugSystems)
|
||||
debugSystems.ResetDurations();
|
||||
}
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
for (var i = 0; i < _initializeSystems.Count; i++)
|
||||
{
|
||||
var systemInfo = _initializeSystemInfos[i];
|
||||
if (systemInfo.isActive)
|
||||
{
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
_initializeSystems[i].Initialize();
|
||||
_stopwatch.Stop();
|
||||
systemInfo.initializationDuration = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Execute()
|
||||
{
|
||||
if (!paused)
|
||||
StepExecute();
|
||||
}
|
||||
|
||||
public override void Cleanup()
|
||||
{
|
||||
if (!paused)
|
||||
StepCleanup();
|
||||
}
|
||||
|
||||
public void StepExecute()
|
||||
{
|
||||
_executeDuration = 0;
|
||||
if (Time.frameCount % (int)avgResetInterval == 0)
|
||||
ResetDurations();
|
||||
|
||||
for (var i = 0; i < _executeSystems.Count; i++)
|
||||
{
|
||||
var systemInfo = _executeSystemInfos[i];
|
||||
if (systemInfo.isActive)
|
||||
{
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
_executeSystems[i].Execute();
|
||||
_stopwatch.Stop();
|
||||
var duration = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
_executeDuration += duration;
|
||||
systemInfo.AddExecutionDuration(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void StepCleanup()
|
||||
{
|
||||
_cleanupDuration = 0;
|
||||
for (var i = 0; i < _cleanupSystems.Count; i++)
|
||||
{
|
||||
var systemInfo = _cleanupSystemInfos[i];
|
||||
if (systemInfo.isActive)
|
||||
{
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
_cleanupSystems[i].Cleanup();
|
||||
_stopwatch.Stop();
|
||||
var duration = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
_cleanupDuration += duration;
|
||||
systemInfo.AddCleanupDuration(duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void TearDown()
|
||||
{
|
||||
for (var i = 0; i < _tearDownSystems.Count; i++)
|
||||
{
|
||||
var systemInfo = _tearDownSystemInfos[i];
|
||||
if (systemInfo.isActive)
|
||||
{
|
||||
_stopwatch.Reset();
|
||||
_stopwatch.Start();
|
||||
_tearDownSystems[i].TearDown();
|
||||
_stopwatch.Stop();
|
||||
systemInfo.teardownDuration = _stopwatch.Elapsed.TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fc39bdd40a9bf7409103938352fbd72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,16 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
public class DebugSystemsBehaviour : MonoBehaviour
|
||||
{
|
||||
public DebugSystems systems => _systems;
|
||||
|
||||
DebugSystems _systems;
|
||||
|
||||
public void Init(DebugSystems systems)
|
||||
{
|
||||
_systems = systems;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdcef5607d436f846829c5ad34cf3008
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using JNGame.Sync;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
[Flags]
|
||||
public enum SystemInterfaceFlags
|
||||
{
|
||||
None = 0,
|
||||
IInitializeSystem = 1 << 1,
|
||||
IExecuteSystem = 1 << 2,
|
||||
ICleanupSystem = 1 << 3,
|
||||
ITearDownSystem = 1 << 4,
|
||||
IReactiveSystem = 1 << 5,
|
||||
ISyncSystem = 1 << 6
|
||||
}
|
||||
|
||||
public class SystemInfo
|
||||
{
|
||||
public ISystem system => _system;
|
||||
public string systemName => _systemName;
|
||||
|
||||
public bool isInitializeSystems => (_interfaceFlags & SystemInterfaceFlags.IInitializeSystem) == SystemInterfaceFlags.IInitializeSystem;
|
||||
public bool isExecuteSystems => (_interfaceFlags & SystemInterfaceFlags.IExecuteSystem) == SystemInterfaceFlags.IExecuteSystem;
|
||||
public bool isCleanupSystems => (_interfaceFlags & SystemInterfaceFlags.ICleanupSystem) == SystemInterfaceFlags.ICleanupSystem;
|
||||
public bool isTearDownSystems => (_interfaceFlags & SystemInterfaceFlags.ITearDownSystem) == SystemInterfaceFlags.ITearDownSystem;
|
||||
public bool isReactiveSystems => (_interfaceFlags & SystemInterfaceFlags.IReactiveSystem) == SystemInterfaceFlags.IReactiveSystem;
|
||||
public bool isSyncSystems => (_interfaceFlags & SystemInterfaceFlags.ISyncSystem) == SystemInterfaceFlags.ISyncSystem;
|
||||
|
||||
public double initializationDuration { get; set; }
|
||||
public double accumulatedExecutionDuration => _accumulatedExecutionDuration;
|
||||
public double minExecutionDuration => _minExecutionDuration;
|
||||
public double maxExecutionDuration => _maxExecutionDuration;
|
||||
public double averageExecutionDuration => _executionDurationsCount == 0 ? 0 : _accumulatedExecutionDuration / _executionDurationsCount;
|
||||
public double minSyncDuration => _minSyncDuration;
|
||||
public double maxSyncDuration => _maxSyncDuration;
|
||||
public double averageSyncDuration => _syncDurationsCount == 0 ? 0 : _accumulatedSyncDuration / _syncDurationsCount;
|
||||
public double accumulatedCleanupDuration => _accumulatedCleanupDuration;
|
||||
public double minCleanupDuration => _minCleanupDuration;
|
||||
public double maxCleanupDuration => _maxCleanupDuration;
|
||||
public double averageCleanupDuration => _cleanupDurationsCount == 0 ? 0 : _accumulatedCleanupDuration / _cleanupDurationsCount;
|
||||
public double cleanupDuration { get; set; }
|
||||
public double teardownDuration { get; set; }
|
||||
|
||||
public bool areAllParentsActive => parentSystemInfo == null || (parentSystemInfo.isActive && parentSystemInfo.areAllParentsActive);
|
||||
|
||||
public SystemInfo parentSystemInfo;
|
||||
public bool isActive;
|
||||
|
||||
readonly ISystem _system;
|
||||
readonly SystemInterfaceFlags _interfaceFlags;
|
||||
readonly string _systemName;
|
||||
|
||||
double _accumulatedExecutionDuration;
|
||||
double _minExecutionDuration;
|
||||
double _maxExecutionDuration;
|
||||
int _executionDurationsCount;
|
||||
|
||||
double _accumulatedSyncDuration;
|
||||
double _minSyncDuration;
|
||||
double _maxSyncDuration;
|
||||
int _syncDurationsCount;
|
||||
|
||||
double _accumulatedCleanupDuration;
|
||||
double _minCleanupDuration;
|
||||
double _maxCleanupDuration;
|
||||
int _cleanupDurationsCount;
|
||||
|
||||
public SystemInfo(ISystem system)
|
||||
{
|
||||
_system = system;
|
||||
_interfaceFlags = getInterfaceFlags(system);
|
||||
|
||||
var debugSystem = system as DebugSystems;
|
||||
_systemName = debugSystem != null
|
||||
? debugSystem.name
|
||||
: system.GetType().Name.RemoveSystemSuffix();
|
||||
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public void AddExecutionDuration(double executionDuration)
|
||||
{
|
||||
if (executionDuration < _minExecutionDuration || _minExecutionDuration == 0)
|
||||
_minExecutionDuration = executionDuration;
|
||||
|
||||
if (executionDuration > _maxExecutionDuration)
|
||||
_maxExecutionDuration = executionDuration;
|
||||
|
||||
_accumulatedExecutionDuration += executionDuration;
|
||||
_executionDurationsCount += 1;
|
||||
}
|
||||
|
||||
public void AddSyncUpdateDuration(double executionDuration)
|
||||
{
|
||||
if (executionDuration < _minSyncDuration || _minSyncDuration == 0)
|
||||
_minSyncDuration = executionDuration;
|
||||
|
||||
if (executionDuration > _maxSyncDuration)
|
||||
_maxSyncDuration = executionDuration;
|
||||
|
||||
_accumulatedSyncDuration += executionDuration;
|
||||
_syncDurationsCount += 1;
|
||||
}
|
||||
|
||||
public void AddCleanupDuration(double cleanupDuration)
|
||||
{
|
||||
if (cleanupDuration < _minCleanupDuration || _minCleanupDuration == 0)
|
||||
_minCleanupDuration = cleanupDuration;
|
||||
|
||||
if (cleanupDuration > _maxCleanupDuration)
|
||||
_maxCleanupDuration = cleanupDuration;
|
||||
|
||||
_accumulatedCleanupDuration += cleanupDuration;
|
||||
_cleanupDurationsCount += 1;
|
||||
}
|
||||
|
||||
public void ResetDurations()
|
||||
{
|
||||
_accumulatedExecutionDuration = 0;
|
||||
_executionDurationsCount = 0;
|
||||
_accumulatedSyncDuration = 0;
|
||||
_syncDurationsCount = 0;
|
||||
|
||||
_accumulatedCleanupDuration = 0;
|
||||
_cleanupDurationsCount = 0;
|
||||
}
|
||||
|
||||
static SystemInterfaceFlags getInterfaceFlags(ISystem system)
|
||||
{
|
||||
var flags = SystemInterfaceFlags.None;
|
||||
if (system is IInitializeSystem)
|
||||
flags |= SystemInterfaceFlags.IInitializeSystem;
|
||||
|
||||
if (system is IReactiveSystem)
|
||||
flags |= SystemInterfaceFlags.IReactiveSystem;
|
||||
else if (system is IExecuteSystem)
|
||||
flags |= SystemInterfaceFlags.IExecuteSystem;
|
||||
|
||||
if (system is ICleanupSystem)
|
||||
flags |= SystemInterfaceFlags.ICleanupSystem;
|
||||
|
||||
if (system is ITearDownSystem)
|
||||
flags |= SystemInterfaceFlags.ITearDownSystem;
|
||||
|
||||
if (system is IJNSyncCycle)
|
||||
flags |= SystemInterfaceFlags.ISyncSystem;
|
||||
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0ed9e80cae92004cad7049532bf2dc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41d616c184d2d4d4cb79de55b477a344
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class DontDrawComponentAttribute : Attribute { }
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3a0252024c73f0540b032d96f952ebd6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
[ExecuteInEditMode]
|
||||
public class EntityBehaviour : MonoBehaviour
|
||||
{
|
||||
public IContext context => _context;
|
||||
public IEntity entity => _entity;
|
||||
|
||||
IContext _context;
|
||||
IEntity _entity;
|
||||
Stack<EntityBehaviour> _entityBehaviourPool;
|
||||
string _cachedName;
|
||||
|
||||
public void Init(IContext context, IEntity entity, Stack<EntityBehaviour> entityBehaviourPool)
|
||||
{
|
||||
_context = context;
|
||||
_entity = entity;
|
||||
_entityBehaviourPool = entityBehaviourPool;
|
||||
_entity.OnEntityReleased += onEntityReleased;
|
||||
gameObject.hideFlags = HideFlags.None;
|
||||
gameObject.SetActive(true);
|
||||
Update();
|
||||
}
|
||||
|
||||
void onEntityReleased(IEntity e)
|
||||
{
|
||||
_entity.OnEntityReleased -= onEntityReleased;
|
||||
gameObject.SetActive(false);
|
||||
gameObject.hideFlags = HideFlags.HideInHierarchy;
|
||||
_entityBehaviourPool.Push(this);
|
||||
_cachedName = null;
|
||||
name = string.Empty;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (_entity != null && _cachedName != _entity.ToString())
|
||||
name = _cachedName = _entity.ToString();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (_entity != null)
|
||||
_entity.OnEntityReleased -= onEntityReleased;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fa8320db813e7840b41db45b2583e0c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,15 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Entitas.VisualDebugging.Unity
|
||||
{
|
||||
public static class GameObjectDestroyExtension
|
||||
{
|
||||
public static void DestroyGameObject(this GameObject gameObject)
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
Object.Destroy(gameObject);
|
||||
else
|
||||
Object.DestroyImmediate(gameObject);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 544d80be634caa5438caefb85c51ab0a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d25deb048adb29a43803d9d3ffb6bd83
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4829299aa8c2b114c9acb7d540c14e67
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9de4a3c18c9d0c04386236d039466de7
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,139 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
|
||||
namespace Entitas
|
||||
{
|
||||
/// A Collector can observe one or more groups from the same context
|
||||
/// and collects changed entities based on the specified groupEvent.
|
||||
public class Collector<TEntity> : ICollector<TEntity> where TEntity : class, IEntity
|
||||
{
|
||||
/// Returns all collected entities.
|
||||
/// Call collector.ClearCollectedEntities()
|
||||
/// once you processed all entities.
|
||||
public HashSet<TEntity> collectedEntities => _collectedEntities;
|
||||
|
||||
/// Returns the number of all collected entities.
|
||||
public int count => _collectedEntities.Count;
|
||||
|
||||
readonly HashSet<TEntity> _collectedEntities;
|
||||
readonly IGroup<TEntity>[] _groups;
|
||||
readonly GroupEvent[] _groupEvents;
|
||||
readonly GroupChanged<TEntity> _addEntityCache;
|
||||
|
||||
string _toStringCache;
|
||||
StringBuilder _toStringBuilder;
|
||||
|
||||
/// Creates a Collector and will collect changed entities
|
||||
/// based on the specified groupEvent.
|
||||
public Collector(IGroup<TEntity> group, GroupEvent groupEvent) : this(new[] {group}, new[] {groupEvent}) { }
|
||||
|
||||
/// Creates a Collector and will collect changed entities
|
||||
/// based on the specified groupEvents.
|
||||
public Collector(IGroup<TEntity>[] groups, GroupEvent[] groupEvents)
|
||||
{
|
||||
_groups = groups;
|
||||
_collectedEntities = new HashSet<TEntity>(EntityEqualityComparer<TEntity>.comparer);
|
||||
_groupEvents = groupEvents;
|
||||
|
||||
if (groups.Length != groupEvents.Length)
|
||||
throw new CollectorException(
|
||||
$"Unbalanced count with groups ({groups.Length}) and group events ({groupEvents.Length}).",
|
||||
"Group and group events count must be equal."
|
||||
);
|
||||
|
||||
_addEntityCache = addEntity;
|
||||
Activate();
|
||||
}
|
||||
|
||||
/// Activates the Collector and will start collecting
|
||||
/// changed entities. Collectors are activated by default.
|
||||
public void Activate()
|
||||
{
|
||||
for (var i = 0; i < _groups.Length; i++)
|
||||
{
|
||||
var group = _groups[i];
|
||||
var groupEvent = _groupEvents[i];
|
||||
switch (groupEvent)
|
||||
{
|
||||
case GroupEvent.Added:
|
||||
group.OnEntityAdded -= _addEntityCache;
|
||||
group.OnEntityAdded += _addEntityCache;
|
||||
break;
|
||||
case GroupEvent.Removed:
|
||||
group.OnEntityRemoved -= _addEntityCache;
|
||||
group.OnEntityRemoved += _addEntityCache;
|
||||
break;
|
||||
case GroupEvent.AddedOrRemoved:
|
||||
group.OnEntityAdded -= _addEntityCache;
|
||||
group.OnEntityAdded += _addEntityCache;
|
||||
group.OnEntityRemoved -= _addEntityCache;
|
||||
group.OnEntityRemoved += _addEntityCache;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Deactivates the Collector.
|
||||
/// This will also clear all collected entities.
|
||||
/// Collectors are activated by default.
|
||||
public void Deactivate()
|
||||
{
|
||||
for (var i = 0; i < _groups.Length; i++)
|
||||
{
|
||||
var group = _groups[i];
|
||||
group.OnEntityAdded -= _addEntityCache;
|
||||
group.OnEntityRemoved -= _addEntityCache;
|
||||
}
|
||||
|
||||
ClearCollectedEntities();
|
||||
}
|
||||
|
||||
/// Returns all collected entities and casts them.
|
||||
/// Call collector.ClearCollectedEntities()
|
||||
/// once you processed all entities.
|
||||
public IEnumerable<TCast> GetCollectedEntities<TCast>() where TCast : class, IEntity =>
|
||||
_collectedEntities.Cast<TCast>();
|
||||
|
||||
/// Clears all collected entities.
|
||||
public void ClearCollectedEntities()
|
||||
{
|
||||
foreach (var entity in _collectedEntities)
|
||||
entity.Release(this);
|
||||
|
||||
_collectedEntities.Clear();
|
||||
}
|
||||
|
||||
void addEntity(IGroup<TEntity> group, TEntity entity, int index, IComponent component)
|
||||
{
|
||||
if (_collectedEntities.Add(entity))
|
||||
entity.Retain(this);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (_toStringCache == null)
|
||||
{
|
||||
_toStringBuilder ??= new StringBuilder();
|
||||
_toStringBuilder.Length = 0;
|
||||
_toStringBuilder.Append("Collector(");
|
||||
|
||||
const string separator = ", ";
|
||||
var lastSeparator = _groups.Length - 1;
|
||||
for (var i = 0; i < _groups.Length; i++)
|
||||
{
|
||||
_toStringBuilder.Append(_groups[i]);
|
||||
if (i < lastSeparator)
|
||||
_toStringBuilder.Append(separator);
|
||||
}
|
||||
|
||||
_toStringBuilder.Append(")");
|
||||
_toStringCache = _toStringBuilder.ToString();
|
||||
}
|
||||
|
||||
return _toStringCache;
|
||||
}
|
||||
|
||||
~Collector() => Deactivate();
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b816096257df0df4089ab84720f946fc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,28 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public static class CollectorContextExtension
|
||||
{
|
||||
/// Creates a Collector.
|
||||
public static ICollector<TEntity> CreateCollector<TEntity>(
|
||||
this IContext<TEntity> context, IMatcher<TEntity> matcher) where TEntity : class, IEntity
|
||||
{
|
||||
return context.CreateCollector(new TriggerOnEvent<TEntity>(matcher, GroupEvent.Added));
|
||||
}
|
||||
|
||||
/// Creates a Collector.
|
||||
public static ICollector<TEntity> CreateCollector<TEntity>(
|
||||
this IContext<TEntity> context, params TriggerOnEvent<TEntity>[] triggers) where TEntity : class, IEntity
|
||||
{
|
||||
var groups = new IGroup<TEntity>[triggers.Length];
|
||||
var groupEvents = new GroupEvent[triggers.Length];
|
||||
|
||||
for (var i = 0; i < triggers.Length; i++)
|
||||
{
|
||||
groups[i] = context.GetGroup(triggers[i].matcher);
|
||||
groupEvents[i] = triggers[i].groupEvent;
|
||||
}
|
||||
|
||||
return new Collector<TEntity>(groups, groupEvents);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b166aed377d9784db7eccac283f5cad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public class CollectorException : EntitasException
|
||||
{
|
||||
public CollectorException(string message, string hint) : base(message, hint) { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b3c27b1f66e4d04d8acf1b532d0b0ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Entitas
|
||||
{
|
||||
public interface ICollector
|
||||
{
|
||||
int count { get; }
|
||||
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
void ClearCollectedEntities();
|
||||
|
||||
IEnumerable<TCast> GetCollectedEntities<TCast>() where TCast : class, IEntity;
|
||||
}
|
||||
|
||||
public interface ICollector<TEntity> : ICollector where TEntity : class, IEntity
|
||||
{
|
||||
HashSet<TEntity> collectedEntities { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc98d18773bed85459db48a7794d079e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public struct TriggerOnEvent<TEntity> where TEntity : class, IEntity
|
||||
{
|
||||
public readonly IMatcher<TEntity> matcher;
|
||||
public readonly GroupEvent groupEvent;
|
||||
|
||||
public TriggerOnEvent(IMatcher<TEntity> matcher, GroupEvent groupEvent)
|
||||
{
|
||||
this.matcher = matcher;
|
||||
this.groupEvent = groupEvent;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34f197674a960c145a3f033d0dff3929
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,14 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public static class TriggerOnEventMatcherExtension
|
||||
{
|
||||
public static TriggerOnEvent<TEntity> Added<TEntity>(this IMatcher<TEntity> matcher) where TEntity : class, IEntity =>
|
||||
new TriggerOnEvent<TEntity>(matcher, GroupEvent.Added);
|
||||
|
||||
public static TriggerOnEvent<TEntity> Removed<TEntity>(this IMatcher<TEntity> matcher) where TEntity : class, IEntity =>
|
||||
new TriggerOnEvent<TEntity>(matcher, GroupEvent.Removed);
|
||||
|
||||
public static TriggerOnEvent<TEntity> AddedOrRemoved<TEntity>(this IMatcher<TEntity> matcher) where TEntity : class, IEntity =>
|
||||
new TriggerOnEvent<TEntity>(matcher, GroupEvent.AddedOrRemoved);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0c502dc5acd68e943995c026ad879aad
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 412bbea7213406a42ab7c6bed1b3b76c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,344 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DesperateDevs.Caching;
|
||||
|
||||
namespace Entitas
|
||||
{
|
||||
/// A context manages the lifecycle of entities and groups.
|
||||
/// You can create and destroy entities and get groups of entities.
|
||||
/// The preferred way to create a context is to use the generated methods
|
||||
/// from the code generator, e.g. var context = new GameContext();
|
||||
public class Context<TEntity> : IContext<TEntity> where TEntity : class, IEntity
|
||||
{
|
||||
/// Occurs when an entity gets created.
|
||||
public event ContextEntityChanged OnEntityCreated;
|
||||
|
||||
/// Occurs when an entity will be destroyed.
|
||||
public event ContextEntityChanged OnEntityWillBeDestroyed;
|
||||
|
||||
/// Occurs when an entity got destroyed.
|
||||
public event ContextEntityChanged OnEntityDestroyed;
|
||||
|
||||
/// Occurs when a group gets created for the first time.
|
||||
public event ContextGroupChanged OnGroupCreated;
|
||||
|
||||
/// The total amount of components an entity can possibly have.
|
||||
/// This value is generated by the code generator,
|
||||
/// e.g ComponentLookup.TotalComponents.
|
||||
public int totalComponents => _totalComponents;
|
||||
|
||||
/// Returns all componentPools. componentPools is used to reuse
|
||||
/// removed components.
|
||||
/// Removed components will be pushed to the componentPool.
|
||||
/// Use entity.CreateComponent(index, type) to get a new or reusable
|
||||
/// component from the componentPool.
|
||||
public Stack<IComponent>[] componentPools => _componentPools;
|
||||
|
||||
/// The contextInfo contains information about the context.
|
||||
/// It's used to provide better error messages.
|
||||
public ContextInfo contextInfo => _contextInfo;
|
||||
|
||||
/// Returns the number of entities in the context.
|
||||
public int count => _entities.Count;
|
||||
|
||||
/// Returns the number of entities in the internal ObjectPool
|
||||
/// for entities which can be reused.
|
||||
public int reusableEntitiesCount => _reusableEntities.Count;
|
||||
|
||||
/// Returns the number of entities that are currently retained by
|
||||
/// other objects (e.g. Group, Collector, ReactiveSystem).
|
||||
public int retainedEntitiesCount => _retainedEntities.Count;
|
||||
|
||||
readonly int _totalComponents;
|
||||
|
||||
readonly Stack<IComponent>[] _componentPools;
|
||||
readonly ContextInfo _contextInfo;
|
||||
readonly Func<IEntity, IAERC> _aercFactory;
|
||||
readonly Func<TEntity> _entityFactory;
|
||||
|
||||
readonly HashSet<TEntity> _entities = new HashSet<TEntity>(EntityEqualityComparer<TEntity>.comparer);
|
||||
readonly Stack<TEntity> _reusableEntities = new Stack<TEntity>();
|
||||
readonly HashSet<TEntity> _retainedEntities = new HashSet<TEntity>(EntityEqualityComparer<TEntity>.comparer);
|
||||
|
||||
readonly Dictionary<IMatcher<TEntity>, IGroup<TEntity>> _groups = new Dictionary<IMatcher<TEntity>, IGroup<TEntity>>();
|
||||
readonly List<IGroup<TEntity>>[] _groupsForIndex;
|
||||
readonly ObjectPool<List<GroupChanged<TEntity>>> _groupChangedListPool;
|
||||
|
||||
readonly Dictionary<string, IEntityIndex> _entityIndices;
|
||||
|
||||
int _creationIndex;
|
||||
|
||||
protected TEntity[] _entitiesCache;
|
||||
|
||||
// Cache delegates to avoid gc allocations
|
||||
readonly EntityComponentChanged _cachedEntityChanged;
|
||||
readonly EntityComponentReplaced _cachedComponentReplaced;
|
||||
readonly EntityEvent _cachedEntityReleased;
|
||||
readonly EntityEvent _cachedDestroyEntity;
|
||||
|
||||
/// The preferred way to create a context is to use the generated methods
|
||||
/// from the code generator, e.g. var context = new GameContext();
|
||||
public Context(int totalComponents, Func<TEntity> entityFactory) : this(totalComponents, 0, null, null, entityFactory) { }
|
||||
|
||||
/// The preferred way to create a context is to use the generated methods
|
||||
/// from the code generator, e.g. var context = new GameContext();
|
||||
public Context(int totalComponents, int startCreationIndex, ContextInfo contextInfo, Func<IEntity, IAERC> aercFactory, Func<TEntity> entityFactory)
|
||||
{
|
||||
_totalComponents = totalComponents;
|
||||
_creationIndex = startCreationIndex;
|
||||
|
||||
if (contextInfo != null)
|
||||
{
|
||||
_contextInfo = contextInfo;
|
||||
if (contextInfo.componentNames.Length != totalComponents)
|
||||
throw new ContextInfoException(this, contextInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
_contextInfo = createDefaultContextInfo();
|
||||
}
|
||||
|
||||
_aercFactory = aercFactory ?? (entity => new SafeAERC(entity));
|
||||
_entityFactory = entityFactory;
|
||||
|
||||
_groupsForIndex = new List<IGroup<TEntity>>[totalComponents];
|
||||
_componentPools = new Stack<IComponent>[totalComponents];
|
||||
_entityIndices = new Dictionary<string, IEntityIndex>();
|
||||
_groupChangedListPool = new ObjectPool<List<GroupChanged<TEntity>>>(
|
||||
() => new List<GroupChanged<TEntity>>(),
|
||||
list => list.Clear()
|
||||
);
|
||||
|
||||
// Cache delegates to avoid gc allocations
|
||||
_cachedEntityChanged = updateGroupsComponentAddedOrRemoved;
|
||||
_cachedComponentReplaced = updateGroupsComponentReplaced;
|
||||
_cachedEntityReleased = onEntityReleased;
|
||||
_cachedDestroyEntity = onDestroyEntity;
|
||||
}
|
||||
|
||||
ContextInfo createDefaultContextInfo()
|
||||
{
|
||||
var componentNames = new string[_totalComponents];
|
||||
const string prefix = "Index ";
|
||||
for (var i = 0; i < componentNames.Length; i++)
|
||||
componentNames[i] = prefix + i;
|
||||
|
||||
return new ContextInfo("Unnamed Context", componentNames, null);
|
||||
}
|
||||
|
||||
/// Creates a new entity or gets a reusable entity from the
|
||||
/// internal ObjectPool for entities.
|
||||
public virtual TEntity CreateEntity()
|
||||
{
|
||||
TEntity entity;
|
||||
|
||||
if (_reusableEntities.Count > 0)
|
||||
{
|
||||
entity = _reusableEntities.Pop();
|
||||
entity.Reactivate(_creationIndex++);
|
||||
}
|
||||
else
|
||||
{
|
||||
entity = _entityFactory();
|
||||
entity.Initialize(_creationIndex++, _totalComponents, _componentPools, _contextInfo, _aercFactory(entity));
|
||||
}
|
||||
|
||||
_entities.Add(entity);
|
||||
entity.Retain(this);
|
||||
_entitiesCache = null;
|
||||
|
||||
entity.OnComponentAdded += _cachedEntityChanged;
|
||||
entity.OnComponentRemoved += _cachedEntityChanged;
|
||||
entity.OnComponentReplaced += _cachedComponentReplaced;
|
||||
entity.OnEntityReleased += _cachedEntityReleased;
|
||||
entity.OnDestroyEntity += _cachedDestroyEntity;
|
||||
|
||||
OnEntityCreated?.Invoke(this, entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// Destroys all entities in the context.
|
||||
/// Throws an exception if there are still retained entities.
|
||||
public void DestroyAllEntities()
|
||||
{
|
||||
var entities = GetEntities();
|
||||
for (var i = 0; i < entities.Length; i++)
|
||||
entities[i].Destroy();
|
||||
|
||||
_entities.Clear();
|
||||
|
||||
if (_retainedEntities.Count != 0)
|
||||
throw new ContextStillHasRetainedEntitiesException(this, _retainedEntities);
|
||||
}
|
||||
|
||||
/// Determines whether the context has the specified entity.
|
||||
public bool HasEntity(TEntity entity) => _entities.Contains(entity);
|
||||
|
||||
/// Returns all entities which are currently in the context.
|
||||
public virtual TEntity[] GetEntities()
|
||||
{
|
||||
if (_entitiesCache == null)
|
||||
{
|
||||
_entitiesCache = new TEntity[_entities.Count];
|
||||
_entities.CopyTo(_entitiesCache);
|
||||
}
|
||||
|
||||
return _entitiesCache;
|
||||
}
|
||||
|
||||
/// Returns a group for the specified matcher.
|
||||
/// Calling context.GetGroup(matcher) with the same matcher will always
|
||||
/// return the same instance of the group.
|
||||
public IGroup<TEntity> GetGroup(IMatcher<TEntity> matcher)
|
||||
{
|
||||
if (!_groups.TryGetValue(matcher, out var group))
|
||||
{
|
||||
group = new Group<TEntity>(matcher);
|
||||
var entities = GetEntities();
|
||||
for (var i = 0; i < entities.Length; i++)
|
||||
group.HandleEntitySilently(entities[i]);
|
||||
|
||||
_groups.Add(matcher, group);
|
||||
|
||||
for (var i = 0; i < matcher.indices.Length; i++)
|
||||
{
|
||||
var index = matcher.indices[i];
|
||||
if (_groupsForIndex[index] == null)
|
||||
_groupsForIndex[index] = new List<IGroup<TEntity>>();
|
||||
|
||||
_groupsForIndex[index].Add(group);
|
||||
}
|
||||
|
||||
OnGroupCreated?.Invoke(this, group);
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
/// Adds the IEntityIndex for the specified name.
|
||||
/// There can only be one IEntityIndex per name.
|
||||
public void AddEntityIndex(IEntityIndex entityIndex)
|
||||
{
|
||||
if (_entityIndices.ContainsKey(entityIndex.name))
|
||||
throw new ContextEntityIndexDoesAlreadyExistException(this, entityIndex.name);
|
||||
|
||||
_entityIndices.Add(entityIndex.name, entityIndex);
|
||||
}
|
||||
|
||||
/// Gets the IEntityIndex for the specified name.
|
||||
public IEntityIndex GetEntityIndex(string name)
|
||||
{
|
||||
if (!_entityIndices.TryGetValue(name, out var entityIndex))
|
||||
throw new ContextEntityIndexDoesNotExistException(this, name);
|
||||
|
||||
return entityIndex;
|
||||
}
|
||||
|
||||
/// Resets the creationIndex back to 0.
|
||||
public void ResetCreationIndex() => _creationIndex = 0;
|
||||
|
||||
/// Clears the componentPool at the specified index.
|
||||
public void ClearComponentPool(int index) => _componentPools[index]?.Clear();
|
||||
|
||||
/// Clears all componentPools.
|
||||
public void ClearComponentPools()
|
||||
{
|
||||
for (var i = 0; i < _componentPools.Length; i++)
|
||||
ClearComponentPool(i);
|
||||
}
|
||||
|
||||
/// Resets the context (destroys all entities and
|
||||
/// resets creationIndex back to 0).
|
||||
public void Reset()
|
||||
{
|
||||
DestroyAllEntities();
|
||||
ResetCreationIndex();
|
||||
}
|
||||
|
||||
/// Removes all event handlers
|
||||
/// OnEntityCreated, OnEntityWillBeDestroyed,
|
||||
/// OnEntityDestroyed and OnGroupCreated
|
||||
public void RemoveAllEventHandlers()
|
||||
{
|
||||
OnEntityCreated = null;
|
||||
OnEntityWillBeDestroyed = null;
|
||||
OnEntityDestroyed = null;
|
||||
OnGroupCreated = null;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return _contextInfo.name;
|
||||
}
|
||||
|
||||
void updateGroupsComponentAddedOrRemoved(IEntity entity, int index, IComponent component)
|
||||
{
|
||||
var groups = _groupsForIndex[index];
|
||||
if (groups != null)
|
||||
{
|
||||
var events = _groupChangedListPool.Get();
|
||||
var tEntity = (TEntity)entity;
|
||||
|
||||
for (var i = 0; i < groups.Count; i++)
|
||||
events.Add(groups[i].HandleEntity(tEntity));
|
||||
|
||||
for (var i = 0; i < events.Count; i++)
|
||||
events[i]?.Invoke(groups[i], tEntity, index, component);
|
||||
|
||||
_groupChangedListPool.Push(events);
|
||||
}
|
||||
}
|
||||
|
||||
void updateGroupsComponentReplaced(IEntity entity, int index, IComponent previousComponent, IComponent newComponent)
|
||||
{
|
||||
var groups = _groupsForIndex[index];
|
||||
if (groups != null)
|
||||
for (var i = 0; i < groups.Count; i++)
|
||||
groups[i].UpdateEntity((TEntity)entity, index, previousComponent, newComponent);
|
||||
}
|
||||
|
||||
void onEntityReleased(IEntity entity)
|
||||
{
|
||||
if (entity.isEnabled)
|
||||
throw new EntityIsNotDestroyedException($"Cannot release {entity}!");
|
||||
|
||||
var tEntity = (TEntity)entity;
|
||||
entity.RemoveAllOnEntityReleasedHandlers();
|
||||
_retainedEntities.Remove(tEntity);
|
||||
_reusableEntities.Push(tEntity);
|
||||
}
|
||||
|
||||
void onDestroyEntity(IEntity entity)
|
||||
{
|
||||
var tEntity = (TEntity)entity;
|
||||
var removed = _entities.Remove(tEntity);
|
||||
if (!removed)
|
||||
throw new ContextDoesNotContainEntityException(
|
||||
$"'{this}' cannot destroy {tEntity}!",
|
||||
"This cannot happen!?!"
|
||||
);
|
||||
|
||||
_entitiesCache = null;
|
||||
|
||||
OnEntityWillBeDestroyed?.Invoke(this, tEntity);
|
||||
tEntity.InternalDestroy();
|
||||
OnEntityDestroyed?.Invoke(this, tEntity);
|
||||
|
||||
if (tEntity.retainCount == 1)
|
||||
{
|
||||
// Can be released immediately without
|
||||
// adding to _retainedEntities
|
||||
tEntity.OnEntityReleased -= _cachedEntityReleased;
|
||||
_reusableEntities.Push(tEntity);
|
||||
tEntity.Release(this);
|
||||
tEntity.RemoveAllOnEntityReleasedHandlers();
|
||||
}
|
||||
else
|
||||
{
|
||||
_retainedEntities.Add(tEntity);
|
||||
tEntity.Release(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 971c624b1c12ef848819fa2a36a23b6f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,23 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public static class ContextExtension
|
||||
{
|
||||
/// Returns all entities matching the specified matcher.
|
||||
public static TEntity[] GetEntities<TEntity>(this IContext<TEntity> context, IMatcher<TEntity> matcher) where TEntity : class, IEntity =>
|
||||
context.GetGroup(matcher).GetEntities();
|
||||
|
||||
/// Creates a new entity and adds copies of all
|
||||
/// specified components to it.
|
||||
/// If replaceExisting is true it will replace exising components.
|
||||
public static TEntity CloneEntity<TEntity>(this IContext<TEntity> context,
|
||||
IEntity entity,
|
||||
bool replaceExisting = false,
|
||||
params int[] indices)
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
var target = context.CreateEntity();
|
||||
entity.CopyTo(target, replaceExisting, indices);
|
||||
return target;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c56eb6acbbfc9344f8823ad19b640b48
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9a2b2b35657e1f49ac0c66760558362
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public class ContextDoesNotContainEntityException : EntitasException
|
||||
{
|
||||
public ContextDoesNotContainEntityException(string message, string hint) : base(
|
||||
$"{message}\nContext does not contain entity!", hint) { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fff21e42cb7c8a4284f304989a489d6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public class ContextEntityIndexDoesAlreadyExistException : EntitasException
|
||||
{
|
||||
public ContextEntityIndexDoesAlreadyExistException(IContext context, string name) : base(
|
||||
$"Cannot add EntityIndex '{name}' to context '{context}'!",
|
||||
"An EntityIndex with this name has already been added.") { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f718a71f761c9634eb8b2ca7a974f425
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public class ContextEntityIndexDoesNotExistException : EntitasException
|
||||
{
|
||||
public ContextEntityIndexDoesNotExistException(IContext context, string name) : base(
|
||||
$"Cannot get EntityIndex '{name}' from context '{context}'!",
|
||||
"No EntityIndex with this name has been added.") { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 795af94e155d19842947a879222291fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public class ContextInfoException : EntitasException
|
||||
{
|
||||
public ContextInfoException(IContext context, ContextInfo contextInfo) : base(
|
||||
$"Invalid ContextInfo for '{context}'!\nExpected {context.totalComponents} componentName(s) but got {contextInfo.componentNames.Length}:",
|
||||
string.Join("\n", contextInfo.componentNames)) { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a0c400181a10e446a2634a80c383198
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Entitas
|
||||
{
|
||||
public class ContextStillHasRetainedEntitiesException : EntitasException
|
||||
{
|
||||
public ContextStillHasRetainedEntitiesException(IContext context, IEnumerable<IEntity> entities) : base(
|
||||
$"'{context}' detected retained entities although all entities got destroyed!",
|
||||
$"Did you release all entities? Try calling systems.DeactivateReactiveSystems() before calling context.DestroyAllEntities() to avoid memory leaks. Do not forget to activate them back when needed.\n{EntitiesToString(entities)}") { }
|
||||
|
||||
static string EntitiesToString(IEnumerable<IEntity> entities) => string.Join("\n",
|
||||
entities.Select(e => e.aerc is SafeAERC safeAerc
|
||||
? $"{e} - {string.Join(", ", safeAerc.owners.Select(o => o.ToString()))}"
|
||||
: e.ToString())
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42c96a2e1981f7d41ae270cfd62579fb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,9 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public class EntityIsNotDestroyedException : EntitasException
|
||||
{
|
||||
public EntityIsNotDestroyedException(string message) : base(
|
||||
$"{message}\nEntity is not destroyed yet!",
|
||||
"Did you manually call entity.Release(context) yourself? If so, please don\'t :)") { }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df7b40bb428b414499fb063efe7b1a6e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Entitas
|
||||
{
|
||||
public delegate void ContextEntityChanged(IContext context, IEntity entity);
|
||||
public delegate void ContextGroupChanged(IContext context, IGroup group);
|
||||
|
||||
public interface IContext
|
||||
{
|
||||
event ContextEntityChanged OnEntityCreated;
|
||||
event ContextEntityChanged OnEntityWillBeDestroyed;
|
||||
event ContextEntityChanged OnEntityDestroyed;
|
||||
|
||||
event ContextGroupChanged OnGroupCreated;
|
||||
|
||||
int totalComponents { get; }
|
||||
|
||||
Stack<IComponent>[] componentPools { get; }
|
||||
ContextInfo contextInfo { get; }
|
||||
|
||||
int count { get; }
|
||||
int reusableEntitiesCount { get; }
|
||||
int retainedEntitiesCount { get; }
|
||||
|
||||
void DestroyAllEntities();
|
||||
|
||||
void AddEntityIndex(IEntityIndex entityIndex);
|
||||
IEntityIndex GetEntityIndex(string name);
|
||||
|
||||
void ResetCreationIndex();
|
||||
void ClearComponentPool(int index);
|
||||
void ClearComponentPools();
|
||||
void RemoveAllEventHandlers();
|
||||
void Reset();
|
||||
}
|
||||
|
||||
public interface IContext<TEntity> : IContext where TEntity : class, IEntity
|
||||
{
|
||||
TEntity CreateEntity();
|
||||
|
||||
bool HasEntity(TEntity entity);
|
||||
TEntity[] GetEntities();
|
||||
|
||||
IGroup<TEntity> GetGroup(IMatcher<TEntity> matcher);
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63fbea5680a8ba34ea8865a46aad4bfc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,7 @@
|
||||
namespace Entitas
|
||||
{
|
||||
public interface IContexts
|
||||
{
|
||||
IContext[] allContexts { get; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45365f28b36959f4591e23f52acfd01b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Entitas
|
||||
{
|
||||
public class ContextInfo
|
||||
{
|
||||
public readonly string name;
|
||||
public readonly string[] componentNames;
|
||||
public readonly Type[] componentTypes;
|
||||
|
||||
public ContextInfo(string name, string[] componentNames, Type[] componentTypes)
|
||||
{
|
||||
this.name = name;
|
||||
this.componentNames = componentNames;
|
||||
this.componentTypes = componentTypes;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user