mirror of
https://github.com/DCFApixels/DragonECS-Unity.git
synced 2026-04-22 04:35:55 +08:00
Merge branch 'dev'
This commit is contained in:
commit
5d9e9e7055
@ -7,7 +7,7 @@
|
|||||||
},
|
},
|
||||||
"displayName": "DragonECS-Unity",
|
"displayName": "DragonECS-Unity",
|
||||||
"description": "Integration with Unity for DragonECS",
|
"description": "Integration with Unity for DragonECS",
|
||||||
"unity": "2020.3",
|
"unity": "2021.2",
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a124aa9f464ff79439c89b52281215d3
|
guid: f2b9c91714b4752468a3a5691cbf5237
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
7
src/Buildin/EcsDefaultWorldProvider.cs
Normal file
7
src/Buildin/EcsDefaultWorldProvider.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(fileName = nameof(EcsDefaultWorldProvider), menuName = EcsConsts.FRAMEWORK_NAME + "/WorldProviders/" + nameof(EcsDefaultWorldProvider), order = 1)]
|
||||||
|
public class EcsDefaultWorldProvider : EcsWorldProvider<EcsDefaultWorld> { }
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: d36835beef2392f40854af962ff47472
|
guid: 15b6f990a7e05b34a937a9a850d7c68c
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
18
src/Buildin/EcsDefaultWorldSingletonProvider.cs
Normal file
18
src/Buildin/EcsDefaultWorldSingletonProvider.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public class EcsDefaultWorldSingletonProvider : EcsWorldProvider<EcsDefaultWorld>
|
||||||
|
{
|
||||||
|
private static EcsDefaultWorldSingletonProvider _instance;
|
||||||
|
public static EcsDefaultWorldSingletonProvider Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
_instance = FindOrCreateSingleton<EcsDefaultWorldSingletonProvider>("SingletonDefaultWorld");
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: f72bc8ca8108c2b4aac41df126dba1e1
|
guid: 7592c6e5a68845c4abeac089e561d8c7
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
120
src/Buildin/UnityComponents.cs
Normal file
120
src/Buildin/UnityComponents.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
internal static class UnityComponentConsts
|
||||||
|
{
|
||||||
|
private const string UNITY_COMPONENT_NAME = "UnityComponent";
|
||||||
|
public static readonly MetaGroup BaseGroup = new MetaGroupRef(UNITY_COMPONENT_NAME);
|
||||||
|
public static readonly MetaGroup ColliderGroup = new MetaGroupRef($"{UNITY_COMPONENT_NAME}/Collider/");
|
||||||
|
public static readonly MetaGroup JointGroup = new MetaGroupRef($"{UNITY_COMPONENT_NAME}/Joint/");
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
[MetaColor(255 / 3, 255, 0)]
|
||||||
|
public struct UnityComponent<T> : IEcsComponent, IEnumerable<T>//IntelliSense hack
|
||||||
|
where T : Component
|
||||||
|
{
|
||||||
|
public T obj;
|
||||||
|
public UnityComponent(T obj)
|
||||||
|
{
|
||||||
|
this.obj = obj;
|
||||||
|
}
|
||||||
|
IEnumerator<T> IEnumerable<T>.GetEnumerator() //IntelliSense hack
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() //IntelliSense hack
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Unity Component Templates
|
||||||
|
public class UnityComponentTemplate<T> : ComponentTemplateBase<UnityComponent<T>> where T : Component
|
||||||
|
{
|
||||||
|
public override string Name
|
||||||
|
{
|
||||||
|
get { return typeof(T).Name; }
|
||||||
|
}
|
||||||
|
public override MetaGroup Group
|
||||||
|
{
|
||||||
|
get { return UnityComponentConsts.BaseGroup; }
|
||||||
|
}
|
||||||
|
public sealed override void Apply(int worldID, int entityID)
|
||||||
|
{
|
||||||
|
EcsWorld.GetPoolInstance<EcsPool<UnityComponent<T>>>(worldID).TryAddOrGet(entityID) = component;
|
||||||
|
}
|
||||||
|
public override void OnValidate(UnityEngine.Object obj)
|
||||||
|
{
|
||||||
|
if (component.obj == null)
|
||||||
|
{
|
||||||
|
if (obj is GameObject go)
|
||||||
|
{
|
||||||
|
component.obj = go.GetComponent<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentRigitBodyInitializer : UnityComponentTemplate<Rigidbody> { }
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentAnimatorInitializer : UnityComponentTemplate<Animator> { }
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentCharacterControllerInitializer : UnityComponentTemplate<CharacterController> { }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Collider Templates
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentColliderTemplate : UnityComponentTemplate<Collider>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.ColliderGroup; } }
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentBoxColliderTemplate : UnityComponentTemplate<BoxCollider>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.ColliderGroup; } }
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentSphereColliderTemplate : UnityComponentTemplate<SphereCollider>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.ColliderGroup; } }
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentCapsuleColliderTemplate : UnityComponentTemplate<CapsuleCollider>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.ColliderGroup; } }
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentMeshColliderTemplate : UnityComponentTemplate<MeshCollider>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.ColliderGroup; } }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Joint Templates
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentJointTemplate : UnityComponentTemplate<Joint>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.JointGroup; } }
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentFixedJointTemplate : UnityComponentTemplate<FixedJoint>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.JointGroup; } }
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentCharacterJointTemplate : UnityComponentTemplate<CharacterJoint>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.JointGroup; } }
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class UnityComponentConfigurableJointTemplate : UnityComponentTemplate<ConfigurableJoint>
|
||||||
|
{
|
||||||
|
public override MetaGroup Group { get { return UnityComponentConsts.JointGroup; } }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 47a8547ed46c26e4bb6a68651ad40be0
|
guid: 637d69c48b6c0164abe654cd7f5ceb07
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
141
src/Buildin/UnityGameCyclieProcesses.cs
Normal file
141
src/Buildin/UnityGameCyclieProcesses.cs
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
using DCFApixels.DragonECS.RunnersCore;
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
[MetaName(nameof(DrawGizmos))]
|
||||||
|
[MetaColor(MetaColor.Orange)]
|
||||||
|
public interface IEcsGizmosProcess : IEcsProcess
|
||||||
|
{
|
||||||
|
public void DrawGizmos();
|
||||||
|
}
|
||||||
|
[MetaName(nameof(LateRun))]
|
||||||
|
[MetaColor(MetaColor.Orange)]
|
||||||
|
public interface IEcsLateRunProcess : IEcsProcess
|
||||||
|
{
|
||||||
|
public void LateRun();
|
||||||
|
}
|
||||||
|
[MetaName(nameof(FixedRun))]
|
||||||
|
[MetaColor(MetaColor.Orange)]
|
||||||
|
public interface IEcsFixedRunProcess : IEcsProcess
|
||||||
|
{
|
||||||
|
public void FixedRun();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class UnityProcessExtensions
|
||||||
|
{
|
||||||
|
public static void DrawGizmos(this EcsPipeline pipeline)
|
||||||
|
{
|
||||||
|
pipeline.GetRunnerInstance<EcsLateGizmosRunner>().DrawGizmos();
|
||||||
|
}
|
||||||
|
public static void LateRun(this EcsPipeline pipeline)
|
||||||
|
{
|
||||||
|
pipeline.GetRunnerInstance<EcsLateRunRunner>().LateRun();
|
||||||
|
}
|
||||||
|
public static void FixedRun(this EcsPipeline pipeline)
|
||||||
|
{
|
||||||
|
pipeline.GetRunnerInstance<EcsFixedRunRunner>().FixedRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Internal
|
||||||
|
{
|
||||||
|
|
||||||
|
[MetaColor(MetaColor.Orange)]
|
||||||
|
public class EcsLateGizmosRunner : EcsRunner<IEcsGizmosProcess>, IEcsGizmosProcess
|
||||||
|
{
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
private EcsProfilerMarker[] _markers;
|
||||||
|
#endif
|
||||||
|
public void DrawGizmos()
|
||||||
|
{
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
for (int i = 0; i < Process.Length; i++)
|
||||||
|
{
|
||||||
|
using (_markers[i].Auto())
|
||||||
|
{
|
||||||
|
Process[i].DrawGizmos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
foreach (var item in targets) item.DrawGizmos();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
protected override void OnSetup()
|
||||||
|
{
|
||||||
|
_markers = new EcsProfilerMarker[Process.Length];
|
||||||
|
for (int i = 0; i < Process.Length; i++)
|
||||||
|
{
|
||||||
|
_markers[i] = new EcsProfilerMarker($"{Process[i].GetType().Name}.{nameof(DrawGizmos)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[MetaColor(MetaColor.Orange)]
|
||||||
|
public class EcsLateRunRunner : EcsRunner<IEcsLateRunProcess>, IEcsLateRunProcess
|
||||||
|
{
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
private EcsProfilerMarker[] _markers;
|
||||||
|
#endif
|
||||||
|
public void LateRun()
|
||||||
|
{
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
for (int i = 0; i < Process.Length; i++)
|
||||||
|
{
|
||||||
|
using (_markers[i].Auto())
|
||||||
|
{
|
||||||
|
Process[i].LateRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
foreach (var item in targets) item.LateRun();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
protected override void OnSetup()
|
||||||
|
{
|
||||||
|
_markers = new EcsProfilerMarker[Process.Length];
|
||||||
|
for (int i = 0; i < Process.Length; i++)
|
||||||
|
{
|
||||||
|
_markers[i] = new EcsProfilerMarker($"EcsRunner.{Process[i].GetType().Name}.{nameof(LateRun)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
[MetaColor(MetaColor.Orange)]
|
||||||
|
public class EcsFixedRunRunner : EcsRunner<IEcsFixedRunProcess>, IEcsFixedRunProcess
|
||||||
|
{
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
private EcsProfilerMarker[] _markers;
|
||||||
|
#endif
|
||||||
|
public void FixedRun()
|
||||||
|
{
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
for (int i = 0; i < Process.Length; i++)
|
||||||
|
{
|
||||||
|
using (_markers[i].Auto())
|
||||||
|
{
|
||||||
|
Process[i].FixedRun();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
foreach (var item in targets) item.FixedRun();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if DEBUG && !DISABLE_DEBUG
|
||||||
|
protected override void OnSetup()
|
||||||
|
{
|
||||||
|
_markers = new EcsProfilerMarker[Process.Length];
|
||||||
|
for (int i = 0; i < Process.Length; i++)
|
||||||
|
{
|
||||||
|
_markers[i] = new EcsProfilerMarker($"EcsRunner.{Process[i].GetType().Name}.{nameof(FixedRun)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 6b7b4bd406553d64589aa4e085d4ff28
|
guid: 9b692b77d059ff445912bada1712ccab
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 37d966ee996491b4d923ae68af4b67cd
|
guid: 2b32116c3998f6742a35e492a88176be
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
92
src/Connectors/AutoEntityCreator.cs
Normal file
92
src/Connectors/AutoEntityCreator.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
[DisallowMultipleComponent]
|
||||||
|
public class AutoEntityCreator : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField]
|
||||||
|
private EcsEntityConnect _connect;
|
||||||
|
[SerializeField]
|
||||||
|
private EcsWorldProviderBase _world;
|
||||||
|
|
||||||
|
private bool _created;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public EcsEntityConnect Connect => _connect;
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UnityEvents
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (_world == null)
|
||||||
|
{
|
||||||
|
AutoResolveWorldProviderDependensy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
|
||||||
|
CreateEntity();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
private void AutoResolveWorldProviderDependensy()
|
||||||
|
{
|
||||||
|
_world = EcsDefaultWorldSingletonProvider.Instance;
|
||||||
|
}
|
||||||
|
public void ManualStart()
|
||||||
|
{
|
||||||
|
CreateEntity();
|
||||||
|
}
|
||||||
|
private void CreateEntity()
|
||||||
|
{
|
||||||
|
if (_created)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_world == null)
|
||||||
|
{
|
||||||
|
AutoResolveWorldProviderDependensy();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InitConnect(_connect, _world.GetRaw());
|
||||||
|
}
|
||||||
|
_created = true;
|
||||||
|
}
|
||||||
|
private void InitConnect(EcsEntityConnect connect, EcsWorld world)
|
||||||
|
{
|
||||||
|
connect.ConnectWith(world.NewEntityLong(), true);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Editor
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[ContextMenu("Autoset")]
|
||||||
|
internal void Autoset_Editor()
|
||||||
|
{
|
||||||
|
foreach (var connect in GetComponentsInChildren<EcsEntityConnect>())
|
||||||
|
{
|
||||||
|
if (connect.GetComponentInParent<AutoEntityCreator>() == this)
|
||||||
|
{
|
||||||
|
_connect = connect;
|
||||||
|
AutoResolveWorldProviderDependensy();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[ContextMenu("Autoset Cascade")]
|
||||||
|
internal void AutosetCascade_Editor()
|
||||||
|
{
|
||||||
|
foreach (var target in GetComponentsInChildren<AutoEntityCreator>())
|
||||||
|
{
|
||||||
|
target.Autoset_Editor();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 1caa902906afea3409fc63ed94cbbc11
|
guid: e244d7ed454067a4bb82fecd87513856
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
215
src/Connectors/EcsEntityConnect.cs
Normal file
215
src/Connectors/EcsEntityConnect.cs
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public static class EcsConnect
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Connect(this Component cmp, entlong entity, bool applyTemplates)
|
||||||
|
{
|
||||||
|
Connect(entity, cmp, applyTemplates);
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Connect(this entlong entity, Component cmp, bool applyTemplates)
|
||||||
|
{
|
||||||
|
if (cmp.TryGetComponent(out EcsEntityConnect connect) == false)
|
||||||
|
{
|
||||||
|
connect = cmp.gameObject.AddComponent<EcsEntityConnect>();
|
||||||
|
}
|
||||||
|
connect.ConnectWith(entity, applyTemplates);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Connect(this GameObject go, entlong entity, bool applyTemplates)
|
||||||
|
{
|
||||||
|
Connect(entity, go, applyTemplates);
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Connect(this entlong entity, GameObject go, bool applyTemplates)
|
||||||
|
{
|
||||||
|
if (go.TryGetComponent(out EcsEntityConnect connect) == false)
|
||||||
|
{
|
||||||
|
connect = go.AddComponent<EcsEntityConnect>();
|
||||||
|
}
|
||||||
|
connect.ConnectWith(entity, applyTemplates);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Connect(this EcsEntityConnect connect, entlong entity, bool applyTemplates)
|
||||||
|
{
|
||||||
|
Connect(entity, connect, applyTemplates);
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Connect(this entlong entity, EcsEntityConnect connect, bool applyTemplates)
|
||||||
|
{
|
||||||
|
connect.ConnectWith(entity, applyTemplates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DisallowMultipleComponent]
|
||||||
|
public class EcsEntityConnect : MonoBehaviour
|
||||||
|
{
|
||||||
|
private entlong _entity;
|
||||||
|
private EcsWorld _world;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private ScriptableEntityTemplate[] _scriptableTemplates;
|
||||||
|
[SerializeField]
|
||||||
|
private MonoEntityTemplate[] _monoTemplates;
|
||||||
|
|
||||||
|
private bool _isConnected = false;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public entlong Entity
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _entity; }
|
||||||
|
}
|
||||||
|
public EcsWorld World
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _world; }
|
||||||
|
}
|
||||||
|
public bool IsConnected
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _entity.IsAlive; }
|
||||||
|
}
|
||||||
|
public IEnumerable<ScriptableEntityTemplate> ScriptableTemplates
|
||||||
|
{
|
||||||
|
get { return _scriptableTemplates; }
|
||||||
|
}
|
||||||
|
public IEnumerable<MonoEntityTemplate> MonoTemplates
|
||||||
|
{
|
||||||
|
get { return _monoTemplates; }
|
||||||
|
}
|
||||||
|
public IEnumerable<ITemplateInternal> AllTemplates
|
||||||
|
{
|
||||||
|
get { return ((IEnumerable<ITemplateInternal>)_scriptableTemplates).Concat(_monoTemplates); }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Connect
|
||||||
|
public void ConnectWith(entlong entity, bool applyTemplates)
|
||||||
|
{
|
||||||
|
Disconnect();
|
||||||
|
|
||||||
|
if (entity.TryUnpack(out int newEntityID, out EcsWorld world))
|
||||||
|
{
|
||||||
|
_isConnected = true;
|
||||||
|
_entity = entity;
|
||||||
|
_world = world;
|
||||||
|
var goConnects = world.GetPool<GameObjectConnect>();
|
||||||
|
if (goConnects.Has(newEntityID))
|
||||||
|
{
|
||||||
|
ref readonly var goConnect = ref goConnects.Read(newEntityID);
|
||||||
|
if (goConnect.IsConnected)
|
||||||
|
{
|
||||||
|
goConnect.Connect.Disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goConnects.TryAddOrGet(newEntityID) = new GameObjectConnect(this);
|
||||||
|
if (applyTemplates)
|
||||||
|
{
|
||||||
|
ApplyTemplatesFor(world.id, newEntityID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Disconnect()
|
||||||
|
{
|
||||||
|
if(_isConnected == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_isConnected = false;
|
||||||
|
if (_entity.TryGetID(out int oldEntityID) && _world != null)
|
||||||
|
{
|
||||||
|
var unityGameObjects = _world.GetPool<GameObjectConnect>();
|
||||||
|
unityGameObjects.TryDel(oldEntityID);
|
||||||
|
}
|
||||||
|
_world = null;
|
||||||
|
_entity = entlong.NULL;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ApplyTemplates
|
||||||
|
public void ApplyTemplatesFor(short worldID, int entityID)
|
||||||
|
{
|
||||||
|
foreach (var template in _scriptableTemplates)
|
||||||
|
{
|
||||||
|
template.Apply(worldID, entityID);
|
||||||
|
}
|
||||||
|
foreach (var template in _monoTemplates)
|
||||||
|
{
|
||||||
|
template.Apply(worldID, entityID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UnityEvents
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Editor
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
[ContextMenu("Autoset")]
|
||||||
|
internal void Autoset_Editor()
|
||||||
|
{
|
||||||
|
Autoset(this);
|
||||||
|
}
|
||||||
|
[ContextMenu("Autoset Cascade")]
|
||||||
|
internal void AutosetCascade_Editor()
|
||||||
|
{
|
||||||
|
foreach (var item in GetComponentsInChildren<EcsEntityConnect>())
|
||||||
|
{
|
||||||
|
Autoset(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[ContextMenu("Unlink Entity")]
|
||||||
|
internal void UnlinkEntity_Editor()
|
||||||
|
{
|
||||||
|
ConnectWith(entlong.NULL, false);
|
||||||
|
}
|
||||||
|
[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)
|
||||||
|
{
|
||||||
|
var result = target.MonoTemplates.Where(o => o != null).Union(GetTemplatesFor(target.transform));
|
||||||
|
|
||||||
|
target._monoTemplates = result.ToArray();
|
||||||
|
EditorUtility.SetDirty(target);
|
||||||
|
}
|
||||||
|
private static IEnumerable<MonoEntityTemplate> GetTemplatesFor(Transform parent)
|
||||||
|
{
|
||||||
|
IEnumerable<MonoEntityTemplate> result = parent.GetComponents<MonoEntityTemplate>();
|
||||||
|
for (int i = 0; i < parent.childCount; i++)
|
||||||
|
{
|
||||||
|
var child = parent.GetChild(i);
|
||||||
|
if (child.TryGetComponent<EcsEntityConnect>(out _))
|
||||||
|
{
|
||||||
|
return Enumerable.Empty<MonoEntityTemplate>();
|
||||||
|
}
|
||||||
|
result = result.Concat(GetTemplatesFor(child));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: cdc92b01ccc1e684f955830aa7cea7d4
|
guid: 495156623a7b1e94087f916ba42745e6
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
129
src/Connectors/EcsWorldProvider.cs
Normal file
129
src/Connectors/EcsWorldProvider.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public abstract class EcsWorldProviderBase : ScriptableObject
|
||||||
|
{
|
||||||
|
public abstract bool IsEmpty { get; }
|
||||||
|
public abstract void SetRaw(EcsWorld world);
|
||||||
|
public abstract EcsWorld GetRaw();
|
||||||
|
public abstract EcsWorld GetCurrentWorldRaw();
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public abstract class EcsWorldProvider<TWorld> : EcsWorldProviderBase where TWorld : EcsWorld
|
||||||
|
{
|
||||||
|
private TWorld _world;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
public short _worldID = -1;
|
||||||
|
|
||||||
|
[Header("Default Configs")]
|
||||||
|
[Header("Entites")]
|
||||||
|
[SerializeField]
|
||||||
|
private int _entitiesCapacity = EcsWorldConfig.Default.EntitiesCapacity;
|
||||||
|
|
||||||
|
[Header("Groups")]
|
||||||
|
[SerializeField]
|
||||||
|
private int _groupCapacity = EcsWorldConfig.Default.GroupCapacity;
|
||||||
|
|
||||||
|
[Header("Pools/Components")]
|
||||||
|
[SerializeField]
|
||||||
|
private int _poolsCapacity = EcsWorldConfig.Default.PoolsCapacity;
|
||||||
|
[SerializeField]
|
||||||
|
private int _poolComponentsCapacity = EcsWorldConfig.Default.PoolComponentsCapacity;
|
||||||
|
[SerializeField]
|
||||||
|
private int _poolRecycledComponentsCapacity = EcsWorldConfig.Default.PoolRecycledComponentsCapacity;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public sealed override bool IsEmpty
|
||||||
|
{
|
||||||
|
get { return _world == null; }
|
||||||
|
}
|
||||||
|
public int EntitiesCapacity
|
||||||
|
{
|
||||||
|
get { return _entitiesCapacity; }
|
||||||
|
}
|
||||||
|
public int GroupCapacity
|
||||||
|
{
|
||||||
|
get { return _groupCapacity; }
|
||||||
|
}
|
||||||
|
public int PoolsCapacity
|
||||||
|
{
|
||||||
|
get { return _poolsCapacity; }
|
||||||
|
}
|
||||||
|
public int PoolComponentsCapacity
|
||||||
|
{
|
||||||
|
get { return _poolComponentsCapacity; }
|
||||||
|
}
|
||||||
|
public int PoolRecycledComponentsCapacity
|
||||||
|
{
|
||||||
|
get { return _poolRecycledComponentsCapacity; }
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
public sealed override void SetRaw(EcsWorld worldRaw)
|
||||||
|
{
|
||||||
|
Set((TWorld)worldRaw);
|
||||||
|
}
|
||||||
|
public void Set(TWorld world)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
}
|
||||||
|
public sealed override EcsWorld GetRaw()
|
||||||
|
{
|
||||||
|
return Get();
|
||||||
|
}
|
||||||
|
public sealed override EcsWorld GetCurrentWorldRaw()
|
||||||
|
{
|
||||||
|
return _world;
|
||||||
|
}
|
||||||
|
public TWorld Get()
|
||||||
|
{
|
||||||
|
if (_world == null || _world.IsDestroyed)
|
||||||
|
{
|
||||||
|
_world = BuildWorld();
|
||||||
|
OnWorldCreated(_world);
|
||||||
|
}
|
||||||
|
return _world;
|
||||||
|
}
|
||||||
|
protected static TProvider FindOrCreateSingleton<TProvider>() where TProvider : EcsWorldProvider<TWorld>
|
||||||
|
{
|
||||||
|
return FindOrCreateSingleton<TProvider>(typeof(TProvider).Name + "Singleton");
|
||||||
|
}
|
||||||
|
protected static TProvider FindOrCreateSingleton<TProvider>(string name) where TProvider : EcsWorldProvider<TWorld>
|
||||||
|
{
|
||||||
|
TProvider instance = Resources.Load<TProvider>(name);
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = CreateInstance<TProvider>();
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
if (AssetDatabase.IsValidFolder("Assets/Resources/") == false)
|
||||||
|
{
|
||||||
|
System.IO.Directory.CreateDirectory(Application.dataPath + "/Resources/");
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
}
|
||||||
|
AssetDatabase.CreateAsset(instance, "Assets/Resources/" + name + ".asset");
|
||||||
|
AssetDatabase.Refresh();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Events
|
||||||
|
protected virtual TWorld BuildWorld()
|
||||||
|
{
|
||||||
|
EcsWorldConfig config = new EcsWorldConfig(_entitiesCapacity, _groupCapacity, _poolsCapacity, _poolComponentsCapacity, _poolRecycledComponentsCapacity);
|
||||||
|
ConfigContainer configs = new ConfigContainer().Set(config);
|
||||||
|
return (TWorld)Activator.CreateInstance(typeof(TWorld), new object[] { configs, _worldID });
|
||||||
|
}
|
||||||
|
protected virtual void OnWorldCreated(TWorld world) { }
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/Connectors/EcsWorldProvider.cs.meta
Normal file
11
src/Connectors/EcsWorldProvider.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b041a062a2a5b2643bec37be4fad79f1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: a20b387d9272da846b2a1206bfb6d53a
|
guid: 2593ccf9a57f4f045a7e3bf6a839f3c3
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
58
src/Connectors/Editor/AutoEntityCreatorEditor.cs
Normal file
58
src/Connectors/Editor/AutoEntityCreatorEditor.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(AutoEntityCreator))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
internal class AutoEntityCreatorEditor : Editor
|
||||||
|
{
|
||||||
|
private AutoEntityCreator Target => (AutoEntityCreator)target;
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var iterator = serializedObject.GetIterator();
|
||||||
|
iterator.NextVisible(true);
|
||||||
|
while (iterator.NextVisible(false))
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(iterator, true);
|
||||||
|
}
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
DrawControlButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DrawControlButtons()
|
||||||
|
{
|
||||||
|
float height = EcsGUI.EntityBarHeight;
|
||||||
|
Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, height);
|
||||||
|
EditorGUI.DrawRect(rect, new Color(0f, 0f, 0f, 0.1f));
|
||||||
|
rect = RectUtility.AddPadding(rect, 2f, 0f);
|
||||||
|
var (left, autosetCascadeRect) = RectUtility.HorizontalSliceRight(rect, height);
|
||||||
|
var (_, autosetRect) = RectUtility.HorizontalSliceRight(left, height);
|
||||||
|
|
||||||
|
if (EcsGUI.AutosetCascadeButton(autosetCascadeRect))
|
||||||
|
{
|
||||||
|
foreach (AutoEntityCreator target in targets)
|
||||||
|
{
|
||||||
|
target.AutosetCascade_Editor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EcsGUI.AutosetButton(autosetRect))
|
||||||
|
{
|
||||||
|
foreach (AutoEntityCreator target in targets)
|
||||||
|
{
|
||||||
|
target.Autoset_Editor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Connectors/Editor/AutoEntityCreatorEditor.cs.meta
Normal file
11
src/Connectors/Editor/AutoEntityCreatorEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7e21fcbcfdafbb64d86bf965cd16c6b0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
126
src/Connectors/Editor/EcsEntityConnectEditor.cs
Normal file
126
src/Connectors/Editor/EcsEntityConnectEditor.cs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(EcsEntityConnect))]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
internal class EcsEntityConnectEditor : Editor
|
||||||
|
{
|
||||||
|
private bool _isInit = false;
|
||||||
|
private EcsEntityConnect Target => (EcsEntityConnect)target;
|
||||||
|
private bool IsMultipleTargets => targets.Length > 1;
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
if (_isInit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_isInit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
EcsEntityConnect[] targets = new EcsEntityConnect[this.targets.Length];
|
||||||
|
for (int i = 0; i < targets.Length; i++)
|
||||||
|
{
|
||||||
|
targets[i] = (EcsEntityConnect)this.targets[i];
|
||||||
|
}
|
||||||
|
DrawEntityInfo(targets);
|
||||||
|
|
||||||
|
DrawTemplates();
|
||||||
|
|
||||||
|
DrawControlButtons(targets);
|
||||||
|
DrawComponents(targets);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawEntityInfo(EcsEntityConnect[] targets)
|
||||||
|
{
|
||||||
|
bool isConnected = Target.Entity.TryUnpack(out int id, out short gen, out EcsWorld world);
|
||||||
|
EcsGUI.EntityStatus status = IsMultipleTargets ? EcsGUI.EntityStatus.Undefined : isConnected ? EcsGUI.EntityStatus.Alive : EcsGUI.EntityStatus.NotAlive;
|
||||||
|
EcsGUI.Layout.EntityBar(status, id, gen, world.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawTemplates()
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var iterator = serializedObject.GetIterator();
|
||||||
|
iterator.NextVisible(true);
|
||||||
|
while (iterator.NextVisible(false))
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(iterator, true);
|
||||||
|
}
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawControlButtons(EcsEntityConnect[] targets)
|
||||||
|
{
|
||||||
|
float height = EcsGUI.EntityBarHeight;
|
||||||
|
Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, height);
|
||||||
|
EditorGUI.DrawRect(rect, new Color(0f, 0f, 0f, 0.1f));
|
||||||
|
rect = RectUtility.AddPadding(rect, 2f, 0f);
|
||||||
|
var (_, buttonRect) = RectUtility.HorizontalSliceRight(rect, height);
|
||||||
|
if (EcsGUI.AutosetCascadeButton(buttonRect))
|
||||||
|
{
|
||||||
|
foreach (var target in targets)
|
||||||
|
{
|
||||||
|
target.AutosetCascade_Editor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buttonRect = RectUtility.Move(buttonRect, -height, 0);
|
||||||
|
if (EcsGUI.AutosetButton(buttonRect))
|
||||||
|
{
|
||||||
|
foreach (var target in targets)
|
||||||
|
{
|
||||||
|
target.Autoset_Editor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (new EditorGUI.DisabledScope(!Application.isPlaying))
|
||||||
|
{
|
||||||
|
buttonRect = RectUtility.Move(buttonRect, -height, 0);
|
||||||
|
if (EcsGUI.DelEntityButton(buttonRect))
|
||||||
|
{
|
||||||
|
foreach (var target in targets)
|
||||||
|
{
|
||||||
|
target.DeleteEntity_Editor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buttonRect = RectUtility.Move(buttonRect, -height, 0);
|
||||||
|
if (EcsGUI.UnlinkButton(buttonRect))
|
||||||
|
{
|
||||||
|
foreach (var target in targets)
|
||||||
|
{
|
||||||
|
target.UnlinkEntity_Editor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawComponents(EcsEntityConnect[] targets)
|
||||||
|
{
|
||||||
|
if (IsMultipleTargets)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < targets.Length; i++)
|
||||||
|
{
|
||||||
|
if (targets[i].IsConnected == true)
|
||||||
|
{
|
||||||
|
EditorGUILayout.HelpBox("Multiple component editing is not available.", MessageType.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Target.Entity.TryUnpack(out int entityID, out EcsWorld world))
|
||||||
|
{
|
||||||
|
EcsGUI.Layout.DrawRuntimeComponents(entityID, world);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Connectors/Editor/EcsEntityConnectEditor.cs.meta
Normal file
11
src/Connectors/Editor/EcsEntityConnectEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 846d3d07f90835048902b412bfac73aa
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
51
src/Connectors/Editor/EcsWorldProviderBaseEditor.cs
Normal file
51
src/Connectors/Editor/EcsWorldProviderBaseEditor.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(EcsWorldProviderBase), true)]
|
||||||
|
[CanEditMultipleObjects]
|
||||||
|
internal class EcsWorldProviderBaseEditor : Editor
|
||||||
|
{
|
||||||
|
private EcsWorldProviderBase Target => (EcsWorldProviderBase)target;
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
if (Target.IsEmpty)
|
||||||
|
{
|
||||||
|
var style = UnityEditorUtility.GetStyle(new Color32(255, 0, 75, 100));
|
||||||
|
GUILayout.Box("Is Empty", style, GUILayout.ExpandWidth(true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var style = UnityEditorUtility.GetStyle(new Color32(75, 255, 0, 100));
|
||||||
|
EcsWorld world = Target.GetRaw();
|
||||||
|
GUILayout.Box($"{world.GetMeta().Name} ( {world.id} )", style, GUILayout.ExpandWidth(true));
|
||||||
|
}
|
||||||
|
EcsGUI.Layout.DrawWorldBaseInfo(Target.GetCurrentWorldRaw());
|
||||||
|
|
||||||
|
|
||||||
|
base.OnInspectorGUI();
|
||||||
|
|
||||||
|
GUILayout.Space(10);
|
||||||
|
|
||||||
|
if (GUILayout.Button("Destroy"))
|
||||||
|
{
|
||||||
|
var w = Target.GetRaw();
|
||||||
|
if (w != null && w.IsDestroyed == false)
|
||||||
|
{
|
||||||
|
w.Destroy();
|
||||||
|
}
|
||||||
|
Target.SetRaw(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 2f);
|
||||||
|
Color c = Color.white;
|
||||||
|
c.a = 0.3f;
|
||||||
|
EditorGUI.DrawRect(r, c);
|
||||||
|
GUILayout.Space(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Connectors/Editor/EcsWorldProviderBaseEditor.cs.meta
Normal file
11
src/Connectors/Editor/EcsWorldProviderBaseEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1db1c2bb174625249a07a4cef8eff757
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -6,22 +6,32 @@ using UnityEditor;
|
|||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
[DebugColor(DebugColor.Cyan)]
|
[MetaColor(MetaColor.Cyan)]
|
||||||
public struct UnityGameObject : IEcsComponent
|
public readonly struct GameObjectConnect : IEcsComponent, IEcsComponentLifecycle<GameObjectConnect>
|
||||||
{
|
{
|
||||||
public GameObject gameObject;
|
public readonly EcsEntityConnect Connect;
|
||||||
public Transform transform;
|
public bool IsConnected
|
||||||
|
|
||||||
public string Name
|
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get => gameObject.name;
|
get { return Connect != null; }
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal GameObjectConnect(EcsEntityConnect connect)
|
||||||
|
{
|
||||||
|
Connect = connect;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnityGameObject(GameObject gameObject)
|
void IEcsComponentLifecycle<GameObjectConnect>.Enable(ref GameObjectConnect component)
|
||||||
{
|
{
|
||||||
this.gameObject = gameObject;
|
component = default;
|
||||||
transform = gameObject.transform;
|
}
|
||||||
|
void IEcsComponentLifecycle<GameObjectConnect>.Disable(ref GameObjectConnect component)
|
||||||
|
{
|
||||||
|
if (component.Connect != null)
|
||||||
|
{
|
||||||
|
component.Connect.Disconnect();
|
||||||
|
}
|
||||||
|
component = default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,19 +63,18 @@ namespace DCFApixels.DragonECS
|
|||||||
Diamond_Red,
|
Diamond_Red,
|
||||||
Diamond_Purple
|
Diamond_Purple
|
||||||
}
|
}
|
||||||
public static class GameObjectIconConsts
|
internal static class GameObjectIconConsts
|
||||||
{
|
{
|
||||||
public const int RAW_LABEL_ICON_LAST = (int)GameObjectIcon.Label_Purple;
|
public const int RAW_LABEL_ICON_LAST = (int)GameObjectIcon.Label_Purple;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GameObjectRefExt
|
public static class GameObjectRefExt
|
||||||
{
|
{
|
||||||
public static entlong NewEntityWithGameObject(this EcsWorld self, string name = "EcsEntity", GameObjectIcon icon = GameObjectIcon.NONE)
|
public static entlong NewEntityWithGameObject(this EcsWorld self, string name = "Entity", GameObjectIcon icon = GameObjectIcon.NONE)
|
||||||
{
|
{
|
||||||
entlong result = self.GetEntityLong(self.NewEmptyEntity());
|
entlong result = self.NewEntityLong();
|
||||||
GameObject newGameObject = new GameObject(name);
|
GameObject newGameObject = new GameObject(name);
|
||||||
newGameObject.AddComponent<EcsEntityConnect>().ConnectWith(result);
|
newGameObject.AddComponent<EcsEntityConnect>().ConnectWith(result, false);
|
||||||
// self.GetPool<UnityGameObject>().Add(result.id) =
|
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (icon != GameObjectIcon.NONE)
|
if (icon != GameObjectIcon.NONE)
|
||||||
{
|
{
|
||||||
@ -84,7 +93,6 @@ namespace DCFApixels.DragonECS
|
|||||||
EditorGUIUtility.SetIconForObject(newGameObject, (Texture2D)iconContent.image);
|
EditorGUIUtility.SetIconForObject(newGameObject, (Texture2D)iconContent.image);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
11
src/Connectors/GameObjectConnect.cs.meta
Normal file
11
src/Connectors/GameObjectConnect.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 398c78166eea90647a60b91b2b9a0f0b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
33
src/Debug/DebugModule.cs
Normal file
33
src/Debug/DebugModule.cs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public sealed class DebugModule : IEcsModule
|
||||||
|
{
|
||||||
|
public const string DEBUG_LAYER = nameof(DEBUG_LAYER);
|
||||||
|
public EcsWorld[] _worlds;
|
||||||
|
public DebugModule(params EcsWorld[] worlds)
|
||||||
|
{
|
||||||
|
_worlds = worlds;
|
||||||
|
}
|
||||||
|
void IEcsModule.Import(EcsPipeline.Builder b)
|
||||||
|
{
|
||||||
|
UnityDebugService.Activate();
|
||||||
|
b.Layers.Insert(EcsConsts.POST_END_LAYER, DEBUG_LAYER);
|
||||||
|
b.Add(new PipelineMonitorSystem(), DEBUG_LAYER);
|
||||||
|
foreach (var world in _worlds)
|
||||||
|
{
|
||||||
|
b.Add(new WorldMonitorSystem(world), DEBUG_LAYER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DebugModuleExt
|
||||||
|
{
|
||||||
|
public static EcsPipeline.Builder AddUnityDebug(this EcsPipeline.Builder self, params EcsWorld[] worlds)
|
||||||
|
{
|
||||||
|
self.AddModule(new DebugModule(worlds));
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,41 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Editors
|
|
||||||
{
|
|
||||||
[FilePath("DragonECS/DebugMonitorPrefs.prefs", FilePathAttribute.Location.ProjectFolder)]
|
|
||||||
public class DebugMonitorPrefs : ScriptableSingleton<DebugMonitorPrefs>
|
|
||||||
{
|
|
||||||
private bool _isShowInterfaces = false;
|
|
||||||
public bool IsShowInterfaces
|
|
||||||
{
|
|
||||||
get => _isShowInterfaces; set
|
|
||||||
{
|
|
||||||
_isShowInterfaces = value;
|
|
||||||
Save(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private bool _isShowHidden = false;
|
|
||||||
public bool IsShowHidden
|
|
||||||
{
|
|
||||||
get => _isShowHidden; set
|
|
||||||
{
|
|
||||||
_isShowHidden = value;
|
|
||||||
Save(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _poolsToggle = false;
|
|
||||||
public bool PoolsToggle
|
|
||||||
{
|
|
||||||
get => _poolsToggle; set
|
|
||||||
{
|
|
||||||
_poolsToggle = value;
|
|
||||||
Save(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
#if UNITY_EDITOR
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Editors
|
|
||||||
{
|
|
||||||
[InitializeOnLoad]
|
|
||||||
public static class EcsEditor
|
|
||||||
{
|
|
||||||
static EcsEditor()
|
|
||||||
{
|
|
||||||
colorBoxeStyles = new SparseArray<GUIStyle>();
|
|
||||||
}
|
|
||||||
private static SparseArray<GUIStyle> colorBoxeStyles = new SparseArray<GUIStyle>();
|
|
||||||
public static GUIStyle GetStyle(Color color, float alphaMultiplier)
|
|
||||||
{
|
|
||||||
color.a *= alphaMultiplier;
|
|
||||||
return GetStyle(color);
|
|
||||||
}
|
|
||||||
public static GUIStyle GetStyle(Color32 color32)
|
|
||||||
{
|
|
||||||
int colorCode = new Color32Union(color32).colorCode;
|
|
||||||
if (colorBoxeStyles.TryGetValue(colorCode, out GUIStyle style))
|
|
||||||
{
|
|
||||||
if (style == null || style.normal.background == null)
|
|
||||||
{
|
|
||||||
style = CreateStyle(color32, colorCode);
|
|
||||||
colorBoxeStyles[colorCode] = style;
|
|
||||||
}
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
|
|
||||||
style = CreateStyle(color32, colorCode);
|
|
||||||
colorBoxeStyles.Add(colorCode, style);
|
|
||||||
return style;
|
|
||||||
}
|
|
||||||
private static GUIStyle CreateStyle(Color32 color32, int colorCode)
|
|
||||||
{
|
|
||||||
GUIStyle result = new GUIStyle(GUI.skin.box);
|
|
||||||
Color componentColor = color32;
|
|
||||||
result.normal.background = CreateTexture(2, 2, componentColor);
|
|
||||||
result.active.background = CreateTexture(2, 2, componentColor);
|
|
||||||
result.hover.background = CreateTexture(2, 2, componentColor);
|
|
||||||
result.focused.background = CreateTexture(2, 2, componentColor);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
private static Texture2D CreateTexture(int width, int height, Color color)
|
|
||||||
{
|
|
||||||
var pixels = new Color[width * height];
|
|
||||||
for (var i = 0; i < pixels.Length; ++i)
|
|
||||||
pixels[i] = color;
|
|
||||||
|
|
||||||
var result = new Texture2D(width, height);
|
|
||||||
result.SetPixels(pixels);
|
|
||||||
result.Apply();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static string GetGenericName(Type type) => EcsDebugUtility.GetGenericTypeName(type);
|
|
||||||
|
|
||||||
public static string GetName<T>() => GetName(typeof(T));
|
|
||||||
public static string GetName(Type type) => EcsDebugUtility.GetName(type);
|
|
||||||
|
|
||||||
public static string GetDescription<T>() => GetDescription(typeof(T));
|
|
||||||
public static string GetDescription(Type type) => EcsDebugUtility.GetDescription(type);
|
|
||||||
|
|
||||||
#region Utils
|
|
||||||
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
|
|
||||||
private readonly ref struct Color32Union
|
|
||||||
{
|
|
||||||
[FieldOffset(0)]
|
|
||||||
public readonly int colorCode;
|
|
||||||
[FieldOffset(0)]
|
|
||||||
public readonly byte r;
|
|
||||||
[FieldOffset(1)]
|
|
||||||
public readonly byte g;
|
|
||||||
[FieldOffset(2)]
|
|
||||||
public readonly byte b;
|
|
||||||
[FieldOffset(3)]
|
|
||||||
public readonly byte a;
|
|
||||||
public Color32Union(byte r, byte g, byte b, byte a) : this()
|
|
||||||
{
|
|
||||||
this.r = r;
|
|
||||||
this.g = g;
|
|
||||||
this.b = b;
|
|
||||||
this.a = a;
|
|
||||||
}
|
|
||||||
public Color32Union(Color32 color) : this()
|
|
||||||
{
|
|
||||||
r = color.r;
|
|
||||||
g = color.g;
|
|
||||||
b = color.b;
|
|
||||||
a = color.a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
57
src/Debug/Editor/SettingsPrefs.cs
Normal file
57
src/Debug/Editor/SettingsPrefs.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[FilePath(EcsConsts.FRAMEWORK_NAME + "/" + nameof(SettingsPrefs) + ".prefs", FilePathAttribute.Location.ProjectFolder)]
|
||||||
|
public class SettingsPrefs : ScriptableSingleton<SettingsPrefs>
|
||||||
|
{
|
||||||
|
[SerializeField]
|
||||||
|
private bool _isShowInterfaces = false;
|
||||||
|
public bool IsShowInterfaces
|
||||||
|
{
|
||||||
|
get => _isShowInterfaces;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isShowInterfaces = value;
|
||||||
|
Save(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[SerializeField]
|
||||||
|
private bool _isShowHidden = false;
|
||||||
|
public bool IsShowHidden
|
||||||
|
{
|
||||||
|
get => _isShowHidden;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isShowHidden = value;
|
||||||
|
Save(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[SerializeField]
|
||||||
|
private bool _isShowRuntimeComponents = false;
|
||||||
|
public bool IsShowRuntimeComponents
|
||||||
|
{
|
||||||
|
get => _isShowRuntimeComponents;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isShowRuntimeComponents = value;
|
||||||
|
Save(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private bool _poolsToggle = false;
|
||||||
|
public bool PoolsToggle
|
||||||
|
{
|
||||||
|
get => _poolsToggle;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_poolsToggle = value;
|
||||||
|
Save(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
8
src/Debug/Monitors.meta
Normal file
8
src/Debug/Monitors.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8b7186fd57cbf9c42b4759c49920a688
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
src/Debug/Monitors/Editor.meta
Normal file
8
src/Debug/Monitors/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b1105324b07e39d449acceb24bdd7eb3
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
20
src/Debug/Monitors/Editor/EntityMonitorEditor.cs
Normal file
20
src/Debug/Monitors/Editor/EntityMonitorEditor.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(EntityMonitor))]
|
||||||
|
internal class EntityMonitorEditor : Editor
|
||||||
|
{
|
||||||
|
private EntityMonitor Target => (EntityMonitor)target;
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
bool isAlive = Target.Entity.TryUnpack(out int id, out short gen, out EcsWorld world);
|
||||||
|
EcsGUI.Layout.EntityBar(isAlive ? EcsGUI.EntityStatus.Alive : EcsGUI.EntityStatus.NotAlive, id, gen, world.id);
|
||||||
|
EcsGUI.Layout.DrawRuntimeComponents(Target.Entity, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Debug/Monitors/Editor/EntityMonitorEditor.cs.meta
Normal file
11
src/Debug/Monitors/Editor/EntityMonitorEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c5457dbe0f53566419d37e0ee9d9c13f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
139
src/Debug/Monitors/Editor/PipelineMonitorEditor.cs
Normal file
139
src/Debug/Monitors/Editor/PipelineMonitorEditor.cs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.RunnersCore;
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(PipelineMonitor))]
|
||||||
|
internal class PipelineMonitorEditor : Editor
|
||||||
|
{
|
||||||
|
private MetaColorAttribute _fakeDebugColorAttribute = new MetaColorAttribute(190, 190, 190);
|
||||||
|
private Type _debugColorAttributeType = typeof(MetaColorAttribute);
|
||||||
|
private GUIStyle _headerStyle;
|
||||||
|
private GUIStyle _interfacesStyle;
|
||||||
|
private Color _interfaceColor = new Color(0.96f, 1f, 0.16f);
|
||||||
|
|
||||||
|
private GUIStyle systemsListStyle;
|
||||||
|
|
||||||
|
private PipelineMonitor Target => (PipelineMonitor)target;
|
||||||
|
private bool IsShowInterfaces
|
||||||
|
{
|
||||||
|
get { return SettingsPrefs.instance.IsShowInterfaces; }
|
||||||
|
set { SettingsPrefs.instance.IsShowInterfaces = value; }
|
||||||
|
}
|
||||||
|
private bool IsShowHidden
|
||||||
|
{
|
||||||
|
get { return SettingsPrefs.instance.IsShowHidden; }
|
||||||
|
set { SettingsPrefs.instance.IsShowHidden = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
systemsListStyle = new GUIStyle(EditorStyles.miniLabel);
|
||||||
|
systemsListStyle.wordWrap = true;
|
||||||
|
|
||||||
|
if (Target.Pipeline == null || Target.Pipeline.IsDestoryed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_headerStyle == null)
|
||||||
|
{
|
||||||
|
_headerStyle = new GUIStyle(EditorStyles.boldLabel);
|
||||||
|
_interfacesStyle = new GUIStyle(EditorStyles.miniLabel);
|
||||||
|
_interfacesStyle.hover.textColor = _interfaceColor;
|
||||||
|
_interfacesStyle.focused.textColor = _interfaceColor;
|
||||||
|
_interfacesStyle.active.textColor = _interfaceColor;
|
||||||
|
_interfacesStyle.normal.textColor = _interfaceColor;
|
||||||
|
_interfacesStyle.wordWrap = true;
|
||||||
|
_headerStyle.fontSize = 28;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Label("[Systems]", _headerStyle);
|
||||||
|
|
||||||
|
IsShowInterfaces = EditorGUILayout.Toggle("Show Interfaces", IsShowInterfaces);
|
||||||
|
IsShowHidden = EditorGUILayout.Toggle("Show Hidden", IsShowHidden);
|
||||||
|
|
||||||
|
GUILayout.BeginVertical();
|
||||||
|
foreach (var item in Target.Pipeline.AllSystems)
|
||||||
|
{
|
||||||
|
DrawSystem(item);
|
||||||
|
}
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
|
||||||
|
GUILayout.Label("[Runners]", _headerStyle);
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f));
|
||||||
|
foreach (var item in Target.Pipeline.AllRunners)
|
||||||
|
{
|
||||||
|
if (item.Key.IsInterface == false)
|
||||||
|
{
|
||||||
|
DrawRunner(item.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
private void DrawSystem(IEcsProcess system)
|
||||||
|
{
|
||||||
|
if (system is SystemsLayerMarkerSystem markerSystem)
|
||||||
|
{
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f));
|
||||||
|
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
GUILayout.Label("<");
|
||||||
|
GUILayout.Label($"{markerSystem.name}", EditorStyles.boldLabel);
|
||||||
|
GUILayout.Label(">", GUILayout.ExpandWidth(false));
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type = system.GetType();
|
||||||
|
TypeMeta meta = type.ToMeta();
|
||||||
|
|
||||||
|
if (CheckIsHidden(meta))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = meta.Name;
|
||||||
|
Color color = meta.Color.ToUnityColor();
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(color, 0.2f));
|
||||||
|
if (IsShowInterfaces)
|
||||||
|
{
|
||||||
|
GUILayout.Label(string.Join(", ", type.GetInterfaces().Select(o => o.Name)), _interfacesStyle);
|
||||||
|
}
|
||||||
|
GUILayout.Label(name, EditorStyles.boldLabel);
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
private void DrawRunner(IEcsRunner runner)
|
||||||
|
{
|
||||||
|
Type type = runner.GetType();
|
||||||
|
TypeMeta meta = type.ToMeta();
|
||||||
|
|
||||||
|
if (CheckIsHidden(meta))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Color color = meta.Color.ToUnityColor();
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(color, 0.2f));
|
||||||
|
GUILayout.Label(meta.Name, EditorStyles.boldLabel);
|
||||||
|
GUILayout.Label(string.Join(", ", runner.ProcessRaw.Cast<object>().Select(o => o.GetType().Name)), systemsListStyle);
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
private bool CheckIsHidden(TypeMeta meta)
|
||||||
|
{
|
||||||
|
if (IsShowHidden)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return meta.IsHidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Debug/Monitors/Editor/PipelineMonitorEditor.cs.meta
Normal file
11
src/Debug/Monitors/Editor/PipelineMonitorEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 406298e83eb7a0b41b525c7e810c0c6f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
218
src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs
Normal file
218
src/Debug/Monitors/Editor/PipelineProcessesMonitorEditor.cs
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(PipelineProcessMonitor))]
|
||||||
|
internal class PipelineProcessesMonitorEditor : Editor
|
||||||
|
{
|
||||||
|
private static Type SYSTEM_INTERFACE_TYPE = typeof(IEcsProcess);
|
||||||
|
|
||||||
|
private bool _isInit = false;
|
||||||
|
private List<ProcessData> _processList = new List<ProcessData>();
|
||||||
|
private Dictionary<Type, int> _processeIndexes = new Dictionary<Type, int>();
|
||||||
|
private SystemData[] _systemsList;
|
||||||
|
|
||||||
|
private PipelineProcessMonitor Target => (PipelineProcessMonitor)target;
|
||||||
|
private bool IsShowInterfaces
|
||||||
|
{
|
||||||
|
get { return SettingsPrefs.instance.IsShowInterfaces; }
|
||||||
|
set { SettingsPrefs.instance.IsShowInterfaces = value; }
|
||||||
|
}
|
||||||
|
private bool IsShowHidden
|
||||||
|
{
|
||||||
|
get { return SettingsPrefs.instance.IsShowHidden; }
|
||||||
|
set { SettingsPrefs.instance.IsShowHidden = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
if (_isInit)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_processList.Clear();
|
||||||
|
_processeIndexes.Clear();
|
||||||
|
IEnumerable<IEcsProcess> fileretSystems = Target.Pipeline.AllSystems;
|
||||||
|
if (IsShowHidden)
|
||||||
|
{ fileretSystems = fileretSystems.Where(o => o is SystemsLayerMarkerSystem == false); }
|
||||||
|
else
|
||||||
|
{ fileretSystems = fileretSystems.Where(o => o.GetMeta().IsHidden == false); }
|
||||||
|
_systemsList = fileretSystems.Select(o => new SystemData(o.GetMeta(), o)).ToArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < _systemsList.Length; i++)
|
||||||
|
{
|
||||||
|
var system = _systemsList[i];
|
||||||
|
foreach (var interfaceType in system.meta.Type.GetInterfaces())
|
||||||
|
{
|
||||||
|
TypeMeta meta = interfaceType.ToMeta();
|
||||||
|
if (SYSTEM_INTERFACE_TYPE.IsAssignableFrom(interfaceType) && SYSTEM_INTERFACE_TYPE != interfaceType && (IsShowHidden || meta.IsHidden == false))
|
||||||
|
{
|
||||||
|
ProcessData data;
|
||||||
|
if (_processeIndexes.TryGetValue(interfaceType, out int index) == false)
|
||||||
|
{
|
||||||
|
index = _processList.Count;
|
||||||
|
_processeIndexes.Add(interfaceType, index);
|
||||||
|
|
||||||
|
data = new ProcessData();
|
||||||
|
data.meta = meta;
|
||||||
|
data.systemsBitMask = new BitMask(_systemsList.Length);
|
||||||
|
_processList.Add(data);
|
||||||
|
}
|
||||||
|
data = _processList[index];
|
||||||
|
data.systemsBitMask[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_isInit = true;
|
||||||
|
}
|
||||||
|
private Vector2 _position;
|
||||||
|
private Vector2 _cellsize = new Vector2(EditorGUIUtility.singleLineHeight, EditorGUIUtility.singleLineHeight);
|
||||||
|
private Vector2 _nameCellSize = new Vector2(200f, 200f);
|
||||||
|
|
||||||
|
private (TypeMeta system, TypeMeta process) _selectedPointMeta = default;
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
IsShowHidden = EditorGUILayout.Toggle("Show Hidden", IsShowHidden);
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
_isInit = false;
|
||||||
|
}
|
||||||
|
Init();
|
||||||
|
|
||||||
|
GUILayout.Label("", GUILayout.ExpandWidth(true), GUILayout.Height(400f));
|
||||||
|
Rect rect = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
|
rect.height = 400f;
|
||||||
|
|
||||||
|
|
||||||
|
Rect rectView = new Rect(0f, 0f, _nameCellSize.x + _cellsize.x * _processList.Count, _nameCellSize.y + _cellsize.y * _systemsList.Length);
|
||||||
|
EditorGUI.DrawRect(rect, new Color(0, 0, 0, 0.6f));
|
||||||
|
GUI.Button(rect, "", EditorStyles.helpBox);
|
||||||
|
|
||||||
|
_position = GUI.BeginScrollView(rect, _position, rectView, true, true);
|
||||||
|
|
||||||
|
Vector2 pivod = _nameCellSize;
|
||||||
|
rect = default;
|
||||||
|
rect.y = _nameCellSize.y;
|
||||||
|
rect.width = _nameCellSize.x;
|
||||||
|
rect.height = _cellsize.x;
|
||||||
|
rect.y -= _cellsize.y;
|
||||||
|
//processes line
|
||||||
|
for (int i = 0; i < _processList.Count; i++)
|
||||||
|
{
|
||||||
|
TypeMeta meta = _processList[i].meta;
|
||||||
|
Rect lineRect = rect;
|
||||||
|
lineRect.y = 0f;
|
||||||
|
lineRect.x = _nameCellSize.x + _cellsize.x * i;
|
||||||
|
lineRect.width = _cellsize.x;
|
||||||
|
lineRect.height = rectView.height;
|
||||||
|
lineRect = RectUtility.AddPadding(lineRect, 1, 0);
|
||||||
|
|
||||||
|
Color color = meta.Color.ToUnityColor();
|
||||||
|
color = NormalizeGridColor(i, color);
|
||||||
|
EditorGUI.DrawRect(lineRect, color);
|
||||||
|
|
||||||
|
if (EcsGUI.HitTest(lineRect))
|
||||||
|
{
|
||||||
|
GUI.Button(lineRect, "", EditorStyles.selectionRect);
|
||||||
|
_selectedPointMeta.process = meta;
|
||||||
|
}
|
||||||
|
GUIUtility.RotateAroundPivot(90, pivod);
|
||||||
|
GUI.Label(rect, UnityEditorUtility.GetLabel(meta.Name), EditorStyles.miniBoldLabel);
|
||||||
|
GUIUtility.RotateAroundPivot(-90, pivod);
|
||||||
|
|
||||||
|
pivod.x += _cellsize.x;
|
||||||
|
rect.x += _cellsize.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect = default;
|
||||||
|
rect.y = _nameCellSize.y;
|
||||||
|
rect.width = _nameCellSize.x;
|
||||||
|
rect.height = _cellsize.x;
|
||||||
|
//systems line
|
||||||
|
for (int i = 0; i < _systemsList.Length; i++)
|
||||||
|
{
|
||||||
|
TypeMeta meta = _systemsList[i].meta;
|
||||||
|
string name = meta.Name;
|
||||||
|
|
||||||
|
Rect lineRect = rect;
|
||||||
|
lineRect.width = rectView.width;
|
||||||
|
lineRect = RectUtility.AddPadding(lineRect, 0, 1);
|
||||||
|
|
||||||
|
Color color = meta.Color.ToUnityColor();
|
||||||
|
color = NormalizeGridColor(i, color);
|
||||||
|
EditorGUI.DrawRect(lineRect, color);
|
||||||
|
|
||||||
|
if (EcsGUI.HitTest(lineRect))
|
||||||
|
{
|
||||||
|
GUI.Button(lineRect, "", EditorStyles.selectionRect);
|
||||||
|
_selectedPointMeta.system = meta;
|
||||||
|
}
|
||||||
|
GUI.Label(rect, UnityEditorUtility.GetLabel(name, i + " " + name), EditorStyles.miniBoldLabel);
|
||||||
|
rect.y += _cellsize.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture checkIcon = EditorGUIUtility.IconContent("DotFill").image;
|
||||||
|
|
||||||
|
//matrix
|
||||||
|
for (int x = 0; x < _processList.Count; x++)
|
||||||
|
{
|
||||||
|
var process = _processList[x];
|
||||||
|
for (int y = 0; y < _systemsList.Length; y++)
|
||||||
|
{
|
||||||
|
rect = new Rect(x * _cellsize.x + _nameCellSize.x, y * _cellsize.y + _nameCellSize.y, _cellsize.x, _cellsize.y);
|
||||||
|
bool flag = process.systemsBitMask[y];
|
||||||
|
if (flag)
|
||||||
|
{
|
||||||
|
GUI.Label(rect, UnityEditorUtility.GetLabel(checkIcon));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUI.EndScrollView();
|
||||||
|
|
||||||
|
Rect r = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, EditorGUIUtility.singleLineHeight);
|
||||||
|
if (_selectedPointMeta.process != null && _selectedPointMeta.system != null)
|
||||||
|
{
|
||||||
|
GUI.Label(r, $"{_selectedPointMeta.process.Name}-{_selectedPointMeta.system.Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Color NormalizeGridColor(int index, Color color)
|
||||||
|
{
|
||||||
|
if (index % 2 == 1)
|
||||||
|
{
|
||||||
|
color = color / 1.4f;
|
||||||
|
color.a = 0.3f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color.a = 0.5f;
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
private class SystemData
|
||||||
|
{
|
||||||
|
public TypeMeta meta;
|
||||||
|
public IEcsProcess system;
|
||||||
|
public SystemData(TypeMeta meta, IEcsProcess system)
|
||||||
|
{
|
||||||
|
this.meta = meta;
|
||||||
|
this.system = system;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private class ProcessData
|
||||||
|
{
|
||||||
|
public TypeMeta meta;
|
||||||
|
public BitMask systemsBitMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d3cd5a052acb5c4469a9802390bb532a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
18
src/Debug/Monitors/Editor/WorldMonitorEditor.cs
Normal file
18
src/Debug/Monitors/Editor/WorldMonitorEditor.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[CustomEditor(typeof(WorldMonitor))]
|
||||||
|
internal class WorldMonitorEditor : Editor
|
||||||
|
{
|
||||||
|
private WorldMonitor Target => (WorldMonitor)target;
|
||||||
|
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
EcsGUI.Layout.DrawWorldBaseInfo(Target.World);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Debug/Monitors/Editor/WorldMonitorEditor.cs.meta
Normal file
11
src/Debug/Monitors/Editor/WorldMonitorEditor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7aadf8c836c97694186e4b3aeb01fcce
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
19
src/Debug/Monitors/EntityMonitor.cs
Normal file
19
src/Debug/Monitors/EntityMonitor.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Internal
|
||||||
|
{
|
||||||
|
[MetaTags(MetaTags.HIDDEN)]
|
||||||
|
[MetaColor(MetaColor.Gray)]
|
||||||
|
internal class EntityMonitor : MonoBehaviour
|
||||||
|
{
|
||||||
|
private entlong _entity;
|
||||||
|
public entlong Entity
|
||||||
|
{
|
||||||
|
get { return _entity; }
|
||||||
|
}
|
||||||
|
public void Set(entlong entity)
|
||||||
|
{
|
||||||
|
_entity = entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/Debug/Monitors/EntityMonitor.cs.meta
Normal file
11
src/Debug/Monitors/EntityMonitor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b3c51f9f4aa13e74fbb4339f8c1746d4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
48
src/Debug/Monitors/PipelineMonitor.cs
Normal file
48
src/Debug/Monitors/PipelineMonitor.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using DCFApixels.DragonECS.Unity.Editors;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Internal
|
||||||
|
{
|
||||||
|
[MetaTags(MetaTags.HIDDEN)]
|
||||||
|
[MetaColor(MetaColor.Gray)]
|
||||||
|
internal class PipelineMonitor : MonoBehaviour
|
||||||
|
{
|
||||||
|
private EcsPipeline _pipeline;
|
||||||
|
public EcsPipeline Pipeline
|
||||||
|
{
|
||||||
|
get { return _pipeline; }
|
||||||
|
}
|
||||||
|
public void Set(EcsPipeline pipeline)
|
||||||
|
{
|
||||||
|
_pipeline = pipeline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MetaTags(MetaTags.HIDDEN)]
|
||||||
|
[MetaColor(MetaColor.Gray)]
|
||||||
|
internal class PipelineMonitorSystem : IEcsInit, IEcsPipelineMember, IEcsDestroy
|
||||||
|
{
|
||||||
|
private PipelineMonitor _monitor;
|
||||||
|
private PipelineProcessMonitor _processesMonitor;
|
||||||
|
public EcsPipeline Pipeline { get; set; }
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
TypeMeta meta = typeof(EcsPipeline).ToMeta();
|
||||||
|
_monitor = new GameObject($"{UnityEditorUtility.TransformToUpperName(meta.Name)}").AddComponent<PipelineMonitor>();
|
||||||
|
UnityEngine.Object.DontDestroyOnLoad(_monitor);
|
||||||
|
_monitor.Set(Pipeline);
|
||||||
|
_monitor.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
_processesMonitor = new GameObject($"PROCESS_MATRIX").AddComponent<PipelineProcessMonitor>();
|
||||||
|
_processesMonitor.transform.SetParent(_monitor.transform);
|
||||||
|
_processesMonitor.Set(Pipeline);
|
||||||
|
_processesMonitor.gameObject.SetActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
UnityEngine.Object.Destroy(_monitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/Debug/Monitors/PipelineMonitor.cs.meta
Normal file
11
src/Debug/Monitors/PipelineMonitor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 03154a226ad86e24ebfa4faf43da8310
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
19
src/Debug/Monitors/PipelineProcessMonitor.cs
Normal file
19
src/Debug/Monitors/PipelineProcessMonitor.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[MetaTags(MetaTags.HIDDEN)]
|
||||||
|
[MetaColor(MetaColor.Gray)]
|
||||||
|
internal class PipelineProcessMonitor : MonoBehaviour
|
||||||
|
{
|
||||||
|
private EcsPipeline _pipeline;
|
||||||
|
public EcsPipeline Pipeline
|
||||||
|
{
|
||||||
|
get { return _pipeline; }
|
||||||
|
}
|
||||||
|
public void Set(EcsPipeline pipeline)
|
||||||
|
{
|
||||||
|
_pipeline = pipeline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/Debug/Monitors/PipelineProcessMonitor.cs.meta
Normal file
11
src/Debug/Monitors/PipelineProcessMonitor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2e20707e619a5b742aeb26e3eff3a9c4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
108
src/Debug/Monitors/WorldMonitor.cs
Normal file
108
src/Debug/Monitors/WorldMonitor.cs
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
using DCFApixels.DragonECS.Unity.Editors;
|
||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Internal
|
||||||
|
{
|
||||||
|
[MetaTags(MetaTags.HIDDEN)]
|
||||||
|
[MetaColor(MetaColor.Gray)]
|
||||||
|
internal class WorldMonitor : MonoBehaviour
|
||||||
|
{
|
||||||
|
private EcsWorld _world;
|
||||||
|
public EcsWorld World
|
||||||
|
{
|
||||||
|
get { return _world; }
|
||||||
|
}
|
||||||
|
public void Set(EcsWorld world)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MetaTags(MetaTags.HIDDEN)]
|
||||||
|
[MetaColor(MetaColor.Gray)]
|
||||||
|
internal class WorldMonitorSystem : IEcsInit, IEcsWorldEventListener, IEcsEntityEventListener
|
||||||
|
{
|
||||||
|
private EcsWorld _world;
|
||||||
|
private WorldMonitor _monitor;
|
||||||
|
private Transform _entityMonitorsPoolRoot;
|
||||||
|
private EntityMonitor[] _entityMonitors;
|
||||||
|
public EcsWorld World
|
||||||
|
{
|
||||||
|
get { return _world; }
|
||||||
|
}
|
||||||
|
public WorldMonitorSystem(EcsWorld world)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
_entityMonitors = new EntityMonitor[_world.Capacity];
|
||||||
|
|
||||||
|
_world.AddListener(entityEventListener: this);
|
||||||
|
_world.AddListener(worldEventListener: this);
|
||||||
|
}
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
TypeMeta meta = _world.GetMeta();
|
||||||
|
_monitor = new GameObject($"{UnityEditorUtility.TransformToUpperName(meta.Name)} ( {_world.id} )").AddComponent<WorldMonitor>();
|
||||||
|
UnityEngine.Object.DontDestroyOnLoad(_monitor);
|
||||||
|
_monitor.Set(_world);
|
||||||
|
_monitor.gameObject.SetActive(false);
|
||||||
|
|
||||||
|
_entityMonitorsPoolRoot = new GameObject("__POOL").transform;
|
||||||
|
_entityMonitorsPoolRoot.SetParent(_monitor.transform);
|
||||||
|
|
||||||
|
foreach (var e in _world.Entities)
|
||||||
|
{
|
||||||
|
InitNewEntity(e, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IEcsWorldEventListener.OnWorldResize(int newSize)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _entityMonitors, newSize);
|
||||||
|
}
|
||||||
|
void IEcsWorldEventListener.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||||
|
void IEcsWorldEventListener.OnWorldDestroy()
|
||||||
|
{
|
||||||
|
UnityEngine.Object.Destroy(_monitor);
|
||||||
|
UnityEngine.Object.Destroy(_entityMonitorsPoolRoot);
|
||||||
|
_monitor = null;
|
||||||
|
_entityMonitorsPoolRoot = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IEcsEntityEventListener.OnNewEntity(int entityID)
|
||||||
|
{
|
||||||
|
InitNewEntity(entityID, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitNewEntity(int entityID, bool check)
|
||||||
|
{
|
||||||
|
if (_monitor == null) { return; }
|
||||||
|
ref var _entityMonitorRef = ref _entityMonitors[entityID];
|
||||||
|
if (_entityMonitorRef == null)
|
||||||
|
{
|
||||||
|
_entityMonitorRef = new GameObject($"ENTITY ( {entityID} )").AddComponent<EntityMonitor>();
|
||||||
|
}
|
||||||
|
if (check && _entityMonitorRef.Entity.IsAlive)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
_entityMonitorRef.Set(_world.GetEntityLong(entityID));
|
||||||
|
_entityMonitorRef.transform.SetParent(_monitor.transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IEcsEntityEventListener.OnDelEntity(int entityID)
|
||||||
|
{
|
||||||
|
if (_monitor == null) { return; }
|
||||||
|
ref var _entityMonitorRef = ref _entityMonitors[entityID];
|
||||||
|
if (_entityMonitorRef != null)
|
||||||
|
{
|
||||||
|
if (_entityMonitorRef.Entity.IsAlive)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
_entityMonitorRef.transform.SetParent(_entityMonitorsPoolRoot.transform);
|
||||||
|
_entityMonitorRef.Set(_world.GetEntityLong(entityID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/Debug/Monitors/WorldMonitor.cs.meta
Normal file
11
src/Debug/Monitors/WorldMonitor.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3d65916dbb4c8f74cb5239c5bbf7ba31
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,22 +0,0 @@
|
|||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public sealed class DebugModule : IEcsModule
|
|
||||||
{
|
|
||||||
public const string DEBUG_LAYER = nameof(DEBUG_LAYER);
|
|
||||||
public EcsWorld[] _worlds;
|
|
||||||
public DebugModule(params EcsWorld[] worlds)
|
|
||||||
{
|
|
||||||
_worlds = worlds;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IEcsModule.ImportSystems(EcsPipeline.Builder b)
|
|
||||||
{
|
|
||||||
b.Layers.Insert(EcsConsts.POST_END_LAYER, DEBUG_LAYER);
|
|
||||||
b.Add(new PipelineDebugSystem(), DEBUG_LAYER);
|
|
||||||
foreach (var world in _worlds)
|
|
||||||
{
|
|
||||||
b.Add(new WorldDebugSystem(world), DEBUG_LAYER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Unity.Debug
|
|
||||||
{
|
|
||||||
public class DebugMonitorBase : MonoBehaviour
|
|
||||||
{
|
|
||||||
internal string monitorName;
|
|
||||||
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
DontDestroyOnLoad(this.gameObject);
|
|
||||||
gameObject.SetActive(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,337 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Unity.Debug;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
[DebugHide, DebugColor(DebugColor.Gray)]
|
|
||||||
public class PipelineDebugSystem : IEcsPreInitProcess
|
|
||||||
{
|
|
||||||
private string _monitorName;
|
|
||||||
public PipelineDebugSystem(string monitorName = "Pipeline")
|
|
||||||
{
|
|
||||||
_monitorName = monitorName;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IEcsPreInitProcess.PreInit(EcsPipeline pipeline)
|
|
||||||
{
|
|
||||||
PipelineDebugMonitor monitor = new GameObject(EcsConsts.DEBUG_PREFIX + _monitorName).AddComponent<PipelineDebugMonitor>();
|
|
||||||
monitor.source = this;
|
|
||||||
monitor.pipeline = pipeline;
|
|
||||||
monitor.monitorName = _monitorName;
|
|
||||||
|
|
||||||
PipelineProcessesDebugMonitor processesMonitor = new GameObject(EcsConsts.DEBUG_PREFIX + "Processes Matrix").AddComponent<PipelineProcessesDebugMonitor>();
|
|
||||||
processesMonitor.transform.parent = monitor.transform;
|
|
||||||
processesMonitor.source = this;
|
|
||||||
processesMonitor.pipeline = pipeline;
|
|
||||||
processesMonitor.monitorName = "Processes Matrix";
|
|
||||||
|
|
||||||
//foreach (var item in pipeline.AllSystems) //Вырезано пока не сделаю TODO в SystemDebugMonitor
|
|
||||||
//{
|
|
||||||
// DebugNameAttribute debugName = item.GetType().GetCustomAttribute<DebugNameAttribute>();
|
|
||||||
// string name = debugName == null ? item.GetType().Name : debugName.name;
|
|
||||||
// SystemDebugMonitor.CreateMonitor(monitor.transform, item, name);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PipelineDebugMonitor : DebugMonitorBase
|
|
||||||
{
|
|
||||||
internal PipelineDebugSystem source;
|
|
||||||
internal EcsPipeline pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PipelineProcessesDebugMonitor : DebugMonitorBase
|
|
||||||
{
|
|
||||||
internal PipelineDebugSystem source;
|
|
||||||
internal EcsPipeline pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
namespace Editors
|
|
||||||
{
|
|
||||||
using DCFApixels.DragonECS.Internal;
|
|
||||||
using DCFApixels.DragonECS.RunnersCore;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
[CustomEditor(typeof(PipelineDebugMonitor))]
|
|
||||||
public class PipelineDebugMonitorEditor : Editor
|
|
||||||
{
|
|
||||||
private DebugColorAttribute _fakeDebugColorAttribute = new DebugColorAttribute(190, 190, 190);
|
|
||||||
private Type _debugColorAttributeType = typeof(DebugColorAttribute);
|
|
||||||
private GUIStyle _headerStyle;
|
|
||||||
private GUIStyle _interfacesStyle;
|
|
||||||
private Color _interfaceColor = new Color(0.96f, 1f, 0.16f);
|
|
||||||
private PipelineDebugMonitor Target => (PipelineDebugMonitor)target;
|
|
||||||
|
|
||||||
|
|
||||||
private GUIStyle systemsListStyle;
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
systemsListStyle = new GUIStyle(EditorStyles.miniLabel);
|
|
||||||
systemsListStyle.wordWrap = true;
|
|
||||||
|
|
||||||
if (Target.source == null)
|
|
||||||
return;
|
|
||||||
if (_headerStyle == null)
|
|
||||||
{
|
|
||||||
_headerStyle = new GUIStyle(EditorStyles.boldLabel);
|
|
||||||
_interfacesStyle = new GUIStyle(EditorStyles.miniLabel);
|
|
||||||
_interfacesStyle.hover.textColor = _interfaceColor;
|
|
||||||
_interfacesStyle.focused.textColor = _interfaceColor;
|
|
||||||
_interfacesStyle.active.textColor = _interfaceColor;
|
|
||||||
_interfacesStyle.normal.textColor = _interfaceColor;
|
|
||||||
_interfacesStyle.wordWrap = true;
|
|
||||||
_headerStyle.fontSize = 28;
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.Label("[Systems]", _headerStyle);
|
|
||||||
|
|
||||||
DebugMonitorPrefs.instance.IsShowInterfaces = EditorGUILayout.Toggle("Show Interfaces", DebugMonitorPrefs.instance.IsShowInterfaces);
|
|
||||||
DebugMonitorPrefs.instance.IsShowHidden = EditorGUILayout.Toggle("Show Hidden", DebugMonitorPrefs.instance.IsShowHidden);
|
|
||||||
|
|
||||||
GUILayout.BeginVertical();
|
|
||||||
foreach (var item in Target.pipeline.AllSystems)
|
|
||||||
{
|
|
||||||
DrawSystem(item);
|
|
||||||
}
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
|
|
||||||
|
|
||||||
GUILayout.Label("[Runners]", _headerStyle);
|
|
||||||
|
|
||||||
GUILayout.BeginVertical(EcsEditor.GetStyle(Color.black, 0.2f));
|
|
||||||
foreach (var item in Target.pipeline.AllRunners)
|
|
||||||
{
|
|
||||||
DrawRunner(item.Value);
|
|
||||||
}
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSystem(IEcsSystem system)
|
|
||||||
{
|
|
||||||
if (system is SystemsLayerMarkerSystem markerSystem)
|
|
||||||
{
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
GUILayout.BeginVertical(EcsEditor.GetStyle(Color.black, 0.2f));
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal();
|
|
||||||
GUILayout.Label("<");
|
|
||||||
GUILayout.Label($"{markerSystem.name}", EditorStyles.boldLabel);
|
|
||||||
GUILayout.Label(">", GUILayout.ExpandWidth(false));
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type = system.GetType();
|
|
||||||
|
|
||||||
if (CheckIsHidden(type))
|
|
||||||
return;
|
|
||||||
|
|
||||||
string name = EcsEditor.GetGenericName(type);
|
|
||||||
Color color = (GetAttribute<DebugColorAttribute>(type) ?? _fakeDebugColorAttribute).GetUnityColor();
|
|
||||||
|
|
||||||
GUILayout.BeginVertical(EcsEditor.GetStyle(color, 0.2f));
|
|
||||||
if (DebugMonitorPrefs.instance.IsShowInterfaces)
|
|
||||||
{
|
|
||||||
GUILayout.Label(string.Join(", ", type.GetInterfaces().Select(o => o.Name)), _interfacesStyle);
|
|
||||||
}
|
|
||||||
GUILayout.Label(name, EditorStyles.boldLabel);
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawRunner(IEcsRunner runner)
|
|
||||||
{
|
|
||||||
Type type = runner.GetType();
|
|
||||||
if (CheckIsHidden(type))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Color color = (GetAttribute<DebugColorAttribute>(type) ?? _fakeDebugColorAttribute).GetUnityColor();
|
|
||||||
GUILayout.BeginVertical(EcsEditor.GetStyle(color, 0.2f));
|
|
||||||
GUILayout.Label(EcsEditor.GetGenericName(type), EditorStyles.boldLabel);
|
|
||||||
GUILayout.Label(string.Join(", ", runner.Targets.Cast<object>().Select(o => o.GetType().Name)), systemsListStyle);
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
}
|
|
||||||
|
|
||||||
private TAttribute GetAttribute<TAttribute>(Type target) where TAttribute : Attribute
|
|
||||||
{
|
|
||||||
var result = target.GetCustomAttributes(_debugColorAttributeType, false);
|
|
||||||
if (result.Length > 0)
|
|
||||||
return (TAttribute)result[0];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool CheckIsHidden(Type target)
|
|
||||||
{
|
|
||||||
if (DebugMonitorPrefs.instance.IsShowHidden)
|
|
||||||
return false;
|
|
||||||
return target.GetCustomAttribute<DebugHideAttribute>() != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CustomEditor(typeof(PipelineProcessesDebugMonitor))]
|
|
||||||
public class PipelineProcessesDebugMonitorEditor : Editor
|
|
||||||
{
|
|
||||||
private bool _isInit = false;
|
|
||||||
private List<ProcessData> _processesList = new List<ProcessData>();
|
|
||||||
private Dictionary<Type, int> _processeIndexes = new Dictionary<Type, int>();
|
|
||||||
|
|
||||||
private PipelineProcessesDebugMonitor Target => (PipelineProcessesDebugMonitor)target;
|
|
||||||
private Type systemInterfaceType = typeof(IEcsSystem);
|
|
||||||
|
|
||||||
private IEcsSystem[] _systems;
|
|
||||||
private void Init()
|
|
||||||
{
|
|
||||||
if (_isInit)
|
|
||||||
return;
|
|
||||||
bool showHidden = DebugMonitorPrefs.instance.IsShowHidden;
|
|
||||||
_processesList.Clear();
|
|
||||||
_processeIndexes.Clear();
|
|
||||||
if (showHidden)
|
|
||||||
_systems = Target.pipeline.AllSystems.Where(o => o is SystemsLayerMarkerSystem == false).ToArray();
|
|
||||||
else
|
|
||||||
_systems = Target.pipeline.AllSystems.Where(o => o.GetType().GetCustomAttribute<DebugHideAttribute>() == null).ToArray();
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
foreach (var system in _systems)
|
|
||||||
{
|
|
||||||
foreach (var intr in system.GetType().GetInterfaces())
|
|
||||||
{
|
|
||||||
if(systemInterfaceType.IsAssignableFrom(intr) && systemInterfaceType != intr && (showHidden || intr.GetCustomAttribute<DebugHideAttribute>() == null))
|
|
||||||
{
|
|
||||||
ProcessData data;
|
|
||||||
if (!_processeIndexes.TryGetValue(intr, out int index))
|
|
||||||
{
|
|
||||||
index = _processesList.Count;
|
|
||||||
_processeIndexes.Add(intr, index);
|
|
||||||
|
|
||||||
data = new ProcessData();
|
|
||||||
_processesList.Add(data);
|
|
||||||
|
|
||||||
data.name = EcsEditor.GetGenericName(intr);
|
|
||||||
data.interfaceType = intr;
|
|
||||||
data.systemsBitMask = new BitMask(_systems.Length);
|
|
||||||
}
|
|
||||||
data = _processesList[index];
|
|
||||||
data.systemsBitMask[i] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isInit = true;
|
|
||||||
}
|
|
||||||
private Vector2 _position;
|
|
||||||
private Vector2 _cellsize = new Vector2(EditorGUIUtility.singleLineHeight, EditorGUIUtility.singleLineHeight);
|
|
||||||
private Vector2 _nameCellSize = new Vector2(200f, 200f);
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
DebugMonitorPrefs.instance.IsShowHidden = EditorGUILayout.Toggle("Show Hidden", DebugMonitorPrefs.instance.IsShowHidden);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
_isInit = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Init();
|
|
||||||
|
|
||||||
Rect rect;
|
|
||||||
Rect lineRect;
|
|
||||||
GUILayout.Label("", GUILayout.ExpandWidth(true), GUILayout.Height(400f));
|
|
||||||
rect = GUILayoutUtility.GetLastRect();
|
|
||||||
|
|
||||||
rect.height = 400f;
|
|
||||||
|
|
||||||
|
|
||||||
Rect rectView = new Rect(0f, 0f, _nameCellSize.x + _cellsize.x * _processesList.Count, _nameCellSize.y + _cellsize.y * _systems.Length);
|
|
||||||
_position = GUI.BeginScrollView(rect, _position, rectView, true, true);
|
|
||||||
|
|
||||||
List<string> systeNames = new List<string>();
|
|
||||||
|
|
||||||
var blackStyle = EcsEditor.GetStyle(Color.black, 0.04f);
|
|
||||||
var whiteStyle = EcsEditor.GetStyle(Color.white, 0.04f);
|
|
||||||
GUIContent label = new GUIContent();
|
|
||||||
|
|
||||||
|
|
||||||
Vector2 pivod = _nameCellSize;
|
|
||||||
rect = new Rect();
|
|
||||||
rect.y = _nameCellSize.y;
|
|
||||||
rect.width = _nameCellSize.x;
|
|
||||||
rect.height = _cellsize.x;
|
|
||||||
rect.y -= _cellsize.y;
|
|
||||||
for (int i = 0; i < _processesList.Count; i++)
|
|
||||||
{
|
|
||||||
lineRect = rect;
|
|
||||||
lineRect.y = 0f;
|
|
||||||
lineRect.x = _nameCellSize.x + _cellsize.x * i;
|
|
||||||
lineRect.width = _cellsize.x;
|
|
||||||
lineRect.height = rectView.height;
|
|
||||||
GUI.Label(lineRect, "", i % 2 == 1 ? whiteStyle : blackStyle);
|
|
||||||
|
|
||||||
GUIUtility.RotateAroundPivot(90, pivod);
|
|
||||||
//GUIContent label = new GUIContent(_processesList[i].name, "." + _processesList[i].name);
|
|
||||||
label.text = _processesList[i].name;
|
|
||||||
label.tooltip = "." + _processesList[i].name;
|
|
||||||
GUI.Label(rect, label, EditorStyles.miniBoldLabel);
|
|
||||||
GUIUtility.RotateAroundPivot(-90, pivod);
|
|
||||||
|
|
||||||
pivod.x += _cellsize.x;
|
|
||||||
rect.x += _cellsize.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
//GUIUtility.RotateAroundPivot(-90, _nameCellSize);
|
|
||||||
rect = new Rect();
|
|
||||||
rect.y = _nameCellSize.y;
|
|
||||||
rect.width = _nameCellSize.x;
|
|
||||||
rect.height = _cellsize.x;
|
|
||||||
for (int i = 0; i < _systems.Length; i++)
|
|
||||||
{
|
|
||||||
string name = EcsEditor.GetGenericName(_systems[i].GetType());
|
|
||||||
systeNames.Add(name);
|
|
||||||
|
|
||||||
lineRect = rect;
|
|
||||||
lineRect.width = rectView.width;
|
|
||||||
GUI.Label(lineRect, "", i % 2 == 1 ? whiteStyle : blackStyle);
|
|
||||||
|
|
||||||
// GUIContent label = new GUIContent(name, i + " " + name);
|
|
||||||
label.text = name;
|
|
||||||
label.tooltip = i + " " + name;
|
|
||||||
GUI.Label(rect, label, EditorStyles.miniBoldLabel);
|
|
||||||
rect.y += _cellsize.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x < _processesList.Count; x++)
|
|
||||||
{
|
|
||||||
var process = _processesList[x];
|
|
||||||
for (int y = 0; y < _systems.Length; y++)
|
|
||||||
{
|
|
||||||
string systemName = systeNames[x];
|
|
||||||
rect = new Rect(x * _cellsize.x + _nameCellSize.x, y * _cellsize.y + _nameCellSize.y, _cellsize.x, _cellsize.y);
|
|
||||||
bool flag = process.systemsBitMask[y];
|
|
||||||
string labeltext = flag ? "^" : " ";
|
|
||||||
label.text = labeltext;
|
|
||||||
label.tooltip = $"{process.name}-{systemName}";
|
|
||||||
GUI.Label(rect, label);
|
|
||||||
//GUI.Label(rect, lable, flag ? whiteStyle : blackStyle);
|
|
||||||
// GUI.Label(rect, label, EditorStyles.helpBox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GUI.EndScrollView();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ProcessData
|
|
||||||
{
|
|
||||||
public Type interfaceType;
|
|
||||||
public string name;
|
|
||||||
public BitMask systemsBitMask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@ -1,182 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Unity.Debug;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
[DebugHide, DebugColor(DebugColor.Gray)]
|
|
||||||
public class WorldDebugSystem : IEcsRunProcess
|
|
||||||
{
|
|
||||||
private string _monitorName;
|
|
||||||
private EcsWorld _ecsWorld;
|
|
||||||
|
|
||||||
public WorldDebugSystem(EcsWorld ecsWorld, string monitorName = null)
|
|
||||||
{
|
|
||||||
_monitorName = monitorName;
|
|
||||||
if (string.IsNullOrEmpty(_monitorName)) _monitorName = ecsWorld.GetType().Name;
|
|
||||||
_ecsWorld = ecsWorld;
|
|
||||||
WorldDebugMonitor monitor = new GameObject(EcsConsts.DEBUG_PREFIX + _monitorName).AddComponent<WorldDebugMonitor>();
|
|
||||||
WorldPoolsMonitor poolsmonitor = new GameObject(EcsConsts.DEBUG_PREFIX + "Pools").AddComponent<WorldPoolsMonitor>();
|
|
||||||
poolsmonitor.transform.SetParent(monitor.transform);
|
|
||||||
|
|
||||||
monitor.source = this;
|
|
||||||
monitor.world = _ecsWorld;
|
|
||||||
monitor.monitorName = _monitorName;
|
|
||||||
|
|
||||||
poolsmonitor.source = this;
|
|
||||||
poolsmonitor.world = _ecsWorld;
|
|
||||||
poolsmonitor.monitorName = "pools";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Run(EcsPipeline pipeline)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class WorldDebugMonitor : DebugMonitorBase
|
|
||||||
{
|
|
||||||
internal WorldDebugSystem source;
|
|
||||||
internal EcsWorld world;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
namespace Editors
|
|
||||||
{
|
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
[CustomEditor(typeof(WorldDebugMonitor))]
|
|
||||||
public class WorldDebugMonitorEditor : Editor
|
|
||||||
{
|
|
||||||
private WorldDebugMonitor Target => (WorldDebugMonitor)target;
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
GUILayout.Label($"Size: {Target.world.Capacity}");
|
|
||||||
GUILayout.Label($"Total entities: {Target.world.Count}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public class WorldPoolsMonitor : DebugMonitorBase
|
|
||||||
{
|
|
||||||
internal WorldDebugSystem source;
|
|
||||||
internal EcsWorld world;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
namespace Editors
|
|
||||||
{
|
|
||||||
using System.Linq;
|
|
||||||
using UnityEditor;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[CustomEditor(typeof(WorldPoolsMonitor))]
|
|
||||||
public class WorldPoolsMonitorEditor : Editor
|
|
||||||
{
|
|
||||||
private static Vector2 _poolBlockMinSize = new Vector2(80, 160);
|
|
||||||
private static Vector2 _poolProgressBasrSize = _poolBlockMinSize * new Vector2(1f, 0.8f);
|
|
||||||
|
|
||||||
private WorldPoolsMonitor Target => (WorldPoolsMonitor)target;
|
|
||||||
|
|
||||||
private Vector2 _scroll;
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
_scroll = GUILayout.BeginScrollView(_scroll, GUILayout.Height(800f));
|
|
||||||
|
|
||||||
var pools = Target.world.AllPools.ToArray().Where(o => !o.IsNullOrDummy()).OfType<IEcsPool>();
|
|
||||||
|
|
||||||
GUILayout.Label("", GUILayout.ExpandWidth(true));
|
|
||||||
|
|
||||||
float width = GUILayoutUtility.GetLastRect().width;
|
|
||||||
|
|
||||||
Vector3 newPoolBlockSize = _poolBlockMinSize;
|
|
||||||
int widthCount = Mathf.Max(1, Mathf.Min((Mathf.FloorToInt(width / _poolBlockMinSize.x)), pools.Count()));
|
|
||||||
newPoolBlockSize.x = width / widthCount;
|
|
||||||
|
|
||||||
int x = -1, y = 0;
|
|
||||||
foreach (var pool in pools)
|
|
||||||
{
|
|
||||||
if(++x >= widthCount)
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y++;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawPoolBlock(pool, new Rect(newPoolBlockSize.x * x, newPoolBlockSize.y * y, newPoolBlockSize.x, newPoolBlockSize.y));
|
|
||||||
}
|
|
||||||
GUILayout.EndScrollView();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void DrawPoolBlock(IEcsPool pool, Rect position)
|
|
||||||
{
|
|
||||||
int count = pool.Count;
|
|
||||||
int capacity = pool.Capacity < 0 ? count : pool.Capacity;
|
|
||||||
|
|
||||||
Color defaultContentColor = GUI.contentColor;
|
|
||||||
GUI.contentColor = Color.black * 0.925f;
|
|
||||||
|
|
||||||
position = AddMargin(position, 1f, 1f);
|
|
||||||
|
|
||||||
EditorGUI.DrawRect(position, Color.black* 0.16f);
|
|
||||||
|
|
||||||
Rect progressBar = new Rect(Vector2.zero, _poolProgressBasrSize);
|
|
||||||
progressBar.width = position.width;
|
|
||||||
progressBar.center = position.center - Vector2.up * _poolBlockMinSize.y * 0.09f;
|
|
||||||
|
|
||||||
|
|
||||||
Color mainColor = new Color(0.3f, 1f, 0f, 1f);
|
|
||||||
var debugColor = pool.ComponentType.GetCustomAttribute<DebugColorAttribute>();
|
|
||||||
if (debugColor != null)
|
|
||||||
{
|
|
||||||
mainColor = debugColor.GetUnityColor();
|
|
||||||
}
|
|
||||||
Color backgroundColor = mainColor * 0.3f + Color.white * 0.2f;
|
|
||||||
|
|
||||||
EditorGUI.DrawRect(progressBar, backgroundColor);
|
|
||||||
|
|
||||||
progressBar.yMin = progressBar.yMax - ((float)count / capacity) * progressBar.height;
|
|
||||||
|
|
||||||
GUIStyle textStyle0 = new GUIStyle(EditorStyles.miniBoldLabel);
|
|
||||||
textStyle0.alignment = TextAnchor.MiddleCenter;
|
|
||||||
|
|
||||||
Color foregroundColor = mainColor;
|
|
||||||
EditorGUI.DrawRect(progressBar, foregroundColor);
|
|
||||||
GUI.Label(progressBar, count.ToString(), textStyle0);
|
|
||||||
|
|
||||||
GUIStyle textStyle1 = new GUIStyle(EditorStyles.miniBoldLabel);
|
|
||||||
textStyle1.alignment = TextAnchor.UpperCenter;
|
|
||||||
GUI.Label(AddMargin(position, 3f, 3f), "Total\r\n"+ capacity, textStyle1);
|
|
||||||
|
|
||||||
GUI.contentColor = defaultContentColor;
|
|
||||||
GUIStyle textStyle2 = new GUIStyle(EditorStyles.miniBoldLabel);
|
|
||||||
textStyle2.wordWrap = true;
|
|
||||||
textStyle2.alignment = TextAnchor.LowerCenter;
|
|
||||||
string name = EcsEditor.GetGenericName(pool.ComponentType);
|
|
||||||
GUIContent label = new GUIContent(name, $"{name} e:{count}");
|
|
||||||
GUI.Label(AddMargin(position, -10f, 3f), label, textStyle2);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private Rect AddMargin(Rect rect, Vector2 value)
|
|
||||||
{
|
|
||||||
return AddMargin(rect, value.x, value.y);
|
|
||||||
}
|
|
||||||
private Rect AddMargin(Rect rect, float x, float y)
|
|
||||||
{
|
|
||||||
rect.yMax -= y;
|
|
||||||
rect.yMin += y;
|
|
||||||
rect.xMax -= x;
|
|
||||||
rect.xMin += x;
|
|
||||||
return rect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@ -1,19 +1,33 @@
|
|||||||
using System;
|
using System;
|
||||||
using Unity.Profiling;
|
using Unity.Profiling;
|
||||||
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
|
[InitializeOnLoad]
|
||||||
public class UnityDebugService : DebugService
|
public class UnityDebugService : DebugService
|
||||||
{
|
{
|
||||||
public static void Init() => Set<UnityDebugService>();
|
|
||||||
|
|
||||||
private ProfilerMarker[] _profilerMarkers = new ProfilerMarker[64];
|
private ProfilerMarker[] _profilerMarkers = new ProfilerMarker[64];
|
||||||
|
static UnityDebugService()
|
||||||
|
{
|
||||||
|
Activate();
|
||||||
|
}
|
||||||
|
public static void Activate()
|
||||||
|
{
|
||||||
|
Set<UnityDebugService>();
|
||||||
|
}
|
||||||
public override void Print(string tag, object v)
|
public override void Print(string tag, object v)
|
||||||
{
|
{
|
||||||
string log;
|
string log;
|
||||||
if (!string.IsNullOrEmpty(tag))
|
if (v is Exception e)
|
||||||
|
{
|
||||||
|
Debug.LogException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasTag = string.IsNullOrEmpty(tag) == false;
|
||||||
|
if (hasTag)
|
||||||
{
|
{
|
||||||
log = $".[{tag}] {v}";
|
log = $".[{tag}] {v}";
|
||||||
string taglower = tag.ToLower();
|
string taglower = tag.ToLower();
|
||||||
@ -32,27 +46,29 @@ namespace DCFApixels.DragonECS
|
|||||||
}
|
}
|
||||||
Debug.Log(v);
|
Debug.Log(v);
|
||||||
}
|
}
|
||||||
|
public override void Break()
|
||||||
public override void ProfileMarkBegin(int id)
|
{
|
||||||
|
Debug.Break();
|
||||||
|
}
|
||||||
|
public sealed override void ProfilerMarkBegin(int id)
|
||||||
{
|
{
|
||||||
_profilerMarkers[id].Begin();
|
_profilerMarkers[id].Begin();
|
||||||
}
|
}
|
||||||
|
public sealed override void ProfilerMarkEnd(int id)
|
||||||
public override void ProfileMarkEnd(int id)
|
|
||||||
{
|
{
|
||||||
_profilerMarkers[id].End();
|
_profilerMarkers[id].End();
|
||||||
}
|
}
|
||||||
|
protected sealed override void OnDelProfilerMark(int id)
|
||||||
protected override void OnDelMark(int id)
|
|
||||||
{
|
{
|
||||||
_profilerMarkers[id] = default;
|
_profilerMarkers[id] = default;
|
||||||
}
|
}
|
||||||
|
protected sealed override void OnNewProfilerMark(int id, string name)
|
||||||
protected override void OnNewMark(int id, string name)
|
|
||||||
{
|
{
|
||||||
if (id >= _profilerMarkers.Length) Array.Resize(ref _profilerMarkers, _profilerMarkers.Length << 1);
|
if (id >= _profilerMarkers.Length)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _profilerMarkers, _profilerMarkers.Length << 1);
|
||||||
|
}
|
||||||
_profilerMarkers[id] = new ProfilerMarker(ProfilerCategory.Scripts, name);
|
_profilerMarkers[id] = new ProfilerMarker(ProfilerCategory.Scripts, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
namespace DCFApixels.DragonECS
|
namespace DCFApixels.DragonECS
|
||||||
{
|
{
|
||||||
public static class EcsUnityConsts
|
public static class EcsUnityConsts
|
||||||
{
|
{
|
||||||
public const string INFO_MARK = "[i]";
|
public const string INFO_MARK = "[D]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/EntityTemplate/Editor.meta
Normal file
8
src/EntityTemplate/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d8c6da13649cc094e80f3ec624bad02b
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
254
src/EntityTemplate/Editor/EntityTemplateEditor.cs
Normal file
254
src/EntityTemplate/Editor/EntityTemplateEditor.cs
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
public abstract class EntityTemplateEditorBase : Editor
|
||||||
|
{
|
||||||
|
private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 19f, 19f);
|
||||||
|
private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 19f, 19f);
|
||||||
|
|
||||||
|
private GUIStyle _removeButtonStyle;
|
||||||
|
private GenericMenu _genericMenu;
|
||||||
|
private bool _isInit = false;
|
||||||
|
|
||||||
|
#region Init
|
||||||
|
private void Init()
|
||||||
|
{
|
||||||
|
if (_genericMenu == null) { _isInit = false; }
|
||||||
|
if (_isInit) { return; }
|
||||||
|
|
||||||
|
var tmpstylebase = UnityEditorUtility.GetStyle(new Color(0.9f, 0f, 0.22f), 0.5f);
|
||||||
|
var tmpStyle = UnityEditorUtility.GetStyle(new Color(1f, 0.5f, 0.7f), 0.5f);
|
||||||
|
|
||||||
|
_removeButtonStyle = new GUIStyle(EditorStyles.linkLabel);
|
||||||
|
_removeButtonStyle.alignment = TextAnchor.MiddleCenter;
|
||||||
|
|
||||||
|
_removeButtonStyle.normal = tmpstylebase.normal;
|
||||||
|
_removeButtonStyle.hover = tmpStyle.normal;
|
||||||
|
_removeButtonStyle.active = tmpStyle.normal;
|
||||||
|
_removeButtonStyle.focused = tmpStyle.normal;
|
||||||
|
|
||||||
|
_removeButtonStyle.padding = new RectOffset(0, 0, 0, 0);
|
||||||
|
_removeButtonStyle.margin = new RectOffset(0, 0, 0, 0);
|
||||||
|
_removeButtonStyle.border = new RectOffset(0, 0, 0, 0);
|
||||||
|
|
||||||
|
_genericMenu = new GenericMenu();
|
||||||
|
|
||||||
|
var componentTemplateDummies = ComponentTemplateTypeCache.Dummies;
|
||||||
|
foreach (var dummy in componentTemplateDummies)
|
||||||
|
{
|
||||||
|
ITypeMeta meta = dummy is ITypeMeta metaOverride ? metaOverride : dummy.Type.ToMeta();
|
||||||
|
string name = meta.Name;
|
||||||
|
string description = meta.Description;
|
||||||
|
MetaGroup group = meta.Group;
|
||||||
|
|
||||||
|
if (group.Name.Length > 0)
|
||||||
|
{
|
||||||
|
name = group.Name + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(description) == false)
|
||||||
|
{
|
||||||
|
name = $"{name} {EcsUnityConsts.INFO_MARK}";
|
||||||
|
}
|
||||||
|
_genericMenu.AddItem(new GUIContent(name, description), false, OnAddComponent, dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isInit = true;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Add/Remove
|
||||||
|
private void OnAddComponent(object obj)
|
||||||
|
{
|
||||||
|
Type componentType = obj.GetType();
|
||||||
|
if (this.target is ITemplateInternal target)
|
||||||
|
{
|
||||||
|
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
||||||
|
for (int i = 0; i < componentsProp.arraySize; i++)
|
||||||
|
{
|
||||||
|
if (componentsProp.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentsProp.InsertArrayElementAtIndex(0);
|
||||||
|
|
||||||
|
componentsProp.GetArrayElementAtIndex(0).managedReferenceValue = ((IComponentTemplate)obj).Clone();
|
||||||
|
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
EditorUtility.SetDirty(this.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnRemoveComponentAt(int index)
|
||||||
|
{
|
||||||
|
if (this.target is ITemplateInternal target)
|
||||||
|
{
|
||||||
|
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
||||||
|
componentsProp.DeleteArrayElementAtIndex(index);
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
EditorUtility.SetDirty(this.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
protected void Draw(ITemplateInternal target)
|
||||||
|
{
|
||||||
|
Init();
|
||||||
|
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
||||||
|
if (componentsProp == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f));
|
||||||
|
DrawTop(target);
|
||||||
|
GUILayout.Label("", GUILayout.Height(0), GUILayout.ExpandWidth(true));
|
||||||
|
for (int i = 0; i < componentsProp.arraySize; i++)
|
||||||
|
{
|
||||||
|
DrawComponentData(componentsProp.GetArrayElementAtIndex(i), i);
|
||||||
|
}
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
private void DrawTop(ITemplateInternal target)
|
||||||
|
{
|
||||||
|
switch (EcsGUI.Layout.AddClearComponentButtons())
|
||||||
|
{
|
||||||
|
case EcsGUI.AddClearComponentButton.AddComponent:
|
||||||
|
Init();
|
||||||
|
_genericMenu.ShowAsContext();
|
||||||
|
break;
|
||||||
|
case EcsGUI.AddClearComponentButton.Clear:
|
||||||
|
Init();
|
||||||
|
serializedObject.FindProperty(target.ComponentsPropertyName).ClearArray();
|
||||||
|
serializedObject.ApplyModifiedProperties();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawComponentData(SerializedProperty componentRefProp, int index)
|
||||||
|
{
|
||||||
|
IComponentTemplate template = componentRefProp.managedReferenceValue as IComponentTemplate;
|
||||||
|
if (template == null || componentRefProp.managedReferenceValue == null)
|
||||||
|
{
|
||||||
|
DrawDamagedComponent(componentRefProp, index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Type componentType;
|
||||||
|
SerializedProperty componentProperty = componentRefProp;
|
||||||
|
ComponentTemplateBase customInitializer = componentProperty.managedReferenceValue as ComponentTemplateBase;
|
||||||
|
if (customInitializer != null)
|
||||||
|
{
|
||||||
|
componentProperty = componentRefProp.FindPropertyRelative("component");
|
||||||
|
componentType = customInitializer.GetType().GetField("component", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FieldType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
componentType = componentProperty.managedReferenceValue.GetType(); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
ITypeMeta meta = template is ITypeMeta metaOverride ? metaOverride : template.Type.ToMeta();
|
||||||
|
string name = meta.Name;
|
||||||
|
string description = meta.Description;
|
||||||
|
Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
|
||||||
|
|
||||||
|
//GUIContent label = new GUIContent(name);
|
||||||
|
GUIContent label = UnityEditorUtility.GetLabel(name);
|
||||||
|
bool isEmpty = componentType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0;
|
||||||
|
float padding = EditorGUIUtility.standardVerticalSpacing;
|
||||||
|
Color alphaPanelColor = panelColor;
|
||||||
|
alphaPanelColor.a = EscEditorConsts.COMPONENT_DRAWER_ALPHA;
|
||||||
|
|
||||||
|
Rect removeButtonRect = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(alphaPanelColor));
|
||||||
|
|
||||||
|
#region Draw Component Block
|
||||||
|
bool isRemoveComponent = false;
|
||||||
|
removeButtonRect.yMin = removeButtonRect.yMax;
|
||||||
|
removeButtonRect.yMax += RemoveButtonRect.height;
|
||||||
|
removeButtonRect.xMin = removeButtonRect.xMax - RemoveButtonRect.width;
|
||||||
|
removeButtonRect.center += Vector2.up * padding * 2f;
|
||||||
|
|
||||||
|
if (EcsGUI.CloseButton(removeButtonRect))
|
||||||
|
{
|
||||||
|
isRemoveComponent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isEmpty)
|
||||||
|
{
|
||||||
|
GUILayout.Label(label);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUILayout.PropertyField(componentProperty, label, true);
|
||||||
|
}
|
||||||
|
if (isRemoveComponent)
|
||||||
|
{
|
||||||
|
OnRemoveComponentAt(index);
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(description) == false)
|
||||||
|
{
|
||||||
|
Rect tooltipIconRect = TooltipIconRect;
|
||||||
|
tooltipIconRect.center = removeButtonRect.center;
|
||||||
|
tooltipIconRect.center -= Vector2.right * tooltipIconRect.width;
|
||||||
|
EcsGUI.DescriptionIcon(tooltipIconRect, description);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
componentProperty.serializedObject.ApplyModifiedProperties();
|
||||||
|
EditorUtility.SetDirty(componentProperty.serializedObject.targetObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DrawDamagedComponent(SerializedProperty componentRefProp, int index)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
|
||||||
|
EditorGUILayout.HelpBox($"Damaged component. If the problem occurred after renaming a component or initializer. use MovedFromAttrubute", MessageType.Warning);
|
||||||
|
|
||||||
|
Rect lastrect = GUILayoutUtility.GetLastRect();
|
||||||
|
Rect removeButtonRect = RemoveButtonRect;
|
||||||
|
removeButtonRect.center = new Vector2(lastrect.xMax + removeButtonRect.width, lastrect.yMin + removeButtonRect.height / 2f);
|
||||||
|
|
||||||
|
GUILayout.Label("", GUILayout.Width(removeButtonRect.width));
|
||||||
|
if (GUI.Button(removeButtonRect, "x", _removeButtonStyle))
|
||||||
|
{
|
||||||
|
OnRemoveComponentAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CustomEditor(typeof(ScriptableEntityTemplate), true)]
|
||||||
|
public class EntityTemplatePresetEditor : EntityTemplateEditorBase
|
||||||
|
{
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
Draw((ITemplateInternal)target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[CustomEditor(typeof(MonoEntityTemplate), true)]
|
||||||
|
public class EntityTemplateEditor : EntityTemplateEditorBase
|
||||||
|
{
|
||||||
|
public override void OnInspectorGUI()
|
||||||
|
{
|
||||||
|
Draw((ITemplateInternal)target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -1,40 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public class EntityTemplate : MonoBehaviour, ITemplateInternal
|
|
||||||
{
|
|
||||||
[SerializeReference]
|
|
||||||
private ITemplateComponent[] _components;
|
|
||||||
string ITemplateInternal.ComponentsPropertyName => nameof(_components);
|
|
||||||
|
|
||||||
public void Apply(EcsWorld world, int entityID)
|
|
||||||
{
|
|
||||||
foreach (var item in _components)
|
|
||||||
item.Add(world, entityID);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDrawGizmos()
|
|
||||||
{
|
|
||||||
if (_components == null) return;
|
|
||||||
foreach (var item in _components)
|
|
||||||
{
|
|
||||||
if (item is ITemplateComponentGizmos g)
|
|
||||||
g.OnGizmos(transform, ITemplateComponentGizmos.Mode.Always);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void OnDrawGizmosSelected()
|
|
||||||
{
|
|
||||||
if (_components == null) return;
|
|
||||||
foreach (var item in _components)
|
|
||||||
{
|
|
||||||
if (item is ITemplateComponentGizmos g)
|
|
||||||
g.OnGizmos(transform, ITemplateComponentGizmos.Mode.Selected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_components = new ITemplateComponent[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 3c96e3aedd5a69443af75096e5561265
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,259 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
namespace Editors
|
|
||||||
{
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
public abstract class EntityTemplateEditorBase: Editor
|
|
||||||
{
|
|
||||||
private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 15f, 15f);
|
|
||||||
private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 15f, 15f);
|
|
||||||
|
|
||||||
private GUIStyle removeButtonStyle;
|
|
||||||
private GenericMenu genericMenu;
|
|
||||||
private bool _isInit = false;
|
|
||||||
|
|
||||||
#region Init
|
|
||||||
private void Init()
|
|
||||||
{
|
|
||||||
if (genericMenu == null)
|
|
||||||
_isInit = false;
|
|
||||||
if (_isInit)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var tmpstylebase = EcsEditor.GetStyle(new Color(0.9f, 0f, 0.22f), 0.5f);
|
|
||||||
var tmpStyle = EcsEditor.GetStyle(new Color(1f, 0.5f, 0.7f), 0.5f);
|
|
||||||
|
|
||||||
removeButtonStyle = new GUIStyle(EditorStyles.linkLabel);
|
|
||||||
removeButtonStyle.alignment = TextAnchor.MiddleCenter;
|
|
||||||
|
|
||||||
removeButtonStyle.normal = tmpstylebase.normal;
|
|
||||||
removeButtonStyle.hover = tmpStyle.normal;
|
|
||||||
removeButtonStyle.active = tmpStyle.normal;
|
|
||||||
removeButtonStyle.focused = tmpStyle.normal;
|
|
||||||
|
|
||||||
removeButtonStyle.padding = new RectOffset(0, 0, 0, 0);
|
|
||||||
removeButtonStyle.margin = new RectOffset(0, 0, 0, 0);
|
|
||||||
removeButtonStyle.border = new RectOffset(0, 0, 0, 0);
|
|
||||||
|
|
||||||
genericMenu = new GenericMenu();
|
|
||||||
|
|
||||||
var dummies = TemplateBrowsableTypeCache.Dummies;
|
|
||||||
foreach ( var dummy in dummies )
|
|
||||||
{
|
|
||||||
string name, description;
|
|
||||||
if (dummy is ITemplateComponentName browsableName)
|
|
||||||
name = browsableName.Name;
|
|
||||||
else
|
|
||||||
name = EcsEditor.GetName(dummy.GetType());
|
|
||||||
|
|
||||||
if (dummy is TemplateComponentInitializerBase initializer)
|
|
||||||
description = initializer.Description;
|
|
||||||
else
|
|
||||||
description = EcsEditor.GetDescription(dummy.GetType());
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(description))
|
|
||||||
{
|
|
||||||
name = $"{name} {EcsUnityConsts.INFO_MARK}";
|
|
||||||
}
|
|
||||||
|
|
||||||
genericMenu.AddItem(new GUIContent(name, description), false, OnAddComponent, dummy);
|
|
||||||
}
|
|
||||||
|
|
||||||
_isInit = true;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Add/Remove
|
|
||||||
private void OnAddComponent(object obj)
|
|
||||||
{
|
|
||||||
Type componentType = obj.GetType();
|
|
||||||
if (this.target is ITemplateInternal target)
|
|
||||||
{
|
|
||||||
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
|
||||||
for (int i = 0; i < componentsProp.arraySize; i++)
|
|
||||||
{
|
|
||||||
if (componentsProp.GetArrayElementAtIndex(i).managedReferenceValue.GetType() == componentType)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentsProp.InsertArrayElementAtIndex(0);
|
|
||||||
|
|
||||||
componentsProp.GetArrayElementAtIndex(0).managedReferenceValue = ((ITemplateComponent)obj).Clone();
|
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
EditorUtility.SetDirty(this.target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void OnRemoveComponentAt(int index)
|
|
||||||
{
|
|
||||||
if (this.target is ITemplateInternal target)
|
|
||||||
{
|
|
||||||
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
|
||||||
componentsProp.DeleteArrayElementAtIndex(index);
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
EditorUtility.SetDirty(this.target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
protected void Draw(ITemplateInternal target)
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
SerializedProperty componentsProp = serializedObject.FindProperty(target.ComponentsPropertyName);
|
|
||||||
if (componentsProp == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
DrawTop(target);
|
|
||||||
for (int i = 0; i < componentsProp.arraySize; i++)
|
|
||||||
{
|
|
||||||
DrawComponentData(componentsProp.GetArrayElementAtIndex(i), i);
|
|
||||||
GUILayout.Space(EditorGUIUtility.standardVerticalSpacing * 2);
|
|
||||||
}
|
|
||||||
DrawFooter(target);
|
|
||||||
}
|
|
||||||
private void DrawTop(ITemplateInternal target)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Add Component", GUILayout.Height(24f)))
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
genericMenu.ShowAsContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void DrawFooter(ITemplateInternal target)
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Clear", GUILayout.Height(24f)))
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
serializedObject.FindProperty(target.ComponentsPropertyName).ClearArray();
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private void DrawComponentData(SerializedProperty componentRefProp, int index)
|
|
||||||
{
|
|
||||||
ITemplateComponent browsable = componentRefProp.managedReferenceValue as ITemplateComponent;
|
|
||||||
if(browsable == null)
|
|
||||||
{
|
|
||||||
DrawDamagedComponent(componentRefProp, index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ITemplateComponentName browsableName = browsable as ITemplateComponentName;
|
|
||||||
|
|
||||||
if (componentRefProp.managedReferenceValue == null)
|
|
||||||
{
|
|
||||||
DrawDamagedComponent(componentRefProp, index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type initializerType;
|
|
||||||
Type componentType;
|
|
||||||
SerializedProperty componentProperty = componentRefProp;
|
|
||||||
TemplateComponentInitializerBase customInitializer = componentProperty.managedReferenceValue as TemplateComponentInitializerBase;
|
|
||||||
if (customInitializer != null)
|
|
||||||
{
|
|
||||||
componentProperty = componentRefProp.FindPropertyRelative("component");
|
|
||||||
initializerType = customInitializer.Type;
|
|
||||||
componentType = customInitializer.GetType().GetField("component", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FieldType;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
initializerType = componentProperty.managedReferenceValue.GetType();
|
|
||||||
componentType = initializerType;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type = browsable.GetType();
|
|
||||||
string name = browsableName == null ? type.Name : GetLastPathComponent(browsableName.Name);
|
|
||||||
string description = customInitializer != null ? customInitializer.Description : initializerType.GetCustomAttribute<DebugDescriptionAttribute>()?.description;
|
|
||||||
Color panelColor = customInitializer != null ? customInitializer.Color : initializerType.GetCustomAttribute<DebugColorAttribute>()?.GetUnityColor() ?? Color.black;
|
|
||||||
|
|
||||||
GUILayout.BeginHorizontal();
|
|
||||||
|
|
||||||
GUILayout.BeginVertical(EcsEditor.GetStyle(panelColor, 0.2f));
|
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
GUIContent label = new GUIContent(name, $"{name} ");
|
|
||||||
if (componentType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Length <= 0)
|
|
||||||
{
|
|
||||||
GUILayout.Label(label);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorGUILayout.PropertyField(componentProperty, label, true);
|
|
||||||
}
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
componentProperty.serializedObject.ApplyModifiedProperties();
|
|
||||||
EditorUtility.SetDirty(componentProperty.serializedObject.targetObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect lastrect = GUILayoutUtility.GetLastRect();
|
|
||||||
Rect removeButtonRect = RemoveButtonRect;
|
|
||||||
removeButtonRect.center = new Vector2(lastrect.xMax + removeButtonRect.width, lastrect.yMin + removeButtonRect.height / 2f);
|
|
||||||
|
|
||||||
GUILayout.EndVertical();
|
|
||||||
GUILayout.Label("", GUILayout.Width(removeButtonRect.width));
|
|
||||||
|
|
||||||
if (GUI.Button(removeButtonRect, "x", removeButtonStyle))
|
|
||||||
OnRemoveComponentAt(index);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(description))
|
|
||||||
{
|
|
||||||
Rect tooltipIconRect = TooltipIconRect;
|
|
||||||
tooltipIconRect.center = new Vector2(lastrect.xMax - removeButtonRect.width / 2f, lastrect.yMin + removeButtonRect.height / 2f);
|
|
||||||
GUIContent descriptionLabel = new GUIContent(EcsUnityConsts.INFO_MARK, description);
|
|
||||||
GUI.Label(tooltipIconRect, descriptionLabel, EditorStyles.boldLabel);
|
|
||||||
}
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawDamagedComponent(SerializedProperty componentRefProp, int index)
|
|
||||||
{
|
|
||||||
GUILayout.BeginHorizontal();
|
|
||||||
|
|
||||||
EditorGUILayout.HelpBox($"Damaged component. If the problem occurred after renaming a component or initializer. use MovedFromAttrubute", MessageType.Warning);
|
|
||||||
|
|
||||||
Rect lastrect = GUILayoutUtility.GetLastRect();
|
|
||||||
Rect removeButtonRect = RemoveButtonRect;
|
|
||||||
removeButtonRect.center = new Vector2(lastrect.xMax + removeButtonRect.width, lastrect.yMin + removeButtonRect.height / 2f);
|
|
||||||
|
|
||||||
GUILayout.Label("", GUILayout.Width(removeButtonRect.width));
|
|
||||||
if (GUI.Button(removeButtonRect, "x", removeButtonStyle))
|
|
||||||
OnRemoveComponentAt(index);
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetLastPathComponent(string input)
|
|
||||||
{
|
|
||||||
int lastSlashIndex = input.LastIndexOfAny(new char[] { '/', '\\' });
|
|
||||||
if (lastSlashIndex == -1)
|
|
||||||
return input;
|
|
||||||
else
|
|
||||||
return input.Substring(lastSlashIndex + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[CustomEditor(typeof(EntityTemplatePreset), true)]
|
|
||||||
public class EntityTemplatePresetEditor : EntityTemplateEditorBase
|
|
||||||
{
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
Draw((ITemplateInternal)target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[CustomEditor(typeof(EntityTemplate), true)]
|
|
||||||
public class EntityTemplateEditor : EntityTemplateEditorBase
|
|
||||||
{
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
Draw((ITemplateInternal)target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
[CreateAssetMenu(fileName = "EntityTemplatePreset", menuName = EcsConsts.FRAMEWORK_NAME + "/EntityTemplatePreset", order = 1)]
|
|
||||||
public class EntityTemplatePreset : ScriptableObject, ITemplateInternal
|
|
||||||
{
|
|
||||||
[SerializeReference]
|
|
||||||
private ITemplateComponent[] _components;
|
|
||||||
string ITemplateInternal.ComponentsPropertyName => nameof(_components);
|
|
||||||
|
|
||||||
//ITemplateBrowsable[] ITemplateInternal.Components
|
|
||||||
//{
|
|
||||||
// get => _components;
|
|
||||||
// set => _components = value;
|
|
||||||
//}
|
|
||||||
|
|
||||||
public void Apply(EcsWorld world, int entityID)
|
|
||||||
{
|
|
||||||
foreach (var item in _components)
|
|
||||||
item.Add(world, entityID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
_components = new ITemplateComponent[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 54d84d8749e68c044b4f13a512808a67
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public interface ITemplate
|
|
||||||
{
|
|
||||||
public void Apply(EcsWorld world, int entityID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ITemplateInternal : ITemplate
|
|
||||||
{
|
|
||||||
// internal ITemplateBrowsable[] Components { get; set; }
|
|
||||||
internal string ComponentsPropertyName { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ITemplateExt
|
|
||||||
{
|
|
||||||
public static int NewEntity(this ITemplate self, EcsWorld world)
|
|
||||||
{
|
|
||||||
int e = world.NewEmptyEntity();
|
|
||||||
self.Apply(world, e);
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
57
src/EntityTemplate/ITemplateNode.cs
Normal file
57
src/EntityTemplate/ITemplateNode.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public interface ITemplateNode
|
||||||
|
{
|
||||||
|
void Apply(int worldID, int entityID);
|
||||||
|
}
|
||||||
|
public interface ITemplate : ITemplateNode
|
||||||
|
{
|
||||||
|
//void Add(ITemplateNode template);
|
||||||
|
//void Remove(ITemplateNode template);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ITemplateInternal : ITemplate
|
||||||
|
{
|
||||||
|
string ComponentsPropertyName { get; }
|
||||||
|
//EntityTemplateInheritanceMatrix InheritanceMatrix { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ITemplateExtensions
|
||||||
|
{
|
||||||
|
public static int NewEntity(this EcsWorld world, ITemplateNode template)
|
||||||
|
{
|
||||||
|
int e = world.NewEntity();
|
||||||
|
template.Apply(world.id, e);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
public static entlong NewEntityLong(this EcsWorld world, ITemplateNode template)
|
||||||
|
{
|
||||||
|
entlong e = world.NewEntityLong();
|
||||||
|
template.Apply(world.id, e.ID);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
public static entlong NewEntityWithGameObject(this EcsWorld world, ITemplateNode template, string name = "Entity", GameObjectIcon icon = GameObjectIcon.NONE)
|
||||||
|
{
|
||||||
|
entlong e = world.NewEntityWithGameObject(name, icon);
|
||||||
|
template.Apply(world.id, e.ID);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//[Serializable]
|
||||||
|
//public class EntityTemplateInheritanceMatrix
|
||||||
|
//{
|
||||||
|
// [SerializeReference]
|
||||||
|
// private ITemplateNode[] _components;
|
||||||
|
//
|
||||||
|
// #region Methods
|
||||||
|
// public void Apply(int worldID, int entityID)
|
||||||
|
// {
|
||||||
|
// foreach (var item in _components)
|
||||||
|
// {
|
||||||
|
// item.Apply(worldID, entityID);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// #endregion
|
||||||
|
//}
|
||||||
|
}
|
||||||
@ -1,146 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.Editors;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public interface ITemplateComponent
|
|
||||||
{
|
|
||||||
public void Add(EcsWorld w, int e);
|
|
||||||
}
|
|
||||||
public interface ITemplateComponentName : ITemplateComponent
|
|
||||||
{
|
|
||||||
public string Name { get; }
|
|
||||||
}
|
|
||||||
public interface ITemplateComponentGizmos
|
|
||||||
{
|
|
||||||
public void OnGizmos(Transform transform, Mode mode);
|
|
||||||
public enum Mode
|
|
||||||
{
|
|
||||||
Always,
|
|
||||||
Selected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
public abstract class TemplateComponentInitializerBase
|
|
||||||
{
|
|
||||||
public virtual string Name => string.Empty;
|
|
||||||
public virtual Color Color => Color.black;
|
|
||||||
public virtual string Description => string.Empty;
|
|
||||||
public abstract Type Type { get; }
|
|
||||||
|
|
||||||
internal abstract object ComponentRef { get; }
|
|
||||||
|
|
||||||
#region Get meta
|
|
||||||
internal static Color GetColor(Type type)
|
|
||||||
{
|
|
||||||
var atr = type.GetCustomAttribute<DebugColorAttribute>();
|
|
||||||
if (atr == null) return Color.black;
|
|
||||||
return atr.GetUnityColor();
|
|
||||||
}
|
|
||||||
internal static string GetName(Type type)
|
|
||||||
{
|
|
||||||
string friendlyName = type.Name;
|
|
||||||
if (type.IsGenericType)
|
|
||||||
{
|
|
||||||
int iBacktick = friendlyName.IndexOf('`');
|
|
||||||
if (iBacktick > 0)
|
|
||||||
friendlyName = friendlyName.Remove(iBacktick);
|
|
||||||
|
|
||||||
friendlyName += "/" + friendlyName;
|
|
||||||
friendlyName += "<";
|
|
||||||
Type[] typeParameters = type.GetGenericArguments();
|
|
||||||
for (int i = 0; i < typeParameters.Length; ++i)
|
|
||||||
{
|
|
||||||
string typeParamName = GetName(typeParameters[i]);
|
|
||||||
friendlyName += (i == 0 ? typeParamName : "," + typeParamName);
|
|
||||||
}
|
|
||||||
friendlyName += ">";
|
|
||||||
}
|
|
||||||
return friendlyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static string GetDescription(Type type)
|
|
||||||
{
|
|
||||||
var atr = type.GetCustomAttribute<DebugDescriptionAttribute>();
|
|
||||||
if (atr == null) return string.Empty;
|
|
||||||
return atr.description;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public abstract class TemplateComponentInitializer<T> : TemplateComponentInitializerBase, ITemplateComponentName, ITemplateComponentGizmos
|
|
||||||
{
|
|
||||||
private static string _autoname = GetName(typeof(T));
|
|
||||||
private static Color _autoColor = GetColor(typeof(T));
|
|
||||||
private static string _autoDescription = GetDescription(typeof(T));
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
protected T component;
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public override string Name => _autoname;
|
|
||||||
public override Color Color => _autoColor;
|
|
||||||
public override string Description => _autoDescription;
|
|
||||||
public sealed override Type Type => typeof(T);
|
|
||||||
|
|
||||||
internal T Component => component;
|
|
||||||
internal override object ComponentRef => component;
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public abstract void Add(EcsWorld w, int e);
|
|
||||||
public virtual void OnGizmos(Transform transform, ITemplateComponentGizmos.Mode mode) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class ITemplateBrowsableExt
|
|
||||||
{
|
|
||||||
private static MethodInfo memberwiseCloneMethdo = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);
|
|
||||||
internal static ITemplateComponent Clone(this ITemplateComponent obj)
|
|
||||||
{
|
|
||||||
return (ITemplateComponent)memberwiseCloneMethdo.Invoke(obj, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
namespace Editors
|
|
||||||
{
|
|
||||||
internal static class TemplateBrowsableTypeCache
|
|
||||||
{
|
|
||||||
private static Type[] _types;
|
|
||||||
private static ITemplateComponent[] _dummies;
|
|
||||||
internal static ReadOnlySpan<Type> Types => _types;
|
|
||||||
internal static ReadOnlySpan<ITemplateComponent> Dummies => _dummies;
|
|
||||||
|
|
||||||
static TemplateBrowsableTypeCache()
|
|
||||||
{
|
|
||||||
List<Type> types = new List<Type>();
|
|
||||||
Type interfaceType = typeof(ITemplateComponent);
|
|
||||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
||||||
{
|
|
||||||
var targetTypes = assembly.GetTypes().Where(type => !type.IsGenericType && (type.IsValueType|| type.IsClass) && type.GetCustomAttribute<SerializableAttribute>() != null);
|
|
||||||
|
|
||||||
types.AddRange(targetTypes.Where(type => interfaceType.IsAssignableFrom(type)));
|
|
||||||
|
|
||||||
foreach (var t in targetTypes)
|
|
||||||
{
|
|
||||||
if (t.IsSubclassOf(typeof(TemplateComponentInitializer<>)))
|
|
||||||
{
|
|
||||||
if(t.GetCustomAttribute<SerializableAttribute>() != null)
|
|
||||||
types.Add(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_types = types.ToArray();
|
|
||||||
_dummies = new ITemplateComponent[_types.Length];
|
|
||||||
|
|
||||||
for (int i = 0; i < _types.Length; i++)
|
|
||||||
_dummies[i] = (ITemplateComponent)Activator.CreateInstance(_types[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0ce52308e352f734e8a21c5ae282c246
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
8
src/EntityTemplate/Templates.meta
Normal file
8
src/EntityTemplate/Templates.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 14555d6350df03d448d362de7b6a31c1
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
159
src/EntityTemplate/Templates/ComponentTemplateBase.cs
Normal file
159
src/EntityTemplate/Templates/ComponentTemplateBase.cs
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEngine;
|
||||||
|
using static DCFApixels.DragonECS.IComponentTemplate;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
public interface IComponentTemplate : ITemplateNode
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
Type Type { get; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
object GetRaw();
|
||||||
|
void SetRaw(object raw);
|
||||||
|
void OnGizmos(Transform transform, GizmosMode mode);
|
||||||
|
void OnValidate(UnityEngine.Object obj);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public enum GizmosMode
|
||||||
|
{
|
||||||
|
Always,
|
||||||
|
Selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public interface IComponentTemplateWithMetaOverride : IComponentTemplate, ITypeMeta { }
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public abstract class ComponentTemplateBase : IComponentTemplateWithMetaOverride
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
public abstract Type Type { get; }
|
||||||
|
public virtual string Name { get { return string.Empty; } }
|
||||||
|
public virtual MetaColor Color { get { return new MetaColor(MetaColor.Black); } }
|
||||||
|
public virtual MetaGroup Group { get { return MetaGroup.Empty; } }
|
||||||
|
public virtual string Description { get { return string.Empty; } }
|
||||||
|
public virtual IReadOnlyCollection<string> Tags { get { return Array.Empty<string>(); } }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
public abstract object GetRaw();
|
||||||
|
public abstract void SetRaw(object raw);
|
||||||
|
public virtual void OnGizmos(Transform transform, GizmosMode mode) { }
|
||||||
|
public virtual void OnValidate(UnityEngine.Object obj) { }
|
||||||
|
|
||||||
|
public abstract void Apply(int worldID, int entityID);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public abstract class ComponentTemplateBase<T> : ComponentTemplateBase
|
||||||
|
{
|
||||||
|
protected static TypeMeta Meta = EcsDebugUtility.GetTypeMeta<T>();
|
||||||
|
[SerializeField]
|
||||||
|
protected T component;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
public override Type Type { get { return typeof(T); } }
|
||||||
|
public override string Name { get { return Meta.Name; } }
|
||||||
|
public override MetaGroup Group { get { return Meta.Group; } }
|
||||||
|
public override string Description { get { return Meta.Description; } }
|
||||||
|
public override IReadOnlyCollection<string> Tags { get { return Meta.Tags; } }
|
||||||
|
public override MetaColor Color { get { return Meta.Color; } }
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
public override object GetRaw()
|
||||||
|
{
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
public override void SetRaw(object raw)
|
||||||
|
{
|
||||||
|
component = (T)raw;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class ComponentTemplate<T> : ComponentTemplateBase<T>
|
||||||
|
where T : struct, IEcsComponent
|
||||||
|
{
|
||||||
|
public override void Apply(int worldID, int entityID)
|
||||||
|
{
|
||||||
|
EcsWorld.GetPoolInstance<EcsPool<T>>(worldID).TryAddOrGet(entityID) = component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public abstract class TagComponentTemplate<T> : ComponentTemplateBase<T>
|
||||||
|
where T : struct, IEcsTagComponent
|
||||||
|
{
|
||||||
|
public override void Apply(int worldID, int entityID)
|
||||||
|
{
|
||||||
|
EcsWorld.GetPoolInstance<EcsTagPool<T>>(worldID).Set(entityID, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Internal
|
||||||
|
{
|
||||||
|
internal static class ComponentTemplateExtensions
|
||||||
|
{
|
||||||
|
private static MethodInfo memberwiseCloneMethdo = typeof(object).GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
internal static IComponentTemplate Clone(this IComponentTemplate obj)
|
||||||
|
{
|
||||||
|
return (IComponentTemplate)memberwiseCloneMethdo.Invoke(obj, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UNITY_EDITOR
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
internal static class ComponentTemplateTypeCache
|
||||||
|
{
|
||||||
|
private static Type[] _types;
|
||||||
|
private static IComponentTemplate[] _dummies;
|
||||||
|
internal static ReadOnlySpan<Type> Types
|
||||||
|
{
|
||||||
|
get { return _types; }
|
||||||
|
}
|
||||||
|
internal static ReadOnlySpan<IComponentTemplate> Dummies
|
||||||
|
{
|
||||||
|
get { return _dummies; }
|
||||||
|
}
|
||||||
|
|
||||||
|
static ComponentTemplateTypeCache()
|
||||||
|
{
|
||||||
|
List<Type> types = new List<Type>();
|
||||||
|
Type interfaceType = typeof(IComponentTemplate);
|
||||||
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
{
|
||||||
|
var targetTypes = assembly.GetTypes().Where(type => !type.IsGenericType && !(type.IsAbstract || type.IsInterface) && type.GetCustomAttribute<SerializableAttribute>() != null);
|
||||||
|
|
||||||
|
types.AddRange(targetTypes.Where(type => interfaceType.IsAssignableFrom(type)));
|
||||||
|
|
||||||
|
foreach (var t in targetTypes)
|
||||||
|
{
|
||||||
|
if (t.IsSubclassOf(typeof(ComponentTemplateBase<>)))
|
||||||
|
{
|
||||||
|
types.Add(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_types = types.ToArray();
|
||||||
|
foreach (var type in _types)
|
||||||
|
{
|
||||||
|
EcsDebugUtility.GetTypeMeta(type);
|
||||||
|
}
|
||||||
|
_dummies = new IComponentTemplate[_types.Length];
|
||||||
|
|
||||||
|
for (int i = 0; i < _types.Length; i++)
|
||||||
|
{
|
||||||
|
_dummies[i] = (IComponentTemplate)Activator.CreateInstance(_types[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
11
src/EntityTemplate/Templates/ComponentTemplateBase.cs.meta
Normal file
11
src/EntityTemplate/Templates/ComponentTemplateBase.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b532f9d8441035d49b9acb99ea23c231
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
66
src/EntityTemplate/Templates/MonoEntityTemplate.cs
Normal file
66
src/EntityTemplate/Templates/MonoEntityTemplate.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
[DisallowMultipleComponent]
|
||||||
|
public class MonoEntityTemplate : MonoBehaviour, ITemplateInternal
|
||||||
|
{
|
||||||
|
[SerializeReference]
|
||||||
|
private IComponentTemplate[] _components;
|
||||||
|
//[SerializeField]
|
||||||
|
//private EntityTemplateInheritanceMatrix _inheritanceMatrix;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
string ITemplateInternal.ComponentsPropertyName
|
||||||
|
{
|
||||||
|
get { return nameof(_components); }
|
||||||
|
}
|
||||||
|
//EntityTemplateInheritanceMatrix ITemplateInternal.InheritanceMatrix
|
||||||
|
//{
|
||||||
|
// get { return _inheritanceMatrix; }
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
public void Apply(int worldID, int entityID)
|
||||||
|
{
|
||||||
|
foreach (var item in _components)
|
||||||
|
{
|
||||||
|
item.Apply(worldID, entityID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_components = Array.Empty<IComponentTemplate>();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UnityEvents
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (_components == null) { return; }
|
||||||
|
foreach (var item in _components)
|
||||||
|
{
|
||||||
|
item.OnValidate(gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnDrawGizmos()
|
||||||
|
{
|
||||||
|
if (_components == null) { return; }
|
||||||
|
foreach (var item in _components)
|
||||||
|
{
|
||||||
|
item.OnGizmos(transform, IComponentTemplate.GizmosMode.Always);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void OnDrawGizmosSelected()
|
||||||
|
{
|
||||||
|
if (_components == null) { return; }
|
||||||
|
foreach (var item in _components)
|
||||||
|
{
|
||||||
|
item.OnGizmos(transform, IComponentTemplate.GizmosMode.Selected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/EntityTemplate/Templates/MonoEntityTemplate.cs.meta
Normal file
11
src/EntityTemplate/Templates/MonoEntityTemplate.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 351338ca92ace49499f450172d857af6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
50
src/EntityTemplate/Templates/ScriptableEntityTemplate.cs
Normal file
50
src/EntityTemplate/Templates/ScriptableEntityTemplate.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(fileName = nameof(ScriptableEntityTemplate), menuName = EcsConsts.FRAMEWORK_NAME + "/" + nameof(ScriptableEntityTemplate), order = 1)]
|
||||||
|
public class ScriptableEntityTemplate : ScriptableObject, ITemplateInternal
|
||||||
|
{
|
||||||
|
[SerializeReference]
|
||||||
|
private IComponentTemplate[] _components;
|
||||||
|
//[SerializeField]
|
||||||
|
//private EntityTemplateInheritanceMatrix _inheritanceMatrix;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
string ITemplateInternal.ComponentsPropertyName
|
||||||
|
{
|
||||||
|
get { return nameof(_components); }
|
||||||
|
}
|
||||||
|
//EntityTemplateInheritanceMatrix ITemplateInternal.InheritanceMatrix
|
||||||
|
//{
|
||||||
|
// get { return _inheritanceMatrix; }
|
||||||
|
//}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
public void Apply(int worldID, int entityID)
|
||||||
|
{
|
||||||
|
foreach (var item in _components)
|
||||||
|
{
|
||||||
|
item.Apply(worldID, entityID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
_components = Array.Empty<IComponentTemplate>();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region UnityEvents
|
||||||
|
private void OnValidate()
|
||||||
|
{
|
||||||
|
if (_components == null) { return; }
|
||||||
|
foreach (var item in _components)
|
||||||
|
{
|
||||||
|
item.OnValidate(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3d2b62f9703592042befb46ac1fee09c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,143 +0,0 @@
|
|||||||
using System.Runtime.CompilerServices;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public class EcsEntityConnect : MonoBehaviour
|
|
||||||
{
|
|
||||||
private sealed class Subject : EcsSubject
|
|
||||||
{
|
|
||||||
public readonly EcsPool<UnityGameObject> unityGameObjects;
|
|
||||||
public Subject(Builder b)
|
|
||||||
{
|
|
||||||
unityGameObjects = b.Include<UnityGameObject>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private entlong _entity;
|
|
||||||
private EcsWorld _world;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private EntityTemplatePreset[] _entityTemplatePresets;
|
|
||||||
[SerializeField]
|
|
||||||
private EntityTemplate[] _entityTemplates;
|
|
||||||
|
|
||||||
internal void SetTemplates_Editor(EntityTemplate[] tempaltes)
|
|
||||||
{
|
|
||||||
_entityTemplates = tempaltes;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Properties
|
|
||||||
public entlong Entity
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => _entity;
|
|
||||||
}
|
|
||||||
public EcsWorld World
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => _world;
|
|
||||||
}
|
|
||||||
public bool IsAlive
|
|
||||||
{
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
get => _entity.IsAlive;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
public void ConnectWith(entlong entity, bool applyTemplates = false)
|
|
||||||
{
|
|
||||||
if(_entity.TryGetID(out int oldE) && _world != null)
|
|
||||||
{
|
|
||||||
var s = _world.GetSubject<Subject>();
|
|
||||||
s.unityGameObjects.Del(oldE);
|
|
||||||
}
|
|
||||||
_world = null;
|
|
||||||
|
|
||||||
if (entity.TryGetID(out int newE))
|
|
||||||
{
|
|
||||||
_entity = entity;
|
|
||||||
_world = _entity.World;
|
|
||||||
var s = _world.GetSubject<Subject>();
|
|
||||||
if (!s.unityGameObjects.Has(newE)) s.unityGameObjects.Add(newE) = new UnityGameObject(gameObject);
|
|
||||||
|
|
||||||
if (applyTemplates)
|
|
||||||
ApplyTemplates();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_entity = entlong.NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void ApplyTemplates() => ApplyTemplatesFor(_entity.ID);
|
|
||||||
public void ApplyTemplatesFor(int entityID)
|
|
||||||
{
|
|
||||||
foreach (var t in _entityTemplatePresets)
|
|
||||||
t.Apply(_world, entityID);
|
|
||||||
foreach (var t in _entityTemplates)
|
|
||||||
t.Apply(_world, entityID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
|
|
||||||
namespace Editors
|
|
||||||
{
|
|
||||||
using UnityEditor;
|
|
||||||
[CustomEditor(typeof(EcsEntityConnect))]
|
|
||||||
public class EcsEntityEditor : Editor
|
|
||||||
{
|
|
||||||
private EcsEntityConnect Target => (EcsEntityConnect)target;
|
|
||||||
private GUIStyle _greenStyle;
|
|
||||||
private GUIStyle _redStyle;
|
|
||||||
|
|
||||||
|
|
||||||
private bool _isInit = false;
|
|
||||||
|
|
||||||
private void Init()
|
|
||||||
{
|
|
||||||
if (_isInit)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_greenStyle = EcsEditor.GetStyle(new Color32(75, 255, 0, 100));
|
|
||||||
_redStyle = EcsEditor.GetStyle(new Color32(255, 0, 75, 100));
|
|
||||||
|
|
||||||
|
|
||||||
_isInit = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
Init();
|
|
||||||
if (Target.IsAlive)
|
|
||||||
GUILayout.Box("Connected", _greenStyle, GUILayout.ExpandWidth(true));
|
|
||||||
else
|
|
||||||
GUILayout.Box("Not connected", _redStyle, GUILayout.ExpandWidth(true));
|
|
||||||
|
|
||||||
if(Target.Entity.TryGetID(out int id))
|
|
||||||
EditorGUILayout.IntField(id);
|
|
||||||
else
|
|
||||||
EditorGUILayout.IntField(0);
|
|
||||||
GUILayout.Label(Target.Entity.ToString());
|
|
||||||
|
|
||||||
base.OnInspectorGUI();
|
|
||||||
|
|
||||||
if(GUILayout.Button("Autoset Templates"))
|
|
||||||
{
|
|
||||||
Target.SetTemplates_Editor(Target.GetComponents<EntityTemplate>());
|
|
||||||
|
|
||||||
EditorUtility.SetDirty(target);
|
|
||||||
}
|
|
||||||
if (GUILayout.Button("Autoset Templates Cascade"))
|
|
||||||
{
|
|
||||||
foreach (var item in Target.GetComponentsInChildren<EcsEntityConnect>())
|
|
||||||
{
|
|
||||||
item.SetTemplates_Editor(item.GetComponents<EntityTemplate>());
|
|
||||||
EditorUtility.SetDirty(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
using DCFApixels.DragonECS.RunnersCore;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public interface IEcsLateRunProcess : IEcsSystem
|
|
||||||
{
|
|
||||||
public void LateRun(EcsPipeline pipeline);
|
|
||||||
}
|
|
||||||
public static class IEcsLateRunSystemExtensions
|
|
||||||
{
|
|
||||||
public static void LateRun(this EcsPipeline systems)
|
|
||||||
{
|
|
||||||
systems.GetRunner<IEcsLateRunProcess>().LateRun(systems);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public interface IEcsFixedRunProcess : IEcsSystem
|
|
||||||
{
|
|
||||||
public void FixedRun(EcsPipeline pipeline);
|
|
||||||
}
|
|
||||||
public static class IEcsFixedRunSystemExtensions
|
|
||||||
{
|
|
||||||
public static void FixedRun(this EcsPipeline pipeline)
|
|
||||||
{
|
|
||||||
pipeline.GetRunner<IEcsFixedRunProcess>().FixedRun(pipeline);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Internal
|
|
||||||
{
|
|
||||||
[DebugColor(DebugColor.Orange)]
|
|
||||||
public class EcsLateRunSystemRunner : EcsRunner<IEcsLateRunProcess>, IEcsLateRunProcess
|
|
||||||
{
|
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
|
||||||
private EcsProfilerMarker[] _markers;
|
|
||||||
#endif
|
|
||||||
public void LateRun(EcsPipeline pipeline)
|
|
||||||
{
|
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
|
||||||
for (int i = 0; i < targets.Length; i++)
|
|
||||||
{
|
|
||||||
using (_markers[i].Auto())
|
|
||||||
targets[i].LateRun(pipeline);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
foreach (var item in targets) item.LateRun(pipeline);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
|
||||||
protected override void OnSetup()
|
|
||||||
{
|
|
||||||
_markers = new EcsProfilerMarker[targets.Length];
|
|
||||||
for (int i = 0; i < targets.Length; i++)
|
|
||||||
{
|
|
||||||
_markers[i] = new EcsProfilerMarker(EcsDebug.RegisterMark($"EcsRunner.{targets[i].GetType().Name}.{nameof(LateRun)}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
[DebugColor(DebugColor.Orange)]
|
|
||||||
public class EcsFixedRunSystemRunner : EcsRunner<IEcsFixedRunProcess>, IEcsFixedRunProcess
|
|
||||||
{
|
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
|
||||||
private EcsProfilerMarker[] _markers;
|
|
||||||
#endif
|
|
||||||
public void FixedRun(EcsPipeline pipeline)
|
|
||||||
{
|
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
|
||||||
for (int i = 0; i < targets.Length; i++)
|
|
||||||
{
|
|
||||||
using (_markers[i].Auto())
|
|
||||||
targets[i].FixedRun(pipeline);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
foreach (var item in targets) item.FixedRun(pipeline);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG && !DISABLE_DEBUG
|
|
||||||
protected override void OnSetup()
|
|
||||||
{
|
|
||||||
_markers = new EcsProfilerMarker[targets.Length];
|
|
||||||
for (int i = 0; i < targets.Length; i++)
|
|
||||||
{
|
|
||||||
_markers[i] = new EcsProfilerMarker(EcsDebug.RegisterMark($"EcsRunner.{targets[i].GetType().Name}.{nameof(FixedRun)}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 385a6c66660032944ad2cce7130715d7
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
[DebugHide, DebugColor(DebugColor.Grey)]
|
|
||||||
public class DeleteOneFrameComponentFixedSystem<TWorld, TComponent> : IEcsFixedRunProcess, IEcsInject<TWorld>
|
|
||||||
where TWorld : EcsWorld<TWorld>
|
|
||||||
where TComponent : struct, IEcsComponent
|
|
||||||
{
|
|
||||||
private TWorld _world;
|
|
||||||
public void Inject(TWorld obj) => _world = obj;
|
|
||||||
|
|
||||||
private sealed class Subject : EcsSubject
|
|
||||||
{
|
|
||||||
public EcsPool<TComponent> pool;
|
|
||||||
public Subject(Builder b)
|
|
||||||
{
|
|
||||||
pool = b.Include<TComponent>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void FixedRun(EcsPipeline pipeline)
|
|
||||||
{
|
|
||||||
foreach (var e in _world.Where(out Subject s))
|
|
||||||
{
|
|
||||||
//try
|
|
||||||
//{
|
|
||||||
s.pool.Del(e);
|
|
||||||
//}
|
|
||||||
//catch (System.Exception)
|
|
||||||
//{
|
|
||||||
//
|
|
||||||
// throw;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DeleteOneFrameComponentFixedSystemExt
|
|
||||||
{
|
|
||||||
private const string AUTO_DEL_FIXED_LAYER = nameof(AUTO_DEL_FIXED_LAYER);
|
|
||||||
public static EcsPipeline.Builder AutoDelFixed<TWorld, TComponent>(this EcsPipeline.Builder b)
|
|
||||||
where TWorld : EcsWorld<TWorld>
|
|
||||||
where TComponent : struct, IEcsComponent
|
|
||||||
{
|
|
||||||
b.Layers.Insert(EcsConsts.POST_END_LAYER, AUTO_DEL_FIXED_LAYER);
|
|
||||||
b.AddUnique(new DeleteOneFrameComponentFixedSystem<TWorld, TComponent>(), AUTO_DEL_FIXED_LAYER);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
/// <summary> for EcsDefaultWorld </summary>
|
|
||||||
public static EcsPipeline.Builder AutoDelFixed<TComponent>(this EcsPipeline.Builder b)
|
|
||||||
where TComponent : struct, IEcsComponent
|
|
||||||
{
|
|
||||||
b.Layers.Insert(EcsConsts.POST_END_LAYER, AUTO_DEL_FIXED_LAYER);
|
|
||||||
b.AddUnique(new DeleteOneFrameComponentFixedSystem<EcsDefaultWorld, TComponent>(), AUTO_DEL_FIXED_LAYER);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e8c608fea9f3569409826ec54affa822
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Scripting.APIUpdating;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
[Serializable]
|
|
||||||
[DebugColor(255 / 3, 255, 0)]
|
|
||||||
public struct UnityComponent<T> : IEcsComponent, IEnumerable<T>//IntelliSense hack
|
|
||||||
where T : class
|
|
||||||
{
|
|
||||||
public T obj;
|
|
||||||
|
|
||||||
IEnumerator<T> IEnumerable<T>.GetEnumerator() => throw new NotImplementedException(); //IntelliSense hack
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); //IntelliSense hack
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
[MovedFrom(false, "Client", null, "RefRigitBodyInitializer")]
|
|
||||||
public sealed class UnityComponentRigitBodyInitializer : TemplateComponentInitializer<UnityComponent<Rigidbody>>
|
|
||||||
{
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<Rigidbody>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable]
|
|
||||||
[MovedFrom(false, "Client", null, "RefAnimatorInitializer")]
|
|
||||||
public sealed class UnityComponentAnimatorInitializer : TemplateComponentInitializer<UnityComponent<Animator>>
|
|
||||||
{
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<Animator>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentCharacterControllerInitializer : TemplateComponentInitializer<UnityComponent<CharacterController>>
|
|
||||||
{
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<CharacterController>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Colliders
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentColliderInitializer : TemplateComponentInitializer<UnityComponent<Collider>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Collider/" + nameof(Collider);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<Collider>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentBoxColliderInitializer : TemplateComponentInitializer<UnityComponent<BoxCollider>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Collider/" + nameof(BoxCollider);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<BoxCollider>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentSphereColliderInitializer : TemplateComponentInitializer<UnityComponent<SphereCollider>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Collider/" + nameof(SphereCollider);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<SphereCollider>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentCapsuleColliderInitializer : TemplateComponentInitializer<UnityComponent<CapsuleCollider>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Collider/" + nameof(CapsuleCollider);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<CapsuleCollider>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentMeshColliderInitializer : TemplateComponentInitializer<UnityComponent<MeshCollider>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Collider/" + nameof(MeshCollider);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<MeshCollider>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Joints
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentJointInitializer : TemplateComponentInitializer<UnityComponent<Joint>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Joint/" + nameof(Joint);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<Joint>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentFixedJointInitializer : TemplateComponentInitializer<UnityComponent<FixedJoint>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Joint/" + nameof(FixedJoint);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<FixedJoint>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentCharacterJointInitializer : TemplateComponentInitializer<UnityComponent<CharacterJoint>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Joint/" + nameof(CharacterJoint);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<CharacterJoint>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
[Serializable]
|
|
||||||
public sealed class UnityComponentConfigurableJointInitializer : TemplateComponentInitializer<UnityComponent<ConfigurableJoint>>
|
|
||||||
{
|
|
||||||
public override string Name => "UnityComponent/Joint/" + nameof(ConfigurableJoint);
|
|
||||||
public override void Add(EcsWorld w, int e) => w.GetPool<UnityComponent<ConfigurableJoint>>().Add(e) = component;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 909b2b01fa1e58b4e9e739827e36cff4
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS
|
|
||||||
{
|
|
||||||
public static class UnityWorldProvider<TWorld>
|
|
||||||
where TWorld : EcsWorld<TWorld>
|
|
||||||
{
|
|
||||||
private static TWorld _world;
|
|
||||||
|
|
||||||
public static TWorld Get(Func<TWorld> builder)
|
|
||||||
{
|
|
||||||
if (builder == null)
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
|
|
||||||
if (_world == null)
|
|
||||||
_world = builder();
|
|
||||||
|
|
||||||
return _world;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static TWorld Get()
|
|
||||||
{
|
|
||||||
if (_world == null)
|
|
||||||
_world = (TWorld)Activator.CreateInstance(typeof(TWorld));
|
|
||||||
return _world;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d0af8ddc3edb89242a26c1d308a18c87
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
8
src/Internal.meta
Normal file
8
src/Internal.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fc246fdeda320b649899ee44aca24e18
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,7 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace DCFApixels.DragonECS.Editors
|
namespace DCFApixels.DragonECS.Unity.Internal
|
||||||
{
|
{
|
||||||
internal class BitMask
|
internal class BitMask
|
||||||
{
|
{
|
||||||
@ -21,21 +21,30 @@ namespace DCFApixels.DragonECS.Editors
|
|||||||
public bool this[int index]
|
public bool this[int index]
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get => (_data[index >> OFFSET] & (1 << (index & MOD_MASK))) != 0;
|
get
|
||||||
|
{
|
||||||
|
return (_data[index >> OFFSET] & (1 << (index & MOD_MASK))) != 0;
|
||||||
|
}
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if(value)
|
if (value)
|
||||||
|
{
|
||||||
_data[index >> OFFSET] |= (1 << (index & MOD_MASK));
|
_data[index >> OFFSET] |= (1 << (index & MOD_MASK));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
_data[index >> OFFSET] &= ~(1 << (index & MOD_MASK));
|
_data[index >> OFFSET] &= ~(1 << (index & MOD_MASK));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Resize(int newSize)
|
public void Resize(int newSize)
|
||||||
{
|
{
|
||||||
if (newSize <= _size)
|
if (newSize <= _size)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_size = newSize / DATA_BITS + 1;
|
_size = newSize / DATA_BITS + 1;
|
||||||
Array.Resize(ref _data, _size);
|
Array.Resize(ref _data, _size);
|
||||||
8
src/Internal/Editor.meta
Normal file
8
src/Internal/Editor.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 93ac43c51e44bbb459de81017f530fbe
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
502
src/Internal/Editor/EcsGUI.cs
Normal file
502
src/Internal/Editor/EcsGUI.cs
Normal file
@ -0,0 +1,502 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
internal static class EcsGUI
|
||||||
|
{
|
||||||
|
public struct ColorScope : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Color _oldColor;
|
||||||
|
public ColorScope(Color color)
|
||||||
|
{
|
||||||
|
_oldColor = GUI.color;
|
||||||
|
GUI.color = color;
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GUI.color = _oldColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ContentColorScope : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Color _oldColor;
|
||||||
|
public ContentColorScope(Color color)
|
||||||
|
{
|
||||||
|
_oldColor = GUI.contentColor;
|
||||||
|
GUI.contentColor = color;
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
GUI.contentColor = _oldColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal readonly static Color GrayColor = new Color32(100, 100, 100, 255);
|
||||||
|
internal readonly static Color GreenColor = new Color32(75, 255, 0, 255);
|
||||||
|
internal readonly static Color RedColor = new Color32(255, 0, 75, 255);
|
||||||
|
|
||||||
|
private static readonly Rect RemoveButtonRect = new Rect(0f, 0f, 19f, 19f);
|
||||||
|
private static readonly Rect TooltipIconRect = new Rect(0f, 0f, 19f, 19f);
|
||||||
|
|
||||||
|
public static float EntityBarHeight => EditorGUIUtility.singleLineHeight + 3f;
|
||||||
|
|
||||||
|
private static bool IsShowHidden
|
||||||
|
{
|
||||||
|
get { return SettingsPrefs.instance.IsShowHidden; }
|
||||||
|
set { SettingsPrefs.instance.IsShowHidden = value; }
|
||||||
|
}
|
||||||
|
private static bool IsShowRuntimeComponents
|
||||||
|
{
|
||||||
|
get { return SettingsPrefs.instance.IsShowRuntimeComponents; }
|
||||||
|
set { SettingsPrefs.instance.IsShowRuntimeComponents = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AddClearComponentButton : byte
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
AddComponent,
|
||||||
|
Clear,
|
||||||
|
}
|
||||||
|
[Flags]
|
||||||
|
public enum EntityStatus
|
||||||
|
{
|
||||||
|
NotAlive = 0,
|
||||||
|
Alive = 1 << 0,
|
||||||
|
Undefined = 1 << 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
//private static GUILayoutOption[] _defaultParams;
|
||||||
|
//private static bool _isInit = false;
|
||||||
|
//private static void Init()
|
||||||
|
//{
|
||||||
|
// if (_isInit)
|
||||||
|
// {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// _defaultParams = new GUILayoutOption[] { GUILayout.ExpandWidth(true) };
|
||||||
|
// _isInit = true;
|
||||||
|
//}
|
||||||
|
|
||||||
|
internal static bool HitTest(Rect rect)
|
||||||
|
{
|
||||||
|
return HitTest(rect, Event.current.mousePosition);
|
||||||
|
}
|
||||||
|
internal static bool HitTest(Rect rect, Event evt)
|
||||||
|
{
|
||||||
|
return HitTest(rect, evt.mousePosition);
|
||||||
|
}
|
||||||
|
internal static bool HitTest(Rect rect, Vector2 point)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
return HitTest(rect, point, offset);
|
||||||
|
}
|
||||||
|
internal static bool HitTest(Rect rect, Vector2 point, int offset)
|
||||||
|
{
|
||||||
|
return point.x >= rect.xMin - (float)offset && point.x < rect.xMax + (float)offset && point.y >= rect.yMin - (float)offset && point.y < rect.yMax + (float)offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//public static bool IconButton(Rect position, Texture normal, Texture hover, GUIStyle normalStyle = null, GUIStyle hoverStyle = null)
|
||||||
|
//{
|
||||||
|
// Color dc = GUI.color;
|
||||||
|
// GUI.color = Color.clear; //Хак чтобы сделать реакцию от курсора мыши без лага
|
||||||
|
// bool result = GUI.Button(position, "", EditorStyles.miniButtonMid);
|
||||||
|
// GUI.color = dc;
|
||||||
|
//
|
||||||
|
// var current = Event.current;
|
||||||
|
// {
|
||||||
|
// if (HitTest(position, current))
|
||||||
|
// {
|
||||||
|
// if (hoverStyle != null && Event.current.type == EventType.Repaint)
|
||||||
|
// {
|
||||||
|
// hoverStyle.Draw(position, true, false, false, false);
|
||||||
|
// }
|
||||||
|
// GUI.DrawTexture(position, hover);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if (normalStyle != null && Event.current.type == EventType.Repaint)
|
||||||
|
// {
|
||||||
|
// normalStyle.Draw(position, false, false, false, false);
|
||||||
|
// }
|
||||||
|
// GUI.DrawTexture(position, normal);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return result;
|
||||||
|
//}
|
||||||
|
public static (bool, bool) IconButtonGeneric(Rect position)
|
||||||
|
{
|
||||||
|
Color dc = GUI.color;
|
||||||
|
GUI.color = Color.clear; //Хак чтобы сделать реакцию от курсора мыши без лага
|
||||||
|
bool result = GUI.Button(position, "", EditorStyles.miniButtonMid);
|
||||||
|
GUI.color = dc;
|
||||||
|
|
||||||
|
var current = Event.current;
|
||||||
|
return (GUI.enabled && HitTest(position, current), result);
|
||||||
|
}
|
||||||
|
public static bool IconButton(Rect position, Texture icon, float iconPadding, string description)
|
||||||
|
{
|
||||||
|
//var (hover, click) = IconButton(position);
|
||||||
|
//Color color = GUI.color;
|
||||||
|
//float enableMultiplier = GUI.enabled ? 1f : 0.72f;
|
||||||
|
//
|
||||||
|
//if (hover)
|
||||||
|
//{
|
||||||
|
// if (Event.current.type == EventType.Repaint)
|
||||||
|
// {
|
||||||
|
// GUI.color = Color.white * 2.2f * enableMultiplier;
|
||||||
|
// EditorStyles.helpBox.Draw(position, hover, false, false, false);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Rect rect = RectUtility.AddPadding(position, -1f);
|
||||||
|
// GUI.color = Color.white * enableMultiplier;
|
||||||
|
// GUI.DrawTexture(rect, icon);
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// if (Event.current.type == EventType.Repaint)
|
||||||
|
// {
|
||||||
|
// GUI.color = Color.white * 1.7f * enableMultiplier;
|
||||||
|
// EditorStyles.helpBox.Draw(position, hover, false, false, false);
|
||||||
|
// }
|
||||||
|
// GUI.color = Color.white * enableMultiplier;
|
||||||
|
// GUI.DrawTexture(position, icon);
|
||||||
|
//}
|
||||||
|
//GUI.color = color;
|
||||||
|
//return click;
|
||||||
|
|
||||||
|
bool result = GUI.Button(position, UnityEditorUtility.GetLabel(string.Empty));
|
||||||
|
GUI.Label(RectUtility.AddPadding(position, iconPadding), UnityEditorUtility.GetLabel(icon, description));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public static void DescriptionIcon(Rect position, string description)
|
||||||
|
{
|
||||||
|
using (new ColorScope(new Color(1f, 1f, 1f, 0.8f)))
|
||||||
|
{
|
||||||
|
GUIContent descriptionLabel = UnityEditorUtility.GetLabel(EditorGUIUtility.IconContent("d__Help").image, description);
|
||||||
|
GUI.Label(position, descriptionLabel, EditorStyles.boldLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool CloseButton(Rect position)
|
||||||
|
{
|
||||||
|
using (new ColorScope(new Color(1f, 1f, 1f, 0.8f)))
|
||||||
|
{
|
||||||
|
var (hover, click) = IconButtonGeneric(position);
|
||||||
|
if (hover)
|
||||||
|
{
|
||||||
|
Rect rect = RectUtility.AddPadding(position, -4f);
|
||||||
|
GUI.DrawTexture(rect, EditorGUIUtility.IconContent("P4_DeletedLocal@2x").image);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GUI.DrawTexture(position, EditorGUIUtility.IconContent("d_winbtn_win_close").image);
|
||||||
|
}
|
||||||
|
return click;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static bool AutosetCascadeButton(Rect position)
|
||||||
|
{
|
||||||
|
return IconButton(position, EditorGUIUtility.IconContent("d_winbtn_win_restore@2x").image, 0f, "Autoset Cascade");
|
||||||
|
}
|
||||||
|
public static bool AutosetButton(Rect position)
|
||||||
|
{
|
||||||
|
return IconButton(position, EditorGUIUtility.IconContent("d_winbtn_win_max@2x").image, 1f, "Autoset");
|
||||||
|
}
|
||||||
|
public static bool UnlinkButton(Rect position)
|
||||||
|
{
|
||||||
|
bool result = GUI.Button(position, UnityEditorUtility.GetLabel(string.Empty));
|
||||||
|
GUI.Label(RectUtility.Move(position, 0, -1f), UnityEditorUtility.GetLabel(EditorGUIUtility.IconContent("d_Unlinked").image, "Unlink Entity"));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public static bool DelEntityButton(Rect position)
|
||||||
|
{
|
||||||
|
return IconButton(position, EditorGUIUtility.IconContent("d_winbtn_win_close").image, 0f, "Delete Entity");
|
||||||
|
}
|
||||||
|
public static void EntityBar(Rect position, EntityStatus status, int id, short gen, short world)
|
||||||
|
{
|
||||||
|
var (entityInfoRect, statusRect) = RectUtility.VerticalSliceBottom(position, 3f);
|
||||||
|
|
||||||
|
Color w = Color.gray;
|
||||||
|
w.a = 0.6f;
|
||||||
|
Color b = Color.black;
|
||||||
|
b.a = 0.55f;
|
||||||
|
EditorGUI.DrawRect(entityInfoRect, w);
|
||||||
|
|
||||||
|
var (idRect, genWorldRect) = RectUtility.HorizontalSliceLerp(entityInfoRect, 0.4f);
|
||||||
|
var (genRect, worldRect) = RectUtility.HorizontalSliceLerp(genWorldRect, 0.5f);
|
||||||
|
|
||||||
|
idRect = RectUtility.AddPadding(idRect, 2, 1, 0, 0);
|
||||||
|
genRect = RectUtility.AddPadding(genRect, 1, 1, 0, 0);
|
||||||
|
worldRect = RectUtility.AddPadding(worldRect, 1, 2, 0, 0);
|
||||||
|
EditorGUI.DrawRect(idRect, b);
|
||||||
|
EditorGUI.DrawRect(genRect, b);
|
||||||
|
EditorGUI.DrawRect(worldRect, b);
|
||||||
|
|
||||||
|
|
||||||
|
GUIStyle style = new GUIStyle(EditorStyles.numberField);
|
||||||
|
style.alignment = TextAnchor.MiddleCenter;
|
||||||
|
style.font = EditorStyles.boldFont;
|
||||||
|
if (status == EntityStatus.Alive)
|
||||||
|
{
|
||||||
|
Color statusColor = EcsGUI.GreenColor;
|
||||||
|
statusColor.a = 0.6f;
|
||||||
|
EditorGUI.DrawRect(statusRect, statusColor);
|
||||||
|
|
||||||
|
EditorGUI.IntField(idRect, id, style);
|
||||||
|
EditorGUI.IntField(genRect, gen, style);
|
||||||
|
EditorGUI.IntField(worldRect, world, style);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Color statusColor = status == EntityStatus.Undefined ? new Color32(200, 200, 200, 255) : EcsGUI.RedColor;
|
||||||
|
statusColor.a = 0.6f;
|
||||||
|
EditorGUI.DrawRect(statusRect, statusColor);
|
||||||
|
|
||||||
|
using (new EditorGUI.DisabledScope(true))
|
||||||
|
{
|
||||||
|
GUI.Label(idRect, "Entity ID", style);
|
||||||
|
GUI.Label(genRect, "Generation", style);
|
||||||
|
GUI.Label(worldRect, "World ID", style);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool AddComponentButtons(Rect position)
|
||||||
|
{
|
||||||
|
position = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f);
|
||||||
|
return GUI.Button(position, "Add Component");
|
||||||
|
}
|
||||||
|
public static AddClearComponentButton AddClearComponentButtons(Rect position)
|
||||||
|
{
|
||||||
|
//Rect rect = GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f);
|
||||||
|
position = RectUtility.AddPadding(position, 20f, 20f, 12f, 2f);
|
||||||
|
var (left, right) = RectUtility.HorizontalSliceLerp(position, 0.75f);
|
||||||
|
|
||||||
|
if (GUI.Button(left, "Add Component"))
|
||||||
|
{
|
||||||
|
return AddClearComponentButton.AddComponent;
|
||||||
|
}
|
||||||
|
if (GUI.Button(right, "Clear"))
|
||||||
|
{
|
||||||
|
return AddClearComponentButton.Clear;
|
||||||
|
}
|
||||||
|
return AddClearComponentButton.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Layout
|
||||||
|
{
|
||||||
|
public static void DrawWorldBaseInfo(EcsWorld world)
|
||||||
|
{
|
||||||
|
bool isNull = world == null || world.id == 0;
|
||||||
|
int entitesCount = isNull ? 0 : world.Count;
|
||||||
|
int capacity = isNull ? 0 : world.Capacity;
|
||||||
|
int leakedEntitesCount = isNull ? 0 : world.CountLeakedEntitesDebug();
|
||||||
|
EditorGUILayout.IntField("Entities", entitesCount, EditorStyles.boldLabel);
|
||||||
|
EditorGUILayout.IntField("Capacity", capacity, EditorStyles.boldLabel);
|
||||||
|
Color color = leakedEntitesCount > 0 ? Color.yellow : GUI.contentColor;
|
||||||
|
using (new ContentColorScope(color))
|
||||||
|
{
|
||||||
|
EditorGUILayout.IntField("Leaked Entites", leakedEntitesCount, EditorStyles.boldLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void EntityBar(EntityStatus status, int id, short gen, short world)
|
||||||
|
{
|
||||||
|
float width = EditorGUIUtility.currentViewWidth;
|
||||||
|
float height = EntityBarHeight;
|
||||||
|
EcsGUI.EntityBar(GUILayoutUtility.GetRect(width, height), status, id, gen, world);
|
||||||
|
}
|
||||||
|
public static bool AddComponentButtons()
|
||||||
|
{
|
||||||
|
return EcsGUI.AddComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f));
|
||||||
|
}
|
||||||
|
public static AddClearComponentButton AddClearComponentButtons()
|
||||||
|
{
|
||||||
|
return EcsGUI.AddClearComponentButtons(GUILayoutUtility.GetRect(EditorGUIUtility.currentViewWidth, 36f));
|
||||||
|
}
|
||||||
|
public static void DrawRuntimeComponents(entlong entity, bool isWithFoldout = true)
|
||||||
|
{
|
||||||
|
if (entity.TryUnpack(out int entityID, out EcsWorld world))
|
||||||
|
{
|
||||||
|
DrawRuntimeComponents(entityID, world, isWithFoldout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void DrawRuntimeComponents(int entityID, EcsWorld world, bool isWithFoldout = true)
|
||||||
|
{
|
||||||
|
var componentTypeIDs = world.GetComponentTypeIDsFor(entityID);
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(Color.black, 0.2f));
|
||||||
|
|
||||||
|
if (isWithFoldout)
|
||||||
|
{
|
||||||
|
IsShowRuntimeComponents = EditorGUILayout.BeginFoldoutHeaderGroup(IsShowRuntimeComponents, "RUNTIME COMPONENTS", EditorStyles.foldout);
|
||||||
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||||
|
}
|
||||||
|
if (isWithFoldout == false || IsShowRuntimeComponents)
|
||||||
|
{
|
||||||
|
if (EcsGUI.Layout.AddComponentButtons())
|
||||||
|
{
|
||||||
|
GenericMenu genericMenu = RuntimeComponentsUtility.GetAddComponentGenericMenu(world);
|
||||||
|
RuntimeComponentsUtility.CurrentEntityID = entityID;
|
||||||
|
genericMenu.ShowAsContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.Box("", UnityEditorUtility.GetStyle(GUI.color, 0.16f), GUILayout.ExpandWidth(true));
|
||||||
|
IsShowHidden = EditorGUI.Toggle(GUILayoutUtility.GetLastRect(), "Show Hidden", IsShowHidden);
|
||||||
|
|
||||||
|
foreach (var componentTypeID in componentTypeIDs)
|
||||||
|
{
|
||||||
|
var pool = world.GetPoolInstance(componentTypeID);
|
||||||
|
{
|
||||||
|
DrawRuntimeComponent(entityID, pool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
private static readonly BindingFlags fieldFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||||
|
private static void DrawRuntimeComponent(int entityID, IEcsPool pool)
|
||||||
|
{
|
||||||
|
var meta = pool.ComponentType.ToMeta();
|
||||||
|
if (meta.IsHidden == false || IsShowHidden)
|
||||||
|
{
|
||||||
|
object data = pool.GetRaw(entityID);
|
||||||
|
Color panelColor = meta.Color.ToUnityColor().Desaturate(EscEditorConsts.COMPONENT_DRAWER_DESATURATE);
|
||||||
|
|
||||||
|
float padding = EditorGUIUtility.standardVerticalSpacing;
|
||||||
|
Rect removeButtonRect = GUILayoutUtility.GetLastRect();
|
||||||
|
|
||||||
|
GUILayout.BeginVertical(UnityEditorUtility.GetStyle(panelColor, EscEditorConsts.COMPONENT_DRAWER_ALPHA));
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
|
||||||
|
bool isRemoveComponent = false;
|
||||||
|
removeButtonRect.yMin = removeButtonRect.yMax;
|
||||||
|
removeButtonRect.yMax += RemoveButtonRect.height;
|
||||||
|
removeButtonRect.xMin = removeButtonRect.xMax - RemoveButtonRect.width;
|
||||||
|
removeButtonRect.center += Vector2.up * padding * 2f;
|
||||||
|
if (EcsGUI.CloseButton(removeButtonRect))
|
||||||
|
{
|
||||||
|
isRemoveComponent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type componentType = pool.ComponentType;
|
||||||
|
ExpandMatrix expandMatrix = ExpandMatrix.Take(componentType);
|
||||||
|
bool changed = DrawRuntimeData(componentType, UnityEditorUtility.GetLabel(meta.Name), expandMatrix, data, out object resultData);
|
||||||
|
if (changed || isRemoveComponent)
|
||||||
|
{
|
||||||
|
if (isRemoveComponent)
|
||||||
|
{
|
||||||
|
pool.Del(entityID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pool.SetRaw(entityID, resultData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(meta.Description) == false)
|
||||||
|
{
|
||||||
|
Rect tooltipIconRect = TooltipIconRect;
|
||||||
|
tooltipIconRect.center = removeButtonRect.center;
|
||||||
|
tooltipIconRect.center -= Vector2.right * tooltipIconRect.width;
|
||||||
|
EcsGUI.DescriptionIcon(tooltipIconRect, meta.Description);
|
||||||
|
}
|
||||||
|
|
||||||
|
GUILayout.EndVertical();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool DrawRuntimeData(Type fieldType, GUIContent label, ExpandMatrix expandMatrix, object data, out object outData)
|
||||||
|
{
|
||||||
|
outData = data;
|
||||||
|
Type type = data == null ? typeof(void) : data.GetType();
|
||||||
|
|
||||||
|
bool isUnityObject = typeof(UnityEngine.Object).IsAssignableFrom(fieldType);
|
||||||
|
|
||||||
|
if (isUnityObject == false && data == null)
|
||||||
|
{
|
||||||
|
EditorGUILayout.TextField(label, "Null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ref bool isExpanded = ref expandMatrix.Down();
|
||||||
|
bool changed = false;
|
||||||
|
outData = data;
|
||||||
|
|
||||||
|
if (isUnityObject == false && (type.IsGenericType || !type.IsSerializable))
|
||||||
|
{
|
||||||
|
isExpanded = EditorGUILayout.BeginFoldoutHeaderGroup(isExpanded, label, EditorStyles.foldout);
|
||||||
|
EditorGUILayout.EndFoldoutHeaderGroup();
|
||||||
|
|
||||||
|
if (isExpanded)
|
||||||
|
{
|
||||||
|
EditorGUI.indentLevel++;
|
||||||
|
foreach (var field in type.GetFields(fieldFlags))
|
||||||
|
{
|
||||||
|
GUIContent subLabel = UnityEditorUtility.GetLabel(UnityEditorUtility.TransformFieldName(field.Name));
|
||||||
|
if (DrawRuntimeData(field.FieldType, subLabel, expandMatrix, field.GetValue(data), out object fieldData))
|
||||||
|
{
|
||||||
|
field.SetValue(data, fieldData);
|
||||||
|
outData = data;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EditorGUI.indentLevel--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isUnityObject)
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
var uobj = (UnityEngine.Object)data;
|
||||||
|
|
||||||
|
bool isComponent = (typeof(UnityEngine.Component)).IsAssignableFrom(fieldType);
|
||||||
|
if (isComponent)
|
||||||
|
{
|
||||||
|
uobj = EditorGUILayout.ObjectField(label, uobj, typeof(UnityEngine.Object), true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uobj = EditorGUILayout.ObjectField(label, uobj, fieldType, true);
|
||||||
|
}
|
||||||
|
if (isComponent && uobj is GameObject go)
|
||||||
|
{
|
||||||
|
uobj = go.GetComponent(fieldType);
|
||||||
|
}
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
outData = uobj;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EditorGUI.BeginChangeCheck();
|
||||||
|
WrapperBase w = RefEditorWrapper.Take(data);
|
||||||
|
|
||||||
|
w.IsExpanded = isExpanded;
|
||||||
|
EditorGUILayout.PropertyField(w.Property, label, true);
|
||||||
|
isExpanded = w.IsExpanded;
|
||||||
|
|
||||||
|
if (EditorGUI.EndChangeCheck())
|
||||||
|
{
|
||||||
|
w.SO.ApplyModifiedProperties();
|
||||||
|
outData = w.Data;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
w.Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expandMatrix.Up();
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Internal/Editor/EcsGUI.cs.meta
Normal file
11
src/Internal/Editor/EcsGUI.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f27d7dd0452a826479d2b19d7885ce49
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
57
src/Internal/Editor/ExpandMatrix.cs
Normal file
57
src/Internal/Editor/ExpandMatrix.cs
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
internal class ExpandMatrix
|
||||||
|
{
|
||||||
|
private const bool TOP_DEFAULT = true;
|
||||||
|
private const bool DEFAULT = false;
|
||||||
|
private static Dictionary<Type, ExpandMatrix> _instances = new Dictionary<Type, ExpandMatrix>();
|
||||||
|
public static ExpandMatrix Take(Type type)
|
||||||
|
{
|
||||||
|
if (_instances.TryGetValue(type, out ExpandMatrix result) == false)
|
||||||
|
{
|
||||||
|
result = new ExpandMatrix();
|
||||||
|
_instances.Add(type, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
private bool[] _flags = new bool[8];
|
||||||
|
private int _count = 0;
|
||||||
|
private int _ptr = 0;
|
||||||
|
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get { return _count; }
|
||||||
|
}
|
||||||
|
public ref bool CurrentIsExpanded
|
||||||
|
{
|
||||||
|
get { return ref _flags[_ptr]; }
|
||||||
|
}
|
||||||
|
public void Up()
|
||||||
|
{
|
||||||
|
if (_ptr < 0)
|
||||||
|
{
|
||||||
|
throw new Exception("нарушение баланса инкремент/декремент");
|
||||||
|
}
|
||||||
|
_ptr--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref bool Down()
|
||||||
|
{
|
||||||
|
_ptr++;
|
||||||
|
if (_ptr >= _count)
|
||||||
|
{
|
||||||
|
if (_count >= _flags.Length)
|
||||||
|
{
|
||||||
|
Array.Resize(ref _flags, _flags.Length << 1);
|
||||||
|
}
|
||||||
|
_flags[_count++] = _ptr <= 1 ? TOP_DEFAULT : DEFAULT;
|
||||||
|
}
|
||||||
|
return ref _flags[_ptr];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Internal/Editor/ExpandMatrix.cs.meta
Normal file
11
src/Internal/Editor/ExpandMatrix.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fef04508ed32be24386f6b2a43e01b2c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
src/Internal/Editor/SOWrappers.meta
Normal file
8
src/Internal/Editor/SOWrappers.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fc9ef2bbe6a95624e9c6d50e19f38a05
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
36
src/Internal/Editor/SOWrappers/RefEditorWrapper.cs
Normal file
36
src/Internal/Editor/SOWrappers/RefEditorWrapper.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
internal class RefEditorWrapper : WrapperBase<RefEditorWrapper>
|
||||||
|
{
|
||||||
|
[SerializeReference]
|
||||||
|
public object data;
|
||||||
|
|
||||||
|
public override object Data
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return data; }
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static RefEditorWrapper Take(object data)
|
||||||
|
{
|
||||||
|
var result = Take();
|
||||||
|
result.data = data;
|
||||||
|
result.SO.Update();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
internal class EmptyDummy
|
||||||
|
{
|
||||||
|
public static readonly EmptyDummy Instance = new EmptyDummy();
|
||||||
|
private EmptyDummy() { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Internal/Editor/SOWrappers/RefEditorWrapper.cs.meta
Normal file
11
src/Internal/Editor/SOWrappers/RefEditorWrapper.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b0f14ae652b89744888db94704a170ef
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
92
src/Internal/Editor/SOWrappers/WrapperBase.cs
Normal file
92
src/Internal/Editor/SOWrappers/WrapperBase.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
internal abstract class WrapperBase : ScriptableObject
|
||||||
|
{
|
||||||
|
public abstract object Data { get; }
|
||||||
|
public abstract bool IsExpanded { get; set; }
|
||||||
|
public abstract SerializedObject SO { get; }
|
||||||
|
public abstract SerializedProperty Property { get; }
|
||||||
|
public abstract void Release();
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
internal abstract class WrapperBase<TSelf> : WrapperBase
|
||||||
|
where TSelf : WrapperBase<TSelf>
|
||||||
|
{
|
||||||
|
private SerializedObject _so;
|
||||||
|
private SerializedProperty _property;
|
||||||
|
|
||||||
|
private bool _isDestroyed = false;
|
||||||
|
private bool _isReleased = false;
|
||||||
|
|
||||||
|
private static Stack<TSelf> _wrappers = new Stack<TSelf>();
|
||||||
|
|
||||||
|
public override bool IsExpanded
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return Property.isExpanded; }
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
set { Property.isExpanded = value; }
|
||||||
|
}
|
||||||
|
public override SerializedObject SO
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _so; }
|
||||||
|
}
|
||||||
|
public override SerializedProperty Property
|
||||||
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
get { return _property; }
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TSelf Take()
|
||||||
|
{
|
||||||
|
TSelf result;
|
||||||
|
if (_wrappers.Count <= 0)
|
||||||
|
{
|
||||||
|
result = CreateInstance<TSelf>();
|
||||||
|
result._so = new SerializedObject(result);
|
||||||
|
result._property = result._so.FindProperty("data");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = _wrappers.Pop();
|
||||||
|
if (result._isDestroyed)
|
||||||
|
{
|
||||||
|
result = Take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result._isReleased = false;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void Release(TSelf wrapper)
|
||||||
|
{
|
||||||
|
if (wrapper._isReleased)
|
||||||
|
{
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
wrapper._isReleased = true;
|
||||||
|
_wrappers.Push(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy()
|
||||||
|
{
|
||||||
|
_isDestroyed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public override void Release()
|
||||||
|
{
|
||||||
|
Release((TSelf)this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/Internal/Editor/SOWrappers/WrapperBase.cs.meta
Normal file
11
src/Internal/Editor/SOWrappers/WrapperBase.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6c0cef58c08259f4bbb78af2fcec4c79
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
309
src/Internal/Editor/UnityEditorUtility.cs
Normal file
309
src/Internal/Editor/UnityEditorUtility.cs
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
#if UNITY_EDITOR
|
||||||
|
using DCFApixels.DragonECS.Unity.Internal;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using UnityEditor;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace DCFApixels.DragonECS.Unity.Editors
|
||||||
|
{
|
||||||
|
[InitializeOnLoad]
|
||||||
|
internal static class UnityEditorUtility
|
||||||
|
{
|
||||||
|
static UnityEditorUtility()
|
||||||
|
{
|
||||||
|
colorBoxeStyles = new SparseArray<GUIStyle>();
|
||||||
|
}
|
||||||
|
private static SparseArray<GUIStyle> colorBoxeStyles = new SparseArray<GUIStyle>();
|
||||||
|
private static GUIContent _singletonContent = null;
|
||||||
|
|
||||||
|
#region TransformFieldName
|
||||||
|
public static string TransformToUpperName(string name)
|
||||||
|
{
|
||||||
|
if (name.Length <= 0)
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
bool nextWorld = true;
|
||||||
|
bool prewIsUpper = false;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < name.Length; i++)
|
||||||
|
{
|
||||||
|
char c = name[i];
|
||||||
|
if (char.IsLetter(c) == false)
|
||||||
|
{
|
||||||
|
nextWorld = true;
|
||||||
|
prewIsUpper = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isUpper = char.IsUpper(c);
|
||||||
|
if (isUpper)
|
||||||
|
{
|
||||||
|
if (nextWorld == false && prewIsUpper == false)
|
||||||
|
{
|
||||||
|
b.Append('_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Append(char.ToUpper(c));
|
||||||
|
nextWorld = false;
|
||||||
|
prewIsUpper = isUpper;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string TransformFieldName(string name)
|
||||||
|
{
|
||||||
|
if (name.Length <= 0)
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
bool nextWorld = true;
|
||||||
|
bool prewIsUpper = false;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i = 0; i < name.Length; i++)
|
||||||
|
{
|
||||||
|
char c = name[i];
|
||||||
|
if (char.IsLetter(c) == false)
|
||||||
|
{
|
||||||
|
nextWorld = true;
|
||||||
|
prewIsUpper = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isUpper = char.IsUpper(c);
|
||||||
|
if (isUpper)
|
||||||
|
{
|
||||||
|
if (nextWorld == false && prewIsUpper == false)
|
||||||
|
{
|
||||||
|
b.Append(' ');
|
||||||
|
nextWorld = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextWorld)
|
||||||
|
{
|
||||||
|
b.Append(char.ToUpper(c));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
b.Append(c);
|
||||||
|
}
|
||||||
|
nextWorld = false;
|
||||||
|
prewIsUpper = isUpper;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.ToString();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Label
|
||||||
|
public static GUIContent GetLabelTemp()
|
||||||
|
{
|
||||||
|
if (_singletonContent == null)
|
||||||
|
{
|
||||||
|
_singletonContent = new GUIContent();
|
||||||
|
}
|
||||||
|
return _singletonContent;
|
||||||
|
}
|
||||||
|
public static GUIContent GetLabel(string name, string tooltip = null)
|
||||||
|
{
|
||||||
|
if (_singletonContent == null)
|
||||||
|
{
|
||||||
|
_singletonContent = new GUIContent();
|
||||||
|
}
|
||||||
|
_singletonContent.text = name;
|
||||||
|
_singletonContent.image = null;
|
||||||
|
_singletonContent.tooltip = tooltip;
|
||||||
|
return _singletonContent;
|
||||||
|
}
|
||||||
|
public static GUIContent GetLabel(Texture image, string tooltip = null)
|
||||||
|
{
|
||||||
|
if (_singletonContent == null)
|
||||||
|
{
|
||||||
|
_singletonContent = new GUIContent();
|
||||||
|
}
|
||||||
|
_singletonContent.text = string.Empty;
|
||||||
|
_singletonContent.image = image;
|
||||||
|
_singletonContent.tooltip = tooltip;
|
||||||
|
return _singletonContent;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region GetStyle
|
||||||
|
public static GUIStyle GetStyle(Color color, float alphaMultiplier)
|
||||||
|
{
|
||||||
|
color.a *= alphaMultiplier;
|
||||||
|
return GetStyle(color);
|
||||||
|
}
|
||||||
|
public static GUIStyle GetStyle(Color32 color32)
|
||||||
|
{
|
||||||
|
int colorCode = new Color32Union(color32).colorCode;
|
||||||
|
if (colorBoxeStyles.TryGetValue(colorCode, out GUIStyle style))
|
||||||
|
{
|
||||||
|
if (style == null || style.normal.background == null)
|
||||||
|
{
|
||||||
|
style = CreateStyle(color32, colorCode);
|
||||||
|
colorBoxeStyles[colorCode] = style;
|
||||||
|
}
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
style = CreateStyle(color32, colorCode);
|
||||||
|
colorBoxeStyles.Add(colorCode, style);
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
private static GUIStyle CreateStyle(Color32 color32, int colorCode)
|
||||||
|
{
|
||||||
|
GUIStyle result = new GUIStyle(GUI.skin.box);
|
||||||
|
Color componentColor = color32;
|
||||||
|
Texture2D texture2D = CreateTexture(2, 2, componentColor);
|
||||||
|
result.hover.background = texture2D;
|
||||||
|
result.focused.background = texture2D;
|
||||||
|
result.active.background = texture2D;
|
||||||
|
result.normal.background = texture2D;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
private static Texture2D CreateTexture(int width, int height, Color color)
|
||||||
|
{
|
||||||
|
var pixels = new Color[width * height];
|
||||||
|
for (var i = 0; i < pixels.Length; ++i)
|
||||||
|
pixels[i] = color;
|
||||||
|
|
||||||
|
var result = new Texture2D(width, height);
|
||||||
|
result.SetPixels(pixels);
|
||||||
|
result.Apply();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Utils
|
||||||
|
[StructLayout(LayoutKind.Explicit, Pack = 1, Size = 4)]
|
||||||
|
private readonly ref struct Color32Union
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public readonly int colorCode;
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public readonly byte r;
|
||||||
|
[FieldOffset(1)]
|
||||||
|
public readonly byte g;
|
||||||
|
[FieldOffset(2)]
|
||||||
|
public readonly byte b;
|
||||||
|
[FieldOffset(3)]
|
||||||
|
public readonly byte a;
|
||||||
|
public Color32Union(byte r, byte g, byte b, byte a) : this()
|
||||||
|
{
|
||||||
|
this.r = r;
|
||||||
|
this.g = g;
|
||||||
|
this.b = b;
|
||||||
|
this.a = a;
|
||||||
|
}
|
||||||
|
public Color32Union(Color32 color) : this()
|
||||||
|
{
|
||||||
|
r = color.r;
|
||||||
|
g = color.g;
|
||||||
|
b = color.b;
|
||||||
|
a = color.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class RuntimeComponentsUtility
|
||||||
|
{
|
||||||
|
public struct WorldData
|
||||||
|
{
|
||||||
|
public GenericMenu addComponentGenericMenu;
|
||||||
|
public int poolsCount;
|
||||||
|
public WorldData(GenericMenu addComponentGenericMenu, int poolsCount)
|
||||||
|
{
|
||||||
|
this.addComponentGenericMenu = addComponentGenericMenu;
|
||||||
|
this.poolsCount = poolsCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//world id
|
||||||
|
private static Dictionary<EcsWorld, WorldData> _worldDatas = new Dictionary<EcsWorld, WorldData>();
|
||||||
|
|
||||||
|
public static GenericMenu GetAddComponentGenericMenu(EcsWorld world)
|
||||||
|
{
|
||||||
|
if (_worldDatas.TryGetValue(world, out WorldData data))
|
||||||
|
{
|
||||||
|
if (data.poolsCount != world.PoolsCount)
|
||||||
|
{
|
||||||
|
data = CreateWorldData(world);
|
||||||
|
_worldDatas[world] = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = CreateWorldData(world);
|
||||||
|
_worldDatas[world] = data;
|
||||||
|
world.AddListener(new Listener(world));
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.addComponentGenericMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WorldData CreateWorldData(EcsWorld world)
|
||||||
|
{
|
||||||
|
GenericMenu genericMenu = new GenericMenu();
|
||||||
|
|
||||||
|
var pools = world.AllPools;
|
||||||
|
for (int i = 0; i < world.PoolsCount; i++)
|
||||||
|
{
|
||||||
|
var pool = pools[i];
|
||||||
|
if (pool.IsNullOrDummy())
|
||||||
|
{
|
||||||
|
i--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var meta = pool.ComponentType.ToMeta();
|
||||||
|
|
||||||
|
genericMenu.AddItem(new GUIContent(meta.Name, meta.Description), false, OnAddComponent, pool);
|
||||||
|
}
|
||||||
|
return new WorldData(genericMenu, world.PoolsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int CurrentEntityID = 0;
|
||||||
|
|
||||||
|
private static void OnAddComponent(object userData)
|
||||||
|
{
|
||||||
|
IEcsPool pool = (IEcsPool)userData;
|
||||||
|
if (pool.World.IsUsed(CurrentEntityID) == false)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pool.Has(CurrentEntityID) == false)
|
||||||
|
{
|
||||||
|
pool.AddRaw(CurrentEntityID, Activator.CreateInstance(pool.ComponentType));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Entity({CurrentEntityID}) already has component {EcsDebugUtility.GetGenericTypeName(pool.ComponentType)}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Listener : IEcsWorldEventListener
|
||||||
|
{
|
||||||
|
private EcsWorld _world;
|
||||||
|
public Listener(EcsWorld world)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
}
|
||||||
|
public void OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) { }
|
||||||
|
public void OnWorldDestroy()
|
||||||
|
{
|
||||||
|
_worldDatas.Remove(_world);
|
||||||
|
}
|
||||||
|
public void OnWorldResize(int newSize) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user