Kaynağa Gözat

ECSView ET组件可视化添加 (#86)

1.增加编辑器内Hierarchy视图查看ET组件树
2.计划添加Inspector视图查看组件属性
HongXiao 7 yıl önce
ebeveyn
işleme
4ae00dd743

+ 38 - 9
Unity/Assets/Scripts/Base/Object/Component.cs

@@ -3,7 +3,7 @@ using MongoDB.Bson.Serialization.Attributes;
 
 namespace ETModel
 {
-	[BsonIgnoreExtraElements]
+    [BsonIgnoreExtraElements]
 	public abstract class Component : Object, IDisposable, IComponentSerialize
 	{
 		// 只有Game.EventSystem.Add方法中会设置该值,如果new出来的对象不想加入Game.EventSystem中,则需要自己在构造函数中设置
@@ -31,7 +31,10 @@ namespace ETModel
 
 				this.InstanceId = IdGenerater.GenerateId();
 				Game.EventSystem.Add(this);
-			}
+#if UNITY_EDITOR
+                ECSView.SetParent(this);
+#endif
+            }
 		}
 
 		[BsonIgnore]
@@ -42,11 +45,23 @@ namespace ETModel
 				return this.InstanceId == 0;
 			}
 		}
-		
-		[BsonIgnore]
-		public Component Parent { get; set; }
 
-		public T GetParent<T>() where T : Component
+        [BsonIgnore]
+        private Component parent;
+        [BsonIgnore]
+        public Component Parent
+        {
+            get { return parent; }
+            set
+            {
+                parent = value;
+#if UNITY_EDITOR
+                ECSView.SetParent(this, parent);
+#endif
+            }
+        }
+
+        public T GetParent<T>() where T : Component
 		{
 			return this.Parent as T;
 		}
@@ -62,6 +77,9 @@ namespace ETModel
 		
 		protected Component()
 		{
+#if UNITY_EDITOR
+            ECSView.CreateView(this);
+#endif
 		}
 
 		public virtual void Dispose()
@@ -77,14 +95,25 @@ namespace ETModel
 			Game.EventSystem.Remove(this.InstanceId);
 			
 			this.InstanceId = 0;
-
+#if UNITY_EDITOR
 			if (this.IsFromPool)
 			{
 				Game.ObjectPool.Recycle(this);
+                ECSView.ReturnPool(this);
 			}
-		}
+            else
+            {
+                ECSView.DestroyView(this);
+            }
+#else
+            if (this.IsFromPool)
+            {
+                Game.ObjectPool.Recycle(this);
+            }
+#endif
+        }
 
-		public virtual void BeginSerialize()
+        public virtual void BeginSerialize()
 		{
 		}
 

+ 184 - 0
Unity/Assets/Scripts/Other/ECSView.cs

@@ -0,0 +1,184 @@
+#if UNITY_EDITOR
+using UnityEditor;
+#endif
+using UnityEngine;
+
+namespace ETModel
+{
+    /// <summary>
+    /// ET组件可视化
+    /// </summary>
+    public class ECSView : MonoBehaviour
+    {
+        #region Static Parts
+        /// <summary>
+        /// 组件与其对应可视化对象map
+        /// </summary>
+        private static DoubleMap<object, ECSView> _dic = new DoubleMap<object, ECSView>();
+
+        private static Transform root;
+        /// <summary>
+        /// 可视化对象根节点
+        /// </summary>
+        private static Transform Root
+        {
+            get
+            {
+                if (root == null)
+                {
+                    root = new GameObject("ETViewRoot").transform;
+                    DontDestroyOnLoad(root);
+                }
+                return root;
+            }
+        }
+        private static Transform pool;
+        /// <summary>
+        /// 组件放入Pool的可视化根节点
+        /// </summary>
+        private static Transform Pool
+        {
+            get
+            {
+                if (pool == null)
+                {
+                    pool = new GameObject("Pool").transform;
+                    pool.parent = Root;
+                }
+                return pool;
+            }
+        }
+        /// <summary>
+        /// 创建组件的可视化节点
+        /// </summary>
+        /// <param name="self"></param>
+        public static void CreateView(object self)
+        {
+            if (!Define.IsEditorMode)
+                return;
+            if (_dic.ContainsKey(self))
+                return;
+            ECSView view = new GameObject(self.GetType().ToString()).AddComponent<ECSView>();
+            view.Component = self;
+            _dic.Add(self, view);
+            SetParent(self);
+        }
+        /// <summary>
+        /// 销毁组件的可视化节点
+        /// </summary>
+        /// <param name="self"></param>
+        public static void DestroyView(object self)
+        {
+            if (!Define.IsEditorMode)
+                return;
+            if (_dic.ContainsKey(self))
+            {
+                ECSView view = _dic.GetValueByKey(self);
+                if (view != null)
+                    DestroyImmediate(view.gameObject);
+                _dic.RemoveByKey(self);
+            }
+        }
+        /// <summary>
+        /// 根据组件获取可视化节点
+        /// </summary>
+        /// <param name="self"></param>
+        /// <returns></returns>
+        public static ECSView GetView(object self)
+        {
+            if (!Define.IsEditorMode)
+                return null;
+            if (_dic.ContainsKey(self))
+                return _dic.GetValueByKey(self);
+            return null;
+        }
+        /// <summary>
+        /// 根据可视化节点获取其组件
+        /// </summary>
+        /// <param name="self"></param>
+        /// <returns></returns>
+        public static object GetComponent(ECSView self)
+        {
+            if (!Define.IsEditorMode)
+                return null;
+            if (_dic.ContainsValue(self))
+                return _dic.GetKeyByValue(self);
+            return null;
+        }
+        /// <summary>
+        /// 放入Pool操作,修改可视化节点到Pool节点下
+        /// </summary>
+        /// <param name="self"></param>
+        public static void ReturnPool(object self)
+        {
+            if (!Define.IsEditorMode)
+                return;
+            if (self == null)
+                return;
+            ECSView selfView = GetView(self);
+            if (selfView == null)
+            {
+                _dic.RemoveByKey(self);
+                return;
+            }
+            selfView.transform.parent = Pool;
+        }
+        /// <summary>
+        /// 设置可视化父对象
+        /// </summary>
+        /// <param name="self"></param>
+        /// <param name="parent"></param>
+        public static void SetParent(object self, object parent = null)
+        {
+            if (!Define.IsEditorMode)
+                return;
+            if (self == null)
+                return;
+            ECSView selfView = GetView(self);
+            if (selfView == null)
+            {
+                _dic.RemoveByKey(self);
+                return;
+            }
+            ECSView parentView = GetView(parent);
+            if (parentView != null)
+                selfView.transform.parent = parentView.transform;
+            else
+                selfView.transform.parent = Root;
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 该可视化节点对应的组件,对其属性显示到Inspector视图内
+        /// </summary>
+        public object Component;
+    }
+
+#if UNITY_EDITOR
+    [InitializeOnLoad]
+    public class MyHierarchyEditor
+    {
+        static MyHierarchyEditor()
+        {
+            EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyWindowItemOnGUI;
+        }
+
+        private static void OnHierarchyWindowItemOnGUI(int instanceID, Rect selectionRect)
+        {
+            GameObject obj = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
+            if (obj == null)
+                return;
+            if (obj.GetComponent<ECSView>() != null)
+            {
+                GUIStyle style = new GUIStyle(){
+                    padding ={ left =EditorStyles.label.padding.left-1, top = EditorStyles.label.padding.top },
+                    normal ={ textColor =Color.red }
+                };
+                GUI.Box(selectionRect, GUIContent.none);
+                GUI.Label(selectionRect, obj.name, style);
+            }
+        }
+    }
+#endif
+}

+ 13 - 0
Unity/Assets/Scripts/Other/ECSView.cs.meta

@@ -0,0 +1,13 @@
+fileFormatVersion: 2
+guid: f5a40ca22ac5ad54687060716411206f
+timeCreated: 1536830842
+licenseType: Pro
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 47 - 25
Unity/Hotfix/Base/Object/Component.cs

@@ -31,7 +31,9 @@ namespace ETHotfix
 
 				this.InstanceId = IdGenerater.GenerateId();
 				Game.EventSystem.Add(this);
-			}
+                if (Define.IsEditorMode)
+                    ECSView.SetParent(this);
+            }
 		}
 
 		[BsonIgnore]
@@ -43,10 +45,21 @@ namespace ETHotfix
 			}
 		}
 
-		[BsonIgnore]
-		public Component Parent { get; set; }
+        [BsonIgnore]
+        private Component parent;
+        [BsonIgnore]
+        public Component Parent
+        {
+            get { return parent; }
+            set
+            {
+                parent = value;
+                if (Define.IsEditorMode)
+                    ECSView.SetParent(this, parent);
+            }
+        }
 
-		public T GetParent<T>() where T : Component
+        public T GetParent<T>() where T : Component
 		{
 			return this.Parent as T;
 		}
@@ -60,31 +73,40 @@ namespace ETHotfix
 			}
 		}
 
-		protected Component()
-		{
-		}
-		
-		public virtual void Dispose()
-		{
-			if (this.IsDisposed)
-			{
-				return;
-			}
-			
-			// 触发Destroy事件
-			Game.EventSystem.Destroy(this);
+        protected Component()
+        {
+            if (Define.IsEditorMode)
+                ECSView.CreateView(this);
+        }
 
-			Game.EventSystem.Remove(this.InstanceId);
+        public virtual void Dispose()
+        {
+            if (this.IsDisposed)
+            {
+                return;
+            }
 
-			this.InstanceId = 0;
+            // 触发Destroy事件
+            Game.EventSystem.Destroy(this);
 
-			if (this.IsFromPool)
-			{
-				Game.ObjectPool.Recycle(this);
-			}
-		}
+            Game.EventSystem.Remove(this.InstanceId);
+
+            this.InstanceId = 0;
+
+            if (this.IsFromPool)
+                Game.ObjectPool.Recycle(this);
+
+            if (Define.IsEditorMode)
+            {
+                if (this.IsFromPool)
+                    ECSView.ReturnPool(this);
+                else
+                    ECSView.DestroyView(this);
+            }
+
+        }
 
-		public virtual void BeginSerialize()
+        public virtual void BeginSerialize()
 		{
 		}