DragonECS-Unity/src/Connectors/EcsEntityConnect.cs

298 lines
10 KiB
C#
Raw Normal View History

2025-03-14 17:02:34 +08:00
#if DISABLE_DEBUG
#undef DEBUG
#endif
2024-03-09 03:35:01 +08:00
using System.Collections.Generic;
using System.Linq;
2023-05-07 00:50:44 +08:00
using System.Runtime.CompilerServices;
2024-10-12 23:18:58 +08:00
using DCFApixels.DragonECS.Unity;
2023-05-07 00:50:44 +08:00
using UnityEngine;
2024-10-12 23:18:58 +08:00
using DCFApixels.DragonECS.Unity.Internal;
2024-10-11 23:29:48 +08:00
#if UNITY_EDITOR
2024-05-16 19:03:03 +08:00
using UnityEditor;
2025-04-16 09:36:51 +08:00
using DCFApixels.DragonECS.Unity.Editors;
2024-10-11 23:29:48 +08:00
#endif
2023-05-07 00:50:44 +08:00
namespace DCFApixels.DragonECS
{
2024-10-19 00:05:07 +08:00
using static EcsConsts;
2024-03-10 10:20:44 +08:00
public static class EcsConnect
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-02 17:13:11 +08:00
public static EcsEntityConnect Connect(this Component cmp, entlong entity, bool applyTemplates)
2024-03-10 10:24:58 +08:00
{
2026-03-02 17:13:11 +08:00
return Connect(entity, cmp, applyTemplates);
2024-03-10 10:24:58 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-02 17:13:11 +08:00
public static EcsEntityConnect Connect(this entlong entity, Component cmp, bool applyTemplates)
2024-03-10 10:24:58 +08:00
{
if (cmp.TryGetComponent(out EcsEntityConnect connect) == false)
{
connect = cmp.gameObject.AddComponent<EcsEntityConnect>();
}
connect.ConnectWith(entity, applyTemplates);
2026-03-02 17:13:11 +08:00
return connect;
2024-03-10 10:24:58 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-02 17:13:11 +08:00
public static EcsEntityConnect Connect(this GameObject go, entlong entity, bool applyTemplates)
2024-03-10 10:20:44 +08:00
{
2026-03-02 17:13:11 +08:00
return Connect(entity, go, applyTemplates);
2024-03-10 10:20:44 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-02 17:13:11 +08:00
public static EcsEntityConnect Connect(this entlong entity, GameObject go, bool applyTemplates)
2024-03-10 10:20:44 +08:00
{
if (go.TryGetComponent(out EcsEntityConnect connect) == false)
{
connect = go.AddComponent<EcsEntityConnect>();
}
connect.ConnectWith(entity, applyTemplates);
2026-03-02 17:13:11 +08:00
return connect;
2024-03-10 10:20:44 +08:00
}
2024-03-10 10:24:58 +08:00
2024-03-10 10:20:44 +08:00
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-02 17:13:11 +08:00
public static EcsEntityConnect Connect(this EcsEntityConnect connect, entlong entity, bool applyTemplates)
2024-03-10 10:20:44 +08:00
{
2026-03-02 17:13:11 +08:00
return Connect(entity, connect, applyTemplates);
2024-03-10 10:20:44 +08:00
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2026-03-02 17:13:11 +08:00
public static EcsEntityConnect Connect(this entlong entity, EcsEntityConnect connect, bool applyTemplates)
2024-03-10 10:20:44 +08:00
{
connect.ConnectWith(entity, applyTemplates);
2026-03-02 17:13:11 +08:00
return connect;
2024-03-10 10:20:44 +08:00
}
}
2024-03-10 10:24:58 +08:00
[SelectionBase]
2024-03-09 09:56:45 +08:00
[DisallowMultipleComponent]
2024-10-19 00:05:07 +08:00
[AddComponentMenu(FRAMEWORK_NAME + "/" + nameof(EcsEntityConnect), 30)]
2024-10-12 14:37:21 +08:00
[MetaColor(MetaColor.DragonCyan)]
2024-06-13 18:04:47 +08:00
[MetaGroup(EcsUnityConsts.PACK_GROUP, EcsUnityConsts.ENTITY_BUILDING_GROUP)]
2024-10-19 00:05:07 +08:00
[MetaDescription(AUTHOR, nameof(MonoBehaviour) + ". Responsible for connecting the entity and GameObject using the EcsEntityConnect.ConnectWith method.")]
2025-03-19 16:31:32 +08:00
[MetaID("DragonECS_FF7EB3809201DEC2F1977C00D3B3443B")]
2025-03-24 20:12:07 +08:00
public class EcsEntityConnect : MonoBehaviour, ITemplateNode
2023-05-07 00:50:44 +08:00
{
private entlong _entity;
private EcsWorld _world;
private static SparseArray<EcsEntityConnect> _connectedEntities = new SparseArray<EcsEntityConnect>();
2024-03-28 18:43:42 +08:00
[SerializeField]
2024-10-12 20:11:37 +08:00
private bool _deleteEntityWithDestroy = false;
2023-05-07 00:50:44 +08:00
[SerializeField]
2026-03-02 17:13:11 +08:00
private ScriptableEntityTemplateBase[] _scriptableTemplates = System.Array.Empty<ScriptableEntityTemplateBase>();
2023-05-07 00:50:44 +08:00
[SerializeField]
2026-03-02 17:13:11 +08:00
private MonoEntityTemplateBase[] _monoTemplates = System.Array.Empty<MonoEntityTemplateBase>();
2023-05-07 00:50:44 +08:00
2024-03-28 18:43:42 +08:00
private bool _isConnectInvoked = false;
2024-03-10 22:27:17 +08:00
2025-03-24 20:12:07 +08:00
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void OnLoad()
{
_connectedEntities.Clear();
}
2023-05-07 00:50:44 +08:00
#region Properties
public entlong Entity
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-09 03:35:01 +08:00
get { return _entity; }
2023-05-07 00:50:44 +08:00
}
public EcsWorld World
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-10 09:50:20 +08:00
get { return _world; }
2023-05-07 00:50:44 +08:00
}
2024-03-10 10:20:44 +08:00
public bool IsConnected
2023-05-07 00:50:44 +08:00
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2024-03-10 09:50:20 +08:00
get { return _entity.IsAlive; }
2023-05-07 00:50:44 +08:00
}
2024-04-26 06:05:29 +08:00
public IEnumerable<ScriptableEntityTemplateBase> ScriptableTemplates
2024-03-09 03:35:01 +08:00
{
get { return _scriptableTemplates; }
}
2024-04-26 06:05:29 +08:00
public IEnumerable<MonoEntityTemplateBase> MonoTemplates
2024-03-09 03:35:01 +08:00
{
get { return _monoTemplates; }
}
2026-03-02 17:01:46 +08:00
public IEnumerable<ITemplateNode> AllTemplates
2024-03-09 03:35:01 +08:00
{
2026-03-02 17:01:46 +08:00
get { return ((IEnumerable<ITemplateNode>)_scriptableTemplates).Concat(_monoTemplates); }
2024-03-09 03:35:01 +08:00
}
2023-05-07 00:50:44 +08:00
#endregion
2024-03-09 03:35:01 +08:00
#region Connect
2025-03-24 20:12:07 +08:00
void ITemplateNode.Apply(short worldID, int entityID)
{
ConnectWith((EcsWorld.GetWorld(worldID), entityID), true);
}
2024-03-10 09:50:20 +08:00
public void ConnectWith(entlong entity, bool applyTemplates)
2023-05-07 00:50:44 +08:00
{
2024-03-10 10:20:44 +08:00
Disconnect();
2023-05-07 00:50:44 +08:00
2024-03-10 09:50:20 +08:00
if (entity.TryUnpack(out int newEntityID, out EcsWorld world))
2023-05-07 00:50:44 +08:00
{
2024-03-28 18:43:42 +08:00
_isConnectInvoked = true;
2023-05-07 00:50:44 +08:00
_entity = entity;
2024-03-10 09:50:20 +08:00
_world = world;
2025-04-16 09:36:51 +08:00
#if UNITY_EDITOR
2026-04-14 15:19:41 +08:00
world.Get<DragonGUI.EntityLinksComponent>().SetConnectLink(entity.GetIDUnchecked(), this);
2025-04-16 09:36:51 +08:00
#endif
_connectedEntities.Add(GetInstanceID(), this);
2024-03-10 22:27:17 +08:00
var goConnects = world.GetPool<GameObjectConnect>();
if (goConnects.Has(newEntityID))
2024-03-09 03:35:01 +08:00
{
2024-03-10 22:27:17 +08:00
ref readonly var goConnect = ref goConnects.Read(newEntityID);
if (goConnect.IsConnected)
2024-03-10 10:20:44 +08:00
{
2024-03-10 22:27:17 +08:00
goConnect.Connect.Disconnect();
2024-03-10 10:20:44 +08:00
}
2024-03-09 03:35:01 +08:00
}
2024-03-10 10:20:44 +08:00
2024-03-10 22:27:17 +08:00
goConnects.TryAddOrGet(newEntityID) = new GameObjectConnect(this);
2023-05-07 00:50:44 +08:00
if (applyTemplates)
2024-03-09 03:35:01 +08:00
{
2024-11-01 12:44:45 +08:00
ApplyTemplatesFor(world.ID, newEntityID);
2024-03-09 03:35:01 +08:00
}
2023-05-07 00:50:44 +08:00
}
}
2024-03-10 10:20:44 +08:00
public void Disconnect()
{
2024-03-28 18:43:42 +08:00
if (_isConnectInvoked == false)
2024-03-10 22:27:17 +08:00
{
return;
}
2024-03-28 18:43:42 +08:00
_isConnectInvoked = false;
2024-03-28 23:24:39 +08:00
if (_world.IsNullOrDetroyed() == false && _entity.TryGetID(out int oldEntityID))
2024-03-10 10:20:44 +08:00
{
2024-03-10 22:27:17 +08:00
var unityGameObjects = _world.GetPool<GameObjectConnect>();
2024-03-10 10:29:58 +08:00
unityGameObjects.TryDel(oldEntityID);
2024-03-10 10:20:44 +08:00
}
2024-08-13 22:16:58 +08:00
_connectedEntities.Remove(GetInstanceID());
2024-03-10 10:20:44 +08:00
_world = null;
2024-03-10 10:35:02 +08:00
_entity = entlong.NULL;
2024-03-10 10:20:44 +08:00
}
2024-03-09 03:35:01 +08:00
#endregion
#region ApplyTemplates
2024-03-10 09:50:20 +08:00
public void ApplyTemplatesFor(short worldID, int entityID)
2023-05-07 00:50:44 +08:00
{
2024-03-09 03:35:01 +08:00
foreach (var template in _scriptableTemplates)
2024-03-03 03:51:49 +08:00
{
2024-03-10 09:50:20 +08:00
template.Apply(worldID, entityID);
2024-03-03 03:51:49 +08:00
}
2024-03-09 03:35:01 +08:00
foreach (var template in _monoTemplates)
2024-03-03 03:51:49 +08:00
{
2024-03-10 09:50:20 +08:00
template.Apply(worldID, entityID);
2024-03-03 03:51:49 +08:00
}
2023-05-07 00:50:44 +08:00
}
2024-03-09 03:35:01 +08:00
#endregion
2024-03-10 19:23:05 +08:00
#region UnityEvents
private void OnDestroy()
{
2024-03-28 18:43:42 +08:00
entlong ent = _entity;
2024-03-10 19:23:05 +08:00
Disconnect();
2024-10-12 20:11:37 +08:00
if (_deleteEntityWithDestroy == false)
2024-03-28 18:43:42 +08:00
{
return;
2024-03-28 18:43:42 +08:00
}
ent.UnpackUnchecked(out int e, out short gen, out short worldID);
var world = EcsWorld.GetWorld(worldID);
if (world != null && world.IsAlive(e, gen))
{
world.DelEntity(e);
}
//if (_deleteEntiityWithDestroy && ent.TryUnpack(out int id, out EcsWorld world))
//{
// world.DelEntity(id);
//}
}
#endregion
#region Other
public static EcsEntityConnect GetConnectByInstanceID(int instanceID)
{
return _connectedEntities[instanceID];
}
public static bool TryGetConnectByInstanceID(int instanceID, out EcsEntityConnect conncet)
{
return _connectedEntities.TryGetValue(instanceID, out conncet);
2024-03-10 19:23:05 +08:00
}
#endregion
2024-03-09 03:35:01 +08:00
#region Editor
2024-03-09 22:36:35 +08:00
#if UNITY_EDITOR
[ContextMenu("Autoset")]
2026-03-02 17:13:11 +08:00
public void Autoset_Editor()
2024-03-09 03:35:01 +08:00
{
2024-03-09 22:36:35 +08:00
Autoset(this);
2024-03-09 03:35:01 +08:00
}
2024-03-09 22:36:35 +08:00
[ContextMenu("Autoset Cascade")]
2026-03-02 17:13:11 +08:00
public void AutosetCascade_Editor()
2024-03-09 22:36:35 +08:00
{
foreach (var item in GetComponentsInChildren<EcsEntityConnect>())
{
Autoset(item);
}
}
[ContextMenu("Unlink Entity")]
internal void UnlinkEntity_Editor()
{
2024-03-10 09:50:20 +08:00
ConnectWith(entlong.NULL, false);
2024-03-09 22:36:35 +08:00
}
[ContextMenu("Delete Entity")]
internal void DeleteEntity_Editor()
{
if (_entity.TryUnpack(out int id, out EcsWorld world))
{
world.DelEntity(id);
}
UnlinkEntity_Editor();
}
private static void Autoset(EcsEntityConnect target)
{
2024-04-26 06:05:29 +08:00
IEnumerable<MonoEntityTemplateBase> result;
2024-03-28 18:43:42 +08:00
if (target.MonoTemplates != null && target.MonoTemplates.Count() > 0)
{
2026-03-02 17:13:11 +08:00
result = target.MonoTemplates.Where(o => o != null).Union(GetTemplatesFor(target.transform).Range);
2024-03-28 18:43:42 +08:00
}
else
{
2026-03-02 17:13:11 +08:00
result = GetTemplatesFor(target.transform).Range;
2024-03-28 18:43:42 +08:00
}
2024-03-09 22:36:35 +08:00
target._monoTemplates = result.ToArray();
EditorUtility.SetDirty(target);
}
2026-03-02 17:13:11 +08:00
private static (int Count, IEnumerable<MonoEntityTemplateBase> Range) GetTemplatesFor(Transform parent)
2024-03-09 22:36:35 +08:00
{
2026-03-02 17:13:11 +08:00
(int Count, IEnumerable<MonoEntityTemplateBase> Range) result;
result.Count = 0;
result.Range = parent.GetComponents<MonoEntityTemplateBase>();
2024-03-09 22:36:35 +08:00
for (int i = 0; i < parent.childCount; i++)
{
var child = parent.GetChild(i);
2026-03-02 17:13:11 +08:00
if (child.TryGetComponent<EcsEntityConnect>(out _) == false)
2024-03-09 22:36:35 +08:00
{
2026-03-02 17:13:11 +08:00
var concated = GetTemplatesFor(child);
if (concated.Count > 0)
{
result.Range = result.Range.Concat(concated.Range);
result.Count += concated.Count;
}
2024-03-09 22:36:35 +08:00
}
}
return result;
}
#endif
2024-03-09 03:35:01 +08:00
#endregion
2023-05-07 00:50:44 +08:00
}
2024-03-06 21:37:21 +08:00
}