Kaynağa Gözat

增加行为树代码

tanghai 9 yıl önce
ebeveyn
işleme
bf5a32b65e
100 değiştirilmiş dosya ile 5335 ekleme ve 0 silme
  1. 9 0
      Unity/Assets/Editor/BehaviorTreeEditor.meta
  2. 92 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorBatchOperation.cs
  3. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorBatchOperation.cs.meta
  4. 32 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerUtility.cs
  5. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerUtility.cs.meta
  6. 177 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerWindow.cs
  7. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerWindow.cs.meta
  8. 639 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorManager.cs
  9. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorManager.cs.meta
  10. 69 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeConfigExtension.cs
  11. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeConfigExtension.cs.meta
  12. 154 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeData.cs
  13. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeData.cs.meta
  14. 23 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigEditor.cs
  15. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigEditor.cs.meta
  16. 59 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigExtension.cs
  17. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigExtension.cs.meta
  18. 38 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeData.cs
  19. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeData.cs.meta
  20. 26 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeMenu.cs
  21. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeMenu.cs.meta
  22. 160 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeNodeClassPopup.cs
  23. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeNodeClassPopup.cs.meta
  24. 171 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeOperateUtility.cs
  25. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeOperateUtility.cs.meta
  26. 13 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeTipsHelper.cs
  27. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeTipsHelper.cs.meta
  28. 36 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeToolWindow.cs
  29. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeToolWindow.cs.meta
  30. 242 0
      Unity/Assets/Editor/BehaviorTreeEditor/CustomArrayField.cs
  31. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/CustomArrayField.cs.meta
  32. 9 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event.meta
  33. 14 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeAfterChangeNodeTypeEvent_SelectNode.cs
  34. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeAfterChangeNodeTypeEvent_SelectNode.cs.meta
  35. 13 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeClickNodeEvent_SelectNode.cs
  36. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeClickNodeEvent_SelectNode.cs.meta
  37. 13 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeConnectStateEvent_HandleConnectLines.cs
  38. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeConnectStateEvent_HandleConnectLines.cs.meta
  39. 13 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeCreateNodeEvent_SelectNode.cs
  40. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeCreateNodeEvent_SelectNode.cs.meta
  41. 13 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeMouseInNodeEvent_HandleOperate.cs
  42. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeMouseInNodeEvent_HandleOperate.cs.meta
  43. 14 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeNewCreateClickEvent_CreateNode.cs
  44. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeNewCreateClickEvent_CreateNode.cs.meta
  45. 20 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectNode.cs
  46. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectNode.cs.meta
  47. 13 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectTree.cs
  48. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectTree.cs.meta
  49. 13 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_UpdatePropList.cs
  50. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_UpdatePropList.cs.meta
  51. 14 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeReplaceClickEvent_ReplaceNode.cs
  52. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeReplaceClickEvent_ReplaceNode.cs.meta
  53. 15 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRightDesignerDragEvent_ModifyRightBorder.cs
  54. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRightDesignerDragEvent_ModifyRightBorder.cs.meta
  55. 21 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRunTreeEvent_ShowDebugInfo.cs
  56. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRunTreeEvent_ShowDebugInfo.cs.meta
  57. 290 0
      Unity/Assets/Editor/BehaviorTreeEditor/ExportNodeTypeConfig.cs
  58. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/ExportNodeTypeConfig.cs.meta
  59. 172 0
      Unity/Assets/Editor/BehaviorTreeEditor/FoldoutNode.cs
  60. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/FoldoutNode.cs.meta
  61. 801 0
      Unity/Assets/Editor/BehaviorTreeEditor/GraphDesigner.cs
  62. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/GraphDesigner.cs.meta
  63. 373 0
      Unity/Assets/Editor/BehaviorTreeEditor/NodeDesigner.cs
  64. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/NodeDesigner.cs.meta
  65. 284 0
      Unity/Assets/Editor/BehaviorTreeEditor/NodeExtension.cs
  66. 12 0
      Unity/Assets/Editor/BehaviorTreeEditor/NodeExtension.cs.meta
  67. 9 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic.meta
  68. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/Bg.png
  69. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/Bg.png.meta
  70. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/BgLine.png
  71. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/BgLine.png.meta
  72. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/DragIcon.png
  73. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/DragIcon.png.meta
  74. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/Error.png
  75. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/Error.png.meta
  76. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/Execute.png
  77. 57 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/Execute.png.meta
  78. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/False.png
  79. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/False.png.meta
  80. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/HighLight.png
  81. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/HighLight.png.meta
  82. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/LeftConnect.png
  83. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/LeftConnect.png.meta
  84. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/RightConnect.png
  85. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/RightConnect.png.meta
  86. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/SelectHighLight.png
  87. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/SelectHighLight.png.meta
  88. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/ShiftIcon.png
  89. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/ShiftIcon.png.meta
  90. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/True.png
  91. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/True.png.meta
  92. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/blue.png
  93. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/blue.png.meta
  94. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/default.png
  95. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/default.png.meta
  96. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/green.png
  97. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/green.png.meta
  98. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/orange.png
  99. 56 0
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/orange.png.meta
  100. BIN
      Unity/Assets/Editor/BehaviorTreeEditor/Pic/pink.png

+ 9 - 0
Unity/Assets/Editor/BehaviorTreeEditor.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 0457d6384c56e2644bd61463d47f7017
+folderAsset: yes
+timeCreated: 1486452872
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 92 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorBatchOperation.cs

@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using Base;
+using Model;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+	public class BehaviorBatchOperation
+	{
+		public delegate void ExcuteTreeOperate(BehaviorTreeConfig treeConfig, string treePath);
+
+		public static Dictionary<int, BehaviorTreeConfig> mId2TreeDict = new Dictionary<int, BehaviorTreeConfig>();
+		public static Dictionary<string, ClientNodeTypeProto> mCientNodeDict;
+		public static Dictionary<string, bool> mUseNodeDict = new Dictionary<string, bool>();
+
+		public static void HasUseNode(NodeProto node, string treePath)
+		{
+			if (string.IsNullOrEmpty(node.name))
+			{
+				Log.Error($"node name can not be empty!! {treePath}");
+			}
+			if (!mUseNodeDict.ContainsKey(node.name))
+			{
+				Log.Warning($"{node.name} not exist!!!");
+			}
+			else
+			{
+				mUseNodeDict[node.name] = true;
+			}
+			for (int i = 0; i < node.children.Count; i++)
+			{
+				HasUseNode(node.children[i], treePath);
+			}
+		}
+
+        public static void SaveOneTree(BehaviorTreeConfig treeConfig, string treePath, params object[] paramList)
+		{
+			EditorUtility.SetDirty(treeConfig.gameObject);
+			AssetDatabase.SaveAssets();
+		}
+
+
+		public static void CheckHasName(BehaviorTreeConfig config, string path, string nodeName)
+		{
+			if (HasNode(config.RootNodeProto, nodeName))
+			{
+				Log.Info($"{nodeName}: {path}");
+			}
+		}
+
+		public static bool HasNode(NodeProto node, string name)
+		{
+			if (node.name == name)
+			{
+				return true;
+			}
+			for (int i = 0; i < node.children.Count; i++)
+			{
+				if (HasNode(node.children[i], name))
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+
+		public static bool HasNodeField(NodeProto node, Type searchType, string prefabPath)
+		{
+			FieldInfo[] fieldInfos = ExportNodeTypeConfig.GetFieldInfos(node.name);
+			foreach (var fieldInfo in fieldInfos)
+			{
+				if (fieldInfo.FieldType == searchType)
+				{
+					Log.Info($"{prefabPath}");
+					return true;
+				}
+			}
+			for (int i = 0; i < node.children.Count; i++)
+			{
+				if (HasNodeField(node.children[i], searchType, prefabPath))
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorBatchOperation.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: efaceecc0d53ec74088acfc8dccc57d1
+timeCreated: 1456310067
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 32 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerUtility.cs

@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+	public static class BehaviorDesignerUtility
+	{
+		private static readonly string ImagePathName = "Assets/Editor/BehaviorTreeEditor/Pic/";
+
+		private static readonly Dictionary<string, Texture2D> mTextureDict = new Dictionary<string, Texture2D>();
+
+		public static Texture2D GetTexture(string imageName)
+		{
+			if (!mTextureDict.ContainsKey(imageName))
+			{
+				Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(ImagePathName + imageName + ".png");
+				if (tex != null)
+				{
+					mTextureDict.Add(imageName, tex);
+				}
+			}
+			return mTextureDict[imageName];
+		}
+
+		public static void DrawConnection(Vector2 src, Vector2 dst)
+		{
+			Vector3[] linePoints = { src, dst };
+			Handles.DrawAAPolyLine(GetTexture("DarkTaskIdentifyCompact"), 3f, linePoints);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerUtility.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ce0da9cd0a3c87142b3f71a8f5816e2e
+timeCreated: 1445225656
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 177 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerWindow.cs

@@ -0,0 +1,177 @@
+using Model;
+using System;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+    public enum SubWinType
+    {
+        CreateNode,
+        ReplaceNode,
+    }
+	public class MessageBoxArgs: EventArgs
+	{
+		public string msg;
+	}
+
+	public class BehaviorDesignerWindow: EditorWindow
+	{
+		private GraphDesigner mGraphDesigner;
+		private PropertyDesigner mPropDesigner;
+        private RightDesigner mRightDesigner;
+        private static bool mShowSubWin;
+        private SubWinType mSubWinType;
+        private BehaviorTreeNodeClassPopup popUpMenu;
+        public GraphDesigner GraphDesigner
+		{
+			get
+			{
+				return this.mGraphDesigner;
+			}
+		}
+
+		public static BehaviorDesignerWindow Instance
+		{
+			get
+			{
+				return GetWindow<BehaviorDesignerWindow>(false, "行为树编辑器");
+			}
+		}
+        public static bool IsShowSubWin
+        {
+            get
+            {
+                return mShowSubWin;
+            }
+        }
+		public static void ShowWindow()
+		{
+            BehaviorDesignerWindow target = GetWindow<BehaviorDesignerWindow>("行为树编辑器", false);
+            target.minSize = new Vector2(600f, 500f);
+        }
+        public void ShowSubWin(Vector2 pos,SubWinType subWinType)
+        {
+            mShowSubWin = true;
+            popUpMenu.Show(windowRect, subWinType);
+            windowRect.position = pos;
+        }
+        public void CloseSubWin()
+        {
+            mShowSubWin = false;
+        }
+        public static Rect windowRect = new Rect(400, 250, 400, 550);//子窗口的大小和位置
+        public void DrawSubWindow()
+        {
+            BeginWindows();//标记开始区域所有弹出式窗口
+            windowRect = GUILayout.Window(1, windowRect, DoWindow, "行为树节点");//创建内联窗口,参数分别为id,大小位置,创建子窗口的组件的函数,标题
+            EndWindows();//标记结束
+        }
+        void DoWindow(int unusedWindowID)
+        {
+            popUpMenu.DrawSearchList();
+            GUI.DragWindow();//画出子窗口
+        }
+        public void Awake()
+        {
+			mGraphDesigner = ScriptableObject.CreateInstance<GraphDesigner>();
+			mPropDesigner = ScriptableObject.CreateInstance<PropertyDesigner>();
+           // mRightDesigner = new RightDesigner();
+            popUpMenu = new BehaviorTreeNodeClassPopup();
+            popUpMenu.GraphDesigner = mGraphDesigner;
+			//mGraphDesigner.onSelectTree();
+		}
+
+		public void OnGUI()
+		{
+			HandleEvents();
+			mPropDesigner?.Draw();
+			mGraphDesigner?.Draw(this.position);
+          //  mRightDesigner?.Draw();
+            if (mShowSubWin)
+            {
+                DrawSubWindow();
+            }
+            this.Repaint();
+		}
+
+		public void HandleEvents()
+		{
+			var e = Event.current;
+			switch (e.type)
+			{
+				case EventType.KeyUp:
+					if (e.keyCode == KeyCode.Escape || (e.keyCode == KeyCode.S && e.control))
+					{
+						BehaviorManager.GetInstance().SaveAll();
+					}
+                    else if (e.keyCode == KeyCode.F4)
+                    {
+                        BehaviorManager.GetInstance().SaveAll();
+                    }
+                    break;
+                case EventType.MouseDown:
+                    
+                    break;
+            }
+		}
+
+		public void OnDestroy()
+		{
+			BehaviorManager.GetInstance().Clear();
+		}
+
+		public void onUpdatePropList(params object[] list)
+		{
+			mPropDesigner.SetToolBar(0);
+		}
+
+		public void onShowMessage(params object[] list)
+		{
+			string msg = list[0].ToString();
+			this.ShowNotification(new GUIContent(msg));
+		}
+
+		public void OnSelectNode(params object[] list)
+		{
+            if (list.Length == 0)
+            {
+                Debug.LogError(" node list can not be null");
+                return;
+            }
+			mGraphDesigner.onSelectNode(list);
+			mPropDesigner.onSelectNode(list);
+    //      mRightDesigner.onSelectNode(list);
+		}
+
+		public void onStartConnect(NodeDesigner nodeDesigner, State state)
+		{
+			mGraphDesigner.onStartConnect(nodeDesigner, state);
+		}
+
+		public void onMouseInNode(BehaviorNodeData nodeData, NodeDesigner nodeDesigner)
+		{
+			mGraphDesigner.onMouseInNode(nodeData, nodeDesigner);
+		}
+
+		public void onCreateNode(string name, Vector2 pos)
+		{
+			mGraphDesigner.onCreateNode(name, pos);
+		}
+
+		public void onChangeNodeType(string name, Vector2 pos)
+		{
+			mGraphDesigner.onChangeNodeType(name, pos);
+		}
+
+		public NodeDesigner onCreateTree()
+		{
+			return mGraphDesigner.onCreateTree();
+		}
+        public void onDraggingRightDesigner(float deltaX)
+        {
+     //       mRightDesigner.onDraggingBorder(deltaX);
+        }    
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorDesignerWindow.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 720eaee451e99f7489b1943d53d9484a
+timeCreated: 1444988755
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 639 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorManager.cs

@@ -0,0 +1,639 @@
+using System;
+using System.Collections.Generic;
+using Model;
+using UnityEditor;
+using UnityEngine;
+using System.Reflection;
+using Base;
+using Object = UnityEngine.Object;
+
+namespace MyEditor
+{
+	public class BehaviorManager
+	{
+		public GameObject CurTreeGO { get; set; }
+		public BehaviorTreeData CurTree { get; set; }
+        public const int NodeIdStartIndex = 100000;
+        private int AutoID = NodeIdStartIndex;
+        private Dictionary<string, ClientNodeTypeProto> mName2NodeProtoDict = new Dictionary<string, ClientNodeTypeProto>(); //节点类型 name索引
+		private Dictionary<string, List<ClientNodeTypeProto>> mClassify2NodeProtoList = new Dictionary<string, List<ClientNodeTypeProto>>(); //节点分类 分类名索引
+		private readonly Dictionary<int, NodeDesignerProto> mId2DesignerDict = new Dictionary<int, NodeDesignerProto>();
+		private static BehaviorManager mInstance = new BehaviorManager();
+		public static List<List<long>> treePathList = new List<List<long>>();
+		public string selectNodeName;
+		public string selectNodeType;
+		public BehaviorTree CurBehaviorTree { get; set; }
+
+		public BehaviorTreeConfig BehaviorTreeConfig
+		{
+			get
+			{
+				return CurTreeGO?.GetComponent<BehaviorTreeConfig>();
+			}
+		}
+
+		public static BehaviorManager GetInstance()
+		{
+			if (mInstance == null)
+			{
+				mInstance = new BehaviorManager();
+			}
+			return mInstance;
+		}
+         
+		public Dictionary<string, List<ClientNodeTypeProto>> Classify2NodeProtoList
+		{
+			get
+			{
+				return mClassify2NodeProtoList;
+			}
+		}
+       
+        public List<ClientNodeTypeProto> AllNodeProtoList
+        {
+            get
+            {
+                List<ClientNodeTypeProto> list = new List<ClientNodeTypeProto>();
+                foreach (var item in BehaviorManager.GetInstance().Classify2NodeProtoList)
+                {
+                    foreach (var proto in item.Value)
+                    {
+                        list.Add(proto);
+                    }
+                }
+                return list;
+            }
+        }
+
+        //节点配置 get set
+        public ClientNodeTypeProto GetNodeTypeProto(string name)
+		{
+			ClientNodeTypeProto proto = ExportNodeTypeConfig.GetNodeTypeProtoFromDll(name);
+			return proto;
+		}
+
+		public void FilterClassify()
+		{
+			mClassify2NodeProtoList = new Dictionary<string, List<ClientNodeTypeProto>>();
+			foreach (var nodeType in mName2NodeProtoDict.Values)
+			{
+				if (nodeType.isDeprecated)
+				{
+					continue;
+				}
+				string classify = nodeType.classify;
+				if (classify == "")
+				{
+					classify = "未分类";
+				}
+				if (!mClassify2NodeProtoList.ContainsKey(classify))
+				{
+					mClassify2NodeProtoList.Add(classify, new List<ClientNodeTypeProto>());
+				}
+				mClassify2NodeProtoList[classify].Add(nodeType);
+			}
+		}
+
+		public int AutoNodeId()
+		{
+            return ++AutoID;
+		}
+         
+        public void NewLoadData()
+        {
+            LoadNodeTypeProto();
+            NewLoadPrefabTree();
+            FilterClassify();
+        }
+
+        public void LoadNodeTypeProto()
+		{
+			mName2NodeProtoDict = ExportNodeTypeConfig.ExportToDict();
+		}
+         
+        public void NewLoadPrefabTree()
+        {
+            BehaviorTreeConfig config = CurTreeGO.GetComponent<BehaviorTreeConfig>();
+            CurTree = BehaviorTreeConfigToTreeData(config);
+        }
+        
+      
+        public BehaviorTreeData BehaviorTreeConfigToTreeData(BehaviorTreeConfig config)
+        {
+            BehaviorTreeData tree = new BehaviorTreeData();
+            tree.Root = NodeConfigToNodeData(config.RootNodeConfig);
+            return tree;
+        }
+
+        public void printTree(BehaviorNodeData nodeData)
+		{
+			Log.Info($"printTree  :  {nodeData.nodeId} {nodeData}");
+			foreach (var data in nodeData.children)
+			{
+				printTree(data);
+			}
+		}
+        public bool CheckSatisfyInput()
+        {
+            NodeProto rootNode = NodeDataToNodeProto(CurTree.BehaviorNodeData);
+            return CheckNodeInput(rootNode);
+        }
+       
+		public bool CheckNodeInput(NodeProto nodeProto)
+		{
+			List<NodeFieldDesc> list = ExportNodeTypeConfig.GetNodeFieldInOutPutDescList(nodeProto.name, typeof (NodeInputAttribute));
+			foreach (var desc in list)
+			{
+				List<string> canInputList = GetCanInPutEnvKeyList(NodeProtoToNodeData(nodeProto), desc);
+				string value = nodeProto.args_dict.GetTreeDictValue(desc.type, desc.name)?.ToString();
+				List<string> resultList = canInputList.FindAll(str => { return str == value; });
+				if (resultList.Count == 0)
+				{
+					Log.Error($"{nodeProto.name}节点(id:{nodeProto.nodeId})的{value}输入值非法!");
+					return false;
+				}
+			}
+			foreach (var child in nodeProto.children)
+			{
+				if (!CheckNodeInput(child))
+				{
+					return false;
+				}
+			}
+			return true;
+		}
+ 
+        public void SaveAll()
+        {
+            if (!CheckHasTreeDesc())
+            {
+                return;
+            }
+            if (!CheckSatisfyInput())
+            {
+                return;
+            }
+            SavePrefabTree();
+            Log.Info("保存成功!");
+            BehaviorTreeTipsHelper.ShowMessage("保存成功!");
+        }
+        private void SavePrefabTree()
+        {
+            ResetTreeId();
+           
+            BehaviorTreeConfig config = BehaviorTreeDataToConfig(CurTree);
+            RenameTree(config);
+            GameObject.DestroyImmediate(config.gameObject);
+        }
+        public void ResetTreeId()
+		{
+            AutoID = NodeIdStartIndex;
+            CurTree.Root.ResetId();
+        }
+        public void TransformTree(GameObject go)
+        {
+ 
+        }
+ 
+		public void RemoveUnusedArgs(NodeProto nodeProto)
+		{
+			ClientNodeTypeProto proto = ExportNodeTypeConfig.GetNodeTypeProtoFromDll(nodeProto.name);
+			List<string> unUsedList = new List<string>();
+			foreach (var item in nodeProto.args_dict)
+			{
+				if (!proto.new_args_desc.Exists(a => (a.name == item.Key)))
+				{
+					unUsedList.Add(item.Key);
+				}
+			}
+			foreach (var item in unUsedList)
+			{
+				nodeProto.args_dict.Remove(item);
+			}
+			for (int i = 0; i < nodeProto.children.Count; i++)
+			{
+				RemoveUnusedArgs(nodeProto.children[i]);
+			}
+		}
+
+ 
+        private bool CheckHasTreeDesc()
+        {
+            if (string.IsNullOrEmpty(CurTree.Root.describe))
+            {
+                Log.Error("行为树描述不可以不填!!!!!!");
+                return false;
+            }
+            return true;
+        }
+ 
+        public void RenameTree(BehaviorTreeConfig config)
+        {
+            string newName = $"{config.RootNodeConfig.describe}";
+            if (!config.RootNodeConfig.describe.StartsWith("BT_"))
+            {
+                newName = $"BT_{config.RootNodeConfig.describe}";
+            }
+            config.gameObject.name = newName;
+            CurTreeGO =  PrefabUtility.ReplacePrefab(config.gameObject, CurTreeGO,ReplacePrefabOptions.ReplaceNameBased);
+            string prefabPath = AssetDatabase.GetAssetPath(CurTreeGO);
+            string result = AssetDatabase.RenameAsset(prefabPath, newName);
+            if (result.Contains("Invalid file name"))
+            {
+                Log.Error(result);
+            }
+            EditorUtility.SetDirty(config.gameObject);
+        }
+        public BehaviorTreeConfig BehaviorTreeDataToConfig(BehaviorTreeData tree)
+        {
+           GameObject curTreeGo = GameObject.Instantiate(CurTreeGO);
+           BehaviorTreeConfig config = curTreeGo.GetComponent<BehaviorTreeConfig>();
+            if (config == null)
+            {
+                config = curTreeGo.AddComponent<BehaviorTreeConfig>();
+            }
+           foreach (Transform child in config.gameObject.transform)
+           {
+                GameObject.DestroyImmediate(child.gameObject);
+           }
+           try
+           {
+                config.RootNodeConfig = NodeDataToNodeConfig(tree.Root);
+            }
+           catch
+           {
+                Debug.LogError($"tree name : {tree.BehaviorNodeData.name}");
+           }
+            
+            config.RootNodeConfig.gameObject.transform.parent = config.gameObject.transform;
+            return config;
+        }
+
+        public BehaviorNodeData NodeConfigToNodeData(BehaviorNodeConfig nodeProto)
+        {
+            BehaviorNodeData nodeData = new BehaviorNodeData();
+            nodeData.nodeId = nodeProto.id;
+            nodeData.name = ((Object) nodeProto).name;
+            nodeData.describe = nodeProto.describe;
+            nodeData.args_dict = nodeProto.GetArgsDict();
+            nodeData.children = new List<BehaviorNodeData>();
+//             foreach (var item in nodeData.args_dict)
+//             {
+//                 Log.Info($"key :{item.Key} value :{item.Value}");
+//             }
+            foreach (Transform child in nodeProto.gameObject.transform)
+            {
+                BehaviorNodeConfig nodeConfig = child.gameObject.GetComponent<BehaviorNodeConfig>();
+                BehaviorNodeData childData = NodeConfigToNodeData(nodeConfig);
+                nodeData.children.Add(childData);
+            }
+            return nodeData;
+        }
+        public BehaviorNodeConfig NodeDataToNodeConfig(BehaviorNodeData nodeData)
+        {
+            GameObject go = new GameObject();
+            BehaviorNodeConfig nodeConfig = go.AddComponent<BehaviorNodeConfig>();
+            nodeConfig.id = nodeData.nodeId;
+            ((Object) nodeConfig).name = nodeData.name;
+            go.name = nodeData.name;
+            nodeConfig.describe = nodeData.describe;
+            List<string> unUseList = new List<string>();
+            foreach (var args in nodeData.args_dict)
+            {
+                if (!ExportNodeTypeConfig.NodeHasField(nodeData.name,args.Key))
+                {
+                    unUseList.Add(args.Key);
+                    continue;
+                }
+                Type originType = ExportNodeTypeConfig.GetFieldType(nodeData.name, args.Key);
+                try
+                {
+                    string fieldName = args.Key;
+                    object fieldValue = args.Value.GetValueByType(originType);
+                    Type type = BTTypeManager.GetBTType(originType);
+                    UnityEngine.Component comp = go.AddComponent(type);
+                    FieldInfo fieldNameInfo = type.GetField("fieldName");
+                    fieldNameInfo.SetValue(comp, fieldName);
+                    FieldInfo fieldValueinfo = type.GetField("fieldValue");
+                    if (BehaviorTreeArgsDict.IsEnumType(originType))
+                    {
+                        fieldValue = fieldValue.ToString();
+                    }
+                    fieldValueinfo.SetValue(comp, fieldValue);
+                }
+                catch (Exception e)
+                {
+                     throw new Exception($"transform failed,nodeName:{nodeData.name}  fieldName:{args.Key} fieldType:{originType}", e);
+                }
+            }
+            foreach (string key in unUseList)
+            {
+                nodeData.args_dict.Remove(key);
+            }
+            foreach (var child in nodeData.children)
+            {
+                BehaviorNodeConfig childConfig = NodeDataToNodeConfig(child);
+                childConfig.gameObject.transform.parent = nodeConfig.gameObject.transform;
+            }
+            return nodeConfig;
+        }
+        
+        public BehaviorNodeData NodeProtoToNodeData(NodeProto nodeProto)
+		{
+			BehaviorNodeData nodeData = new BehaviorNodeData();
+			nodeData.nodeId = nodeProto.nodeId;
+			nodeData.name = nodeProto.name;
+			nodeData.describe = nodeProto.describe;
+			nodeData.args_dict = nodeProto.args_dict;
+			nodeData.children = new List<BehaviorNodeData>();
+			foreach (var child in nodeProto.children)
+			{
+				nodeData.children.Add(this.NodeProtoToNodeData(child));
+			}
+			return nodeData;
+		}
+
+		public NodeProto NodeDataToNodeProto(BehaviorNodeData nodeData)
+		{
+			NodeProto nodeProto = new NodeProto();
+			nodeProto.nodeId = nodeData.nodeId;
+			nodeProto.name = nodeData.name;
+			nodeProto.describe = nodeData.describe;
+
+			nodeProto.nodeIdList = new List<int>();
+			nodeProto.args_dict = nodeData.args_dict;
+			nodeProto.children = new List<NodeProto>();
+			foreach (var child in nodeData.children)
+			{
+				nodeProto.children.Add(NodeDataToNodeProto(child));
+                nodeProto.nodeIdList.Add(child.nodeId);
+			}
+			return nodeProto;
+		}
+
+		private List<NodeFieldDesc> GetFieldDescList(NodeProto nodeProto, Type type)
+		{
+			List<NodeFieldDesc> list = ExportNodeTypeConfig.GetNodeFieldInOutPutDescList(nodeProto.name, type);
+			foreach (NodeProto childProto in nodeProto.children)
+			{
+				list.AddRange(GetFieldDescList(childProto, type));
+			}
+			return list;
+		}
+
+		public BehaviorNodeData CreateNode(int treeId, string nodeName)
+		{
+			if (!mName2NodeProtoDict.ContainsKey(nodeName))
+			{
+				Debug.LogError($"节点类型:{nodeName}不存在");
+				return null;
+			}
+			BehaviorNodeData node = new BehaviorNodeData(nodeName);
+			node.nodeId = AutoNodeId();
+			node.name = nodeName;
+			return node;
+		}
+
+		public BehaviorNodeData CopyNode(BehaviorNodeData node)
+		{
+			BehaviorNodeData copyNode = new BehaviorNodeData();
+			copyNode.name = node.name;
+			copyNode.describe = node.describe;
+			copyNode.Pos = node.Pos;
+			copyNode.args_dict = new BehaviorTreeArgsDict();
+			foreach (var item in node.args_dict)
+			{
+                ValueBase valueBase = ValueBase.Clone(item.Value);
+				copyNode.args_dict.Add(item.Key, valueBase);
+			}
+			List<BehaviorNodeData> list = new List<BehaviorNodeData>();
+			foreach (var item in node.children)
+			{
+				list.Add(item);
+			}
+			foreach (var child in list)
+			{
+			    copyNode.AddChild(CopyNode(child));
+			}
+            copyNode.ResetId();
+			return copyNode;
+		}
+ 
+        public void OpenBehaviorEditor(GameObject go)
+        {
+            if (go == null)
+            {
+                return;
+            }
+            selectNodeName = "";
+            ExportNodeTypeConfig.LoadAssembly();
+            CurTreeGO = go;
+            NewLoadData();
+            BehaviorDesignerWindow.ShowWindow();
+            Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeOpenEditor);
+        }
+        
+        public string[] GetCanInPutEnvKeyArray(BehaviorNodeData nodeData, NodeFieldDesc desc)
+		{
+			List<string> list1 = new List<string>();
+			list1.AddRange(GetInstance().GetNodeOutPutEnvKeyList(nodeData, desc));
+            list1.Add(BTEnvKey.None);
+            HashSet<string> hashSet = new HashSet<string>();
+			foreach (var item in list1)
+			{
+				hashSet.Add(item);
+			}
+
+			string[] strArr = new string[hashSet.Count];
+			int i = 0;
+			foreach (string str in hashSet)
+			{
+				strArr[i++] = str;
+			}
+			return strArr;
+		}
+
+		public List<string> GetCanInPutEnvKeyList(BehaviorNodeData nodeData, NodeFieldDesc desc)
+		{
+			List<string> list1 = GetInstance().GetNodeOutPutEnvKeyList(nodeData, desc);
+			HashSet<string> hashSet = new HashSet<string>();
+			foreach (var item in list1)
+			{
+				hashSet.Add(item);
+			}
+			List<string> resultList = new List<string>();
+			foreach (var item in hashSet)
+			{
+				resultList.Add(item);
+			}
+			return resultList;
+		}
+
+		public List<string> GetNodeOutPutEnvKeyList(BehaviorNodeData nodeData, NodeFieldDesc desc = null)
+		{
+            NodeProto rootNode = NodeDataToNodeProto(CurTree.Root);
+			NodeProto inputNode = NodeDataToNodeProto(nodeData);
+			List<NodeFieldDesc> descList = _GetNodeOutPutEnvKeyList(rootNode, inputNode, desc);
+			List<string> list = new List<string>();
+			foreach (var item in descList)
+			{
+                string str = item.value?.ToString() ?? "";
+				list.Add(str);
+			}
+			return list;
+		}
+
+		private List<NodeFieldDesc> _GetNodeOutPutEnvKeyList(NodeProto nodeProto, NodeProto inputNode, NodeFieldDesc desc = null)
+		{
+			if (nodeProto.nodeId >= inputNode.nodeId)
+			{
+				return new List<NodeFieldDesc>();
+			}
+			List<NodeFieldDesc> list = new List<NodeFieldDesc>();
+
+			if (desc == null)
+			{
+				list = ExportNodeTypeConfig.GetNodeFieldInOutPutDescList(nodeProto.name, typeof (NodeOutputAttribute));
+			}
+			else
+			{
+				list = ExportNodeTypeConfig.GetNodeFieldInOutPutFilterDescList(nodeProto.name, typeof (NodeOutputAttribute), desc.envKeyType);
+			}
+			for (int i = 0; i < list.Count; i++)
+			{
+				object value = nodeProto.args_dict.GetTreeDictValue(list[i].type, list[i].name);
+				list[i].value = value;
+			}
+
+			foreach (NodeProto childProto in nodeProto.children)
+			{
+				list.AddRange(_GetNodeOutPutEnvKeyList(childProto, inputNode, desc));
+			}
+			return list;
+		}
+
+		public List<string> GetSelectNodeInputValueList(NodeProto nodeProto)
+		{
+			List<string> resultList = new List<string>();
+			List<NodeFieldDesc> list = ExportNodeTypeConfig.GetNodeFieldInOutPutDescList(nodeProto.name, typeof (NodeInputAttribute));
+
+			foreach (var desc in list)
+			{
+				if (!nodeProto.args_dict.ContainsKey(desc.name))
+				{
+					ValueBase valueBase = new ValueBase();
+					nodeProto.args_dict.Add(desc.name, valueBase);
+				}
+				if (string.IsNullOrEmpty(nodeProto.args_dict[desc.name].enumValue))
+				{
+					nodeProto.args_dict[desc.name].enumValue = BTEnvKey.None.ToString();
+				}
+				string value = nodeProto.args_dict.GetTreeDictValue(desc.type, desc.name)?.ToString();
+				resultList.Add(value);
+			}
+			return resultList;
+		}
+
+		private BehaviorNodeData selectedNode;
+		private List<string> inputValueList;
+
+		public void SelectNode(BehaviorNodeData node)
+		{
+			selectedNode = node;
+			NodeProto nodeProto = NodeDataToNodeProto(node);
+			inputValueList = GetSelectNodeInputValueList(nodeProto);
+		}
+
+		public bool IsHighLight(BehaviorNodeData node)
+		{
+			NodeProto nodeProto = NodeDataToNodeProto(node);
+			List<NodeFieldDesc> list = ExportNodeTypeConfig.GetNodeFieldInOutPutDescList(nodeProto.name, typeof (NodeOutputAttribute));
+			foreach (var desc in list)
+			{
+                if (!nodeProto.args_dict.ContainsKey(desc.name))
+                {
+                    continue;
+                }
+				string value = nodeProto.args_dict.GetTreeDictValue(desc.type, desc.name)?.ToString();
+				List<string> resultList = inputValueList.FindAll(str => { return str == value; });
+				if (resultList.Count > 0)
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+
+		public void SetDebugState(BehaviorTree tree, List<long> pathList)
+		{
+			CurBehaviorTree = tree;
+			foreach (var nodeId in pathList)
+			{
+				GetInstance().SetDebugState(tree, (int) nodeId);
+			}
+		}
+
+		private void SetDebugState(BehaviorTree tree, int nodeId)
+		{
+			if (this.BehaviorTreeConfig != null && tree.behaviorTreeConfig.gameObject.name == this.BehaviorTreeConfig.gameObject.name)
+			{
+				BehaviorNodeData nodeData = GetNodeData(CurTree.Root, nodeId);
+				if (nodeData != null)
+				{
+					nodeData.NodeDeubgState = DebugState.True;
+				}
+			}
+		}
+
+		public void ClearDebugState()
+		{
+			_ClearDebugState(CurTree.Root);
+		}
+
+		private void _ClearDebugState(BehaviorNodeData nodeData)
+		{
+			nodeData.NodeDeubgState = DebugState.Normal;
+			foreach (var child in nodeData.children)
+			{
+				_ClearDebugState(child);
+			}
+		}
+
+		public BehaviorNodeData GetNodeData(BehaviorNodeData nodeData, int nodeId)
+		{
+			BehaviorNodeData result = null;
+			if (nodeData.nodeId == nodeId)
+			{
+				return nodeData;
+			}
+			foreach (var child in nodeData.children)
+			{
+				result = GetNodeData(child, nodeId);
+				if (result != null)
+				{
+					break;
+				}
+			}
+			return result;
+		}
+
+		public BehaviorNodeData GetNode(BehaviorNodeData nodeData, int nodeId)
+		{
+			if (nodeData.nodeId == nodeId)
+			{
+				return nodeData;
+			}
+			foreach (var data in nodeData.children)
+			{
+				return GetNode(data, nodeId);
+			}
+			return null;
+		}
+
+		public void Clear()
+		{
+			treePathList.Clear();
+			CurBehaviorTree = null;
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorManager.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 51f78e8a455fac3408d55a96863e7037
+timeCreated: 1445240657
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 69 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeConfigExtension.cs

@@ -0,0 +1,69 @@
+using MyEditor;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+namespace Model
+{
+    public static class BehaviorNodeConfigExtension
+    {
+        public static BehaviorNodeConfig ProtoToConfig(NodeProto nodeData)
+        {
+            GameObject go = new GameObject();
+            BehaviorNodeConfig nodeConfig = go.AddComponent<BehaviorNodeConfig>();
+            nodeConfig.id = nodeData.nodeId;
+            ((UnityEngine.Object) nodeConfig).name = nodeData.name;
+            go.name = nodeData.name;
+            nodeConfig.describe = nodeData.describe;
+            foreach (var args in nodeData.args_dict)
+            {
+                Type originType = ExportNodeTypeConfig.GetFieldType(nodeData.name, args.Key);
+                try
+                {
+                    string fieldName = args.Key;
+                    object fieldValue = args.Value.GetValueByType(originType);
+                    Type type = BTTypeManager.GetBTType(originType);
+					UnityEngine.Component comp = go.AddComponent(type);
+                    FieldInfo fieldNameInfo = type.GetField("fieldName");
+                    fieldNameInfo.SetValue(comp, fieldName);
+                    FieldInfo fieldValueinfo = type.GetField("fieldValue");
+                    if (BehaviorTreeArgsDict.IsEnumType(originType))
+                    {
+                        fieldValue = fieldValue.ToString();
+                    }
+                    fieldValueinfo.SetValue(comp, fieldValue);
+                }
+                catch (Exception ex)
+                {
+                    throw new GameException($"transform failed,nodeName:{nodeData.name}  fieldName:{args.Key} fieldType:{originType}");
+                }
+
+            }
+            foreach (var child in nodeData.children)
+            {
+                BehaviorNodeConfig childConfig = ProtoToConfig(child);
+                childConfig.gameObject.transform.parent = nodeConfig.gameObject.transform;
+            }
+            return nodeConfig;
+        }
+
+        public static NodeProto ConfigToNode(BehaviorNodeConfig nodeProto)
+        {
+            NodeProto nodeData = new NodeProto();
+            nodeData.nodeId = nodeProto.id;
+            nodeData.name = ((UnityEngine.Object) nodeProto).name;
+            nodeData.describe = nodeProto.describe;
+            nodeData.args_dict = nodeProto.GetArgsDict();
+            nodeData.children = new List<NodeProto>();
+            foreach (Transform child in nodeProto.gameObject.transform)
+            {
+                BehaviorNodeConfig nodeConfig = child.gameObject.GetComponent<BehaviorNodeConfig>();
+                NodeProto childData = ConfigToNode(nodeConfig);
+                nodeData.children.Add(childData);
+            }
+            return nodeData;
+        }
+
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeConfigExtension.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 49cadc7f01272b6478e89ac498c2f973
+timeCreated: 1478145751
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 154 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeData.cs

@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using Model;
+using UnityEngine;
+
+namespace MyEditor
+{
+	public enum DebugState
+	{
+		Disable,
+		True,
+		False,
+		Error,
+		Normal
+	}
+ 
+	public class BehaviorNodeData
+	{
+		public int nodeId;
+
+		public string name;
+
+		public string describe = "";
+  
+		public List<BehaviorNodeData> children = new List<BehaviorNodeData>();
+
+		public BehaviorTreeArgsDict args_dict = new BehaviorTreeArgsDict();
+        /// <summary>
+        ///  
+        /// </summary>
+		public string error = "";
+
+		private ClientNodeTypeProto mProto;
+
+		private BehaviorNodeData mParent;
+
+		private string mClassify = "";
+
+		public NodeDesigner NodeDesigner { get; set; }
+		
+		public Vector2 Pos;
+		public DebugState NodeDeubgState { get; set; }
+		public string time;
+
+		public ClientNodeTypeProto Proto
+		{
+			get
+			{
+				return mProto;
+			}
+			set
+			{
+				mProto = value;
+			}
+		}
+
+		public List<BehaviorNodeData> Children
+		{
+			get
+			{
+				return children;
+			}
+		}
+
+		public BehaviorNodeData Parent
+		{
+			get
+			{
+				return mParent;
+			}
+			set
+			{
+				mParent = value;
+			}
+		}
+
+		public string Classify
+		{
+			get
+			{
+				return mClassify;
+			}
+			set
+			{
+				mClassify = value;
+			}
+		}
+
+		public BehaviorNodeData(string proto_name)
+		{
+			name = proto_name;
+			mProto = BehaviorManager.GetInstance().GetNodeTypeProto(proto_name);
+			if (mProto == null)
+			{
+				mProto = BehaviorManager.GetInstance().GetNodeTypeProto("Unknow");
+				return;
+			}
+			mClassify = mProto.classify;
+
+			foreach (var args_desc in mProto.new_args_desc)
+			{
+				args_dict.SetKeyValueComp(args_desc.type, args_desc.name, args_desc.value);
+			}
+
+			foreach (BehaviorNodeData child in children)
+			{
+				AddChild(child);
+			}
+		}
+
+		public BehaviorNodeData()
+		{
+		}
+
+		//默认添加到末尾
+		public void AddChild(BehaviorNodeData node, int index = -1)
+		{
+			index = index == -1? this.Children.Count : index;
+			children.Insert(index, node);
+			node.mParent = this;
+		}
+
+		public BehaviorNodeData RemoveChild(BehaviorNodeData node)
+		{
+			node.Parent = null;
+			children.Remove(node);
+			return node;
+		}
+
+		public bool IsLeaf()
+		{
+			return children.Count == 0;
+		}
+
+		public bool IsRoot()
+		{
+			return Parent == null;
+		}
+ 
+		public bool CanAddChild()
+		{
+			return children.Count < Proto.child_limit;
+		}
+         
+		public void ResetId()
+		{
+			this.nodeId = BehaviorManager.GetInstance().AutoNodeId();
+			foreach (var child in children)
+			{
+				child.ResetId();
+			}
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorNodeData.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c08bbb6fa338299459fb5f68293508e6
+timeCreated: 1445412259
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 23 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigEditor.cs

@@ -0,0 +1,23 @@
+using System;
+using Model;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+    [CustomEditor(typeof(BehaviorTreeConfig))]
+    public class BehaviorTreeConfigEditor : Editor
+    {
+        public override void OnInspectorGUI()
+        {
+            base.OnInspectorGUI();
+            BehaviorTreeConfig config = target as BehaviorTreeConfig;
+
+			if (GUILayout.Button("打开行为树"))
+            {
+                BehaviorManager.GetInstance().OpenBehaviorEditor(config.gameObject);
+            }
+            EditorUtility.SetDirty(config);
+        }
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigEditor.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8da8c0787633f634f8bfe3d81cba5a86
+timeCreated: 1486456203
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 59 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigExtension.cs

@@ -0,0 +1,59 @@
+using MyEditor;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEngine;
+
+namespace Model
+{
+    public static class  BehaviorTreeConfigExtension
+    {
+       
+        public static BehaviorNodeConfig AddRootNode(this BehaviorTreeConfig treeConfig, string rootName)
+        {
+            BehaviorNodeConfig go = treeConfig.CreateNodeConfig(rootName);
+            treeConfig.RootNodeConfig = go.GetComponent<BehaviorNodeConfig>();
+            treeConfig.RootNodeConfig.id = BehaviorManager.NodeIdStartIndex;
+            go.gameObject.name = rootName;
+            return go;
+        }
+ 
+        public static BehaviorNodeConfig AddChild(this BehaviorTreeConfig treeConfig, BehaviorNodeConfig parent, string name)
+        {
+            BehaviorNodeConfig child = treeConfig.CreateNodeConfig(name);
+            AddChild(treeConfig, parent, child);
+            return child;
+        }
+ 
+        public static BehaviorNodeConfig AddChild(this BehaviorTreeConfig treeConfig, BehaviorNodeConfig parent, BehaviorNodeConfig child)
+        {
+            child.transform.parent = parent.transform;
+            child.transform.SetAsLastSibling();
+            child.GetComponent<BehaviorNodeConfig>().id = treeConfig.RootNodeId + treeConfig.AutoId;
+            return child.GetComponent<BehaviorNodeConfig>();
+        }
+        private static BehaviorNodeConfig CreateNodeConfig(this BehaviorTreeConfig treeConfig, string name)
+        {
+            ExportNodeTypeConfig.LoadAssembly();
+            ClientNodeTypeProto proto = ExportNodeTypeConfig.GetNodeTypeProtoFromDll(name);
+            GameObject go = new GameObject();
+            go.name = name;
+            go.transform.parent = treeConfig.gameObject.transform;
+            BehaviorNodeConfig node = go.AddComponent<BehaviorNodeConfig>();
+            ((UnityEngine.Object) node).name = name;
+            //node.describe = proto.describe;
+
+            foreach (var args in proto.new_args_desc)
+            {
+                Type type = BTTypeManager.GetBTType(args.type);
+				UnityEngine.Component comp = go.AddComponent(type);
+                FieldInfo info = type.GetField("fieldName");
+                info.SetValue(comp, args.name);
+                FieldInfo info1 = type.GetField("fieldValue");
+                info1.SetValue(comp, args.value);
+            }
+            return node;
+        }
+  
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeConfigExtension.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6fdeb0fb0ced28142bb395d960a007ac
+timeCreated: 1478156746
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 38 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeData.cs

@@ -0,0 +1,38 @@
+using System;
+using Model;
+using MongoDB.Bson.Serialization.Attributes;
+
+namespace MyEditor
+{
+	[BsonIgnoreExtraElements]
+	[Serializable]
+	public class BehaviorTreeData: AConfig
+	{
+		[BsonElement, BsonIgnoreIfNull]
+		public BehaviorNodeData BehaviorNodeData;
+
+		[BsonElement]
+		public string classify = "";
+
+		public BehaviorTreeData(): base(EntityType.Config)
+		{
+		}
+
+		public BehaviorTreeData(long id) : base(id, EntityType.Config)
+		{
+		}
+
+		[BsonIgnore]
+		public BehaviorNodeData Root
+		{
+			get
+			{
+				return this.BehaviorNodeData;
+			}
+			set
+			{
+				this.BehaviorNodeData = value;
+			}
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeData.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: d54aa5d9bac653246af829f4907826cf
+timeCreated: 1447145739
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 26 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeMenu.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+	public class AlterBundleNameWindow: EditorWindow
+	{
+		[MenuItem("Assets/Create/创建行为树")]
+		private static void CreateBehaviorTree()
+		{
+			var folderPath = AssetDatabase.GetAssetPath(Selection.activeObject);
+			if ((File.GetAttributes(folderPath) & FileAttributes.Directory) != FileAttributes.Directory)
+			{
+				GUILayout.Label("请选择一个文件夹");
+				return;
+			}
+
+			BehaviorTreeOperateUtility.CreateNewTree($"{folderPath}", "Root");
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeMenu.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 7ba79f825cb73b744901c844579efd3e
+timeCreated: 1486455928
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 160 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeNodeClassPopup.cs

@@ -0,0 +1,160 @@
+using Model;
+using System;
+using System.Collections.Generic;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+    public class BehaviorTreeNodeClassPopup
+    {
+        private string mSearchNode = "";
+        private Vector2 mTreeScrollPos = Vector2.zero;
+        private int mNodeCount;
+        private float mWidth = 400f;
+
+        public GraphDesigner GraphDesigner;
+        private SubWinType mSubWinType;
+        public Rect windowRect = new Rect();//子窗口的大小和位置
+        string[] mEnumNodeTypeArr;
+        Rect toolbarRect = new Rect(0f, 0f, 0, 0);
+        private int mEnumNodeTypeSelection;
+        public string DrawSearchList()
+        {
+            List<string> targetList = new List<string>();
+            if (mSubWinType == SubWinType.CreateNode)
+            {
+                targetList = GraphDesigner.GetCanCreateList();
+            }
+            else if (mSubWinType == SubWinType.ReplaceNode)
+            {
+                targetList = GraphDesigner.GetCanRepalceList();
+            }
+
+            List<string> nodeNameList = Filter(targetList, mSearchNode);
+
+            GUILayout.BeginHorizontal();
+            GUI.SetNextControlName("Search");
+            this.mSearchNode = GUILayout.TextField(this.mSearchNode, GUI.skin.FindStyle("ToolbarSeachTextField"));
+            GUI.FocusControl("Search");
+            GUILayout.EndHorizontal();
+            //
+            toolbarRect = new Rect(0f, 15f + 20, mWidth, 25f);
+            Rect boxRect = new Rect(0f, toolbarRect.height, this.mWidth, (Screen.height - toolbarRect.height) - 21f + 10);
+            GUILayout.BeginArea(toolbarRect, EditorStyles.toolbar);
+            GUILayout.BeginHorizontal();
+
+            GUILayout.Label("Filter");
+            Array strArr = Enum.GetValues(typeof(NodeClassifyType));
+            List<string> strList = new List<string>();
+            strList.Add("All");
+            foreach (var str in strArr)
+            {
+                strList.Add(str.ToString());
+            }
+            mEnumNodeTypeArr = strList.ToArray();
+            mEnumNodeTypeSelection = EditorGUILayout.Popup(mEnumNodeTypeSelection, mEnumNodeTypeArr);
+            if (GUILayout.Button("Clear"))
+            {
+                ClearNodes();
+            }
+            GUILayout.EndHorizontal();
+            GUILayout.EndArea();
+            //
+
+
+            GUILayout.BeginArea(new Rect(0, 0, windowRect.width, windowRect.height));
+            float topSpace = 60;
+            this.mTreeScrollPos = GUI.BeginScrollView(new Rect(0f, topSpace, windowRect.width, windowRect.height - topSpace), this.mTreeScrollPos,
+                    new Rect(0f, 0f, windowRect.width - 20f, nodeNameList.Count * 19), false, true);
+
+            foreach (var name in nodeNameList)
+            {
+                ClientNodeTypeProto proto = ExportNodeTypeConfig.GetNodeTypeProtoFromDll(name);
+                if (GUILayout.Button(name +$"({proto.describe})", GetButtonStyle()))
+                {
+                    if (SubWinType.CreateNode == mSubWinType)
+                    {
+                        GraphDesigner.onCreateNode(name, Vector2.zero);
+                    }
+                    else if (SubWinType.ReplaceNode == mSubWinType)
+                    {
+                        GraphDesigner.onChangeNodeType(name, Vector2.zero);
+                    }
+                    BehaviorDesignerWindow.Instance.CloseSubWin();
+                }
+            }
+
+            GUI.EndScrollView();
+            GUILayout.EndArea();
+
+            return "";
+        }
+        private void ClearNodes()
+        {
+            mEnumNodeTypeSelection = 0;
+            mSearchNode = "";
+        }
+        public List<string> Filter(List<string> list, string text)
+        {
+            List<string> result1 = new List<string>();
+            string selectType;
+            if (mEnumNodeTypeSelection == 0)
+            {
+                selectType = "All";
+                result1 = list;
+            }
+            else
+            {
+                selectType = Enum.GetName(typeof(NodeClassifyType), mEnumNodeTypeSelection - 1);
+                foreach (var name in list)
+                {
+                    ClientNodeTypeProto proto = ExportNodeTypeConfig.GetNodeTypeProtoFromDll(name);
+                    if (selectType == proto.classify)
+                    {
+                        result1.Add(name);
+                    }
+                }
+            }
+            
+            if (string.IsNullOrEmpty(text))
+            {
+                return result1;
+            }
+
+            List<string> result2 = new List<string>();
+            foreach (var name in result1)
+            {
+                ClientNodeTypeProto proto = ExportNodeTypeConfig.GetNodeTypeProtoFromDll(name);
+                if (name.ToUpper().Contains(text.ToUpper()) || proto.describe.ToUpper().Contains(text.ToUpper()))
+                {
+                    result2.Add(name);
+                }
+            }
+            return result2;
+        }
+        private Color textColor = new Color(200f / 255f, 200f / 255f, 200f / 255f);
+        private Color textHighLightColor = new Color(200f / 255f, 200f / 255f, 0);
+        public GUIStyle GetButtonStyle()
+        {
+            GUIStyle style = new GUIStyle();
+            style.fontSize = 15;
+            style.alignment = TextAnchor.MiddleLeft;
+            GUIStyleState onHoverStyleState = new GUIStyleState();
+            onHoverStyleState.textColor = textHighLightColor;
+            onHoverStyleState.background = BehaviorDesignerUtility.GetTexture("blue");
+            style.hover = onHoverStyleState;
+
+            GUIStyleState onNormalStyleState = new GUIStyleState();
+            onNormalStyleState.textColor = textColor;
+            style.normal = onNormalStyleState;
+            return style;
+        }
+
+        public void Show(Rect rect, SubWinType subWinType)
+        {
+            windowRect = rect;
+            mSubWinType = subWinType;
+        }
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeNodeClassPopup.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6a1eb8d5c2d0bee48a4c3d8b7c26ae4e
+timeCreated: 1473220994
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 171 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeOperateUtility.cs

@@ -0,0 +1,171 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Base;
+using Model;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+    public class BehaviourTreeNodeProxy<T> where T : Node
+    {
+        public T Node;
+        public NodeProto Proto;
+
+        public BehaviourTreeNodeProxy(NodeProto p)
+        {
+            Node = (T)Activator.CreateInstance(typeof(T), p);
+            Proto = p;
+            UpdateData();
+        }
+
+        public void SetDescribe(string desc)
+        {
+            Proto.describe = desc;
+        }
+
+        public void Apply()
+        {
+            FieldInfo[] mems = Node.GetType().GetFields();
+            foreach (FieldInfo mem in mems)
+            {
+                Proto.args_dict.SetKeyValueComp(mem.FieldType, mem.Name, mem.GetValue(Node));
+            }
+        }
+
+        public NodeProto GetNodeProtoCopy()
+        {
+            return BehaviorTreeOperateUtility.NodeProtoParamClone(Proto);
+        }
+
+        public void UpdateData()
+        {
+            foreach (var argsItem in Proto.args_dict)
+            {
+                FieldInfo fieldInfo = typeof(T).GetField(argsItem.Key, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+                fieldInfo.SetValue(Node, argsItem.Value.GetValueByType(fieldInfo.FieldType));
+            }
+        }
+    }
+
+    public static class BehaviorTreeOperateUtility
+    {
+
+        /// <summary>
+        /// 克隆Node Proto的参数队列
+        /// </summary>
+        /// <param name="p"></param>
+        /// <returns></returns>
+        public static NodeProto NodeProtoParamClone(NodeProto p)
+        {
+            NodeProto newP = new NodeProto();
+            foreach (var dict in p.args_dict)
+            {
+                string key = dict.Key;
+                ValueBase value = ValueBase.Clone(dict.Value);
+                newP.args_dict.Add(key, value);
+            }
+            return newP;
+        }
+
+        public static GameObject CreateTreeWithType<T>(string path, string desc = "默认行为树")
+        {
+            desc = desc.Replace("BT_", "");
+            return CreateTree(path, typeof(T).Name, desc);
+        }
+
+        public static GameObject CreateTree(string path,string rootNodeName, string desc = "默认行为树")
+        {
+            GameObject prefab = null;
+            try
+            {
+
+                GameObject go = new GameObject();
+                go.name = desc;
+                prefab = PrefabUtility.CreatePrefab($"{path}/BT_{desc}.prefab", go, ReplacePrefabOptions.ReplaceNameBased);
+                BehaviorTreeConfig config = prefab.AddComponent<BehaviorTreeConfig>();
+                config.AddRootNode(rootNodeName);
+                EditorUtility.SetDirty(config);
+                EditorUtility.SetDirty(prefab);
+                UnityEngine.Object.DestroyImmediate(go);
+               
+            }
+            catch (Exception ex)
+            {
+                Log.Error($"创建行为树失败|{ex}");
+            }
+            return prefab;
+        }
+
+        public static GameObject CreateNewTree(string path, string rootNodeName, string desc = "默认行为树")
+        {
+            GameObject prefab = null;
+            try
+            {
+                GameObject go = new GameObject();
+                BehaviorTreeConfig newConfig = go.AddComponent<BehaviorTreeConfig>();
+                BehaviorNodeConfig root = newConfig.AddRootNode(rootNodeName);
+
+                prefab = PrefabUtility.CreatePrefab($"{path}/BT_{desc}.prefab", go, ReplacePrefabOptions.ReplaceNameBased);
+                EditorUtility.SetDirty(newConfig);
+                EditorUtility.SetDirty(prefab);
+                UnityEngine.Object.DestroyImmediate(go);
+
+            }
+            catch (Exception ex)
+            {
+                Log.Error($"创建行为树失败|{ex}");
+            }
+            return prefab;
+        }
+        private static void SortBehaviorTree(BehaviorNodeConfig nodeConfig)
+        {
+
+        }
+
+        public static BehaviourTreeNodeProxy<T> AddNodeToLast<T>(BehaviorTreeConfig tree) where T : Node
+        {
+            BehaviorNodeConfig parent = tree.RootNodeConfig;
+            string name = typeof(T).Name;
+            BehaviorNodeConfig p = tree.AddChild(parent, name);
+            BehaviourTreeNodeProxy<T> proxy = new BehaviourTreeNodeProxy<T>(p.ToNodeProto());
+            return proxy;
+        }
+
+        public static BehaviourTreeNodeProxy<T> CreateNode<T>() where T : Node
+        {
+            NodeProto p = new NodeProto();
+            p.name = typeof(T).Name;
+            BehaviourTreeNodeProxy<T> proxy = new BehaviourTreeNodeProxy<T>(p);
+            return proxy;
+        }
+
+        /// <summary>
+        /// 从父节点获取某个指定名字的子节点
+        /// </summary>
+        /// <param name="list"></param>
+        /// <param name="name"></param>
+        /// <param name="p"></param>
+        /// <returns></returns>
+        public static bool TryGetActionChild(List<NodeProto> list, string name, out NodeProto p)
+        {
+            foreach (NodeProto proto in list)
+            {
+                if (proto.describe == name)
+                {
+                    p = proto;
+                    return true;
+                }
+            }
+            p = null;
+            return false;
+        }
+
+        public static BTEditorTree Open(GameObject go)
+        {
+            BehaviorTreeConfig config = go.GetComponent<BehaviorTreeConfig>();
+            return new BTEditorTree(config);
+        }
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeOperateUtility.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ad28444131f02094f88419500ac48038
+timeCreated: 1486455928
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeTipsHelper.cs

@@ -0,0 +1,13 @@
+using UnityEngine;
+
+namespace MyEditor
+{
+	public static class BehaviorTreeTipsHelper
+	{
+		public static void ShowMessage(params object[] list)
+		{
+			string msg = list[0].ToString();
+			BehaviorDesignerWindow.Instance.ShowNotification(new GUIContent(msg));
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeTipsHelper.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 2860b7daa4ea5aa4196cbbe2d9e7a85c
+timeCreated: 1471836065
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 36 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeToolWindow.cs

@@ -0,0 +1,36 @@
+using System;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+    public class BehaviorTreeToolWindow : EditorWindow
+    {
+        
+        public static BehaviorTreeToolWindow Instance
+        {
+            get
+            {
+                return GetWindow<BehaviorTreeToolWindow>(false, "工具箱");
+            }
+        }
+
+        public static void ShowWindow()
+        {
+            Type[] a = new Type[1];
+            a[0] = typeof(BehaviorDesignerWindow);
+            //BehaviorDesignerWindow target = GetWindow<BehaviorDesignerWindow>(false, "行为树编辑器",a);
+            BehaviorTreeToolWindow target = GetWindow<BehaviorTreeToolWindow>("工具箱", true, a);
+            target.ShowTab();
+            //target.maximized = false;
+            // target.Show();
+            Rect rect = BehaviorDesignerWindow.Instance.position;
+            rect.width = 200;
+            target.minSize = rect.size;
+          //  target.position = rect;
+            //target.minSize = new Vector2(600f, 500f);
+             
+
+        }
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/BehaviorTreeToolWindow.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: a1f1c1de7eedbb44494835f8d0863170
+timeCreated: 1473066441
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 242 - 0
Unity/Assets/Editor/BehaviorTreeEditor/CustomArrayField.cs

@@ -0,0 +1,242 @@
+using Model;
+using UnityEditor;
+using UnityEngine;
+using Object = UnityEngine.Object;
+
+namespace MyEditor
+{
+	public static class CustomArrayField
+	{
+		public static int[] IntArrFieldValue(ref bool foldIntArr, string fieldDesc, int[] oldValue)
+		{
+			if (oldValue == null)
+			{
+				oldValue = new int[0];
+			}
+			int[] newValue = oldValue;
+
+			foldIntArr = EditorGUILayout.Foldout(foldIntArr, fieldDesc);
+			if (foldIntArr)
+			{
+				int size = EditorGUILayout.IntField("Size", oldValue.Length);
+
+				newValue = new int[size];
+				if (size >= oldValue.Length)
+				{
+					for (int i = 0; i < oldValue.Length; i++)
+					{
+						newValue[i] = EditorGUILayout.IntField(i.ToString(), oldValue[i]);
+					}
+					for (int i = oldValue.Length; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.IntField(i.ToString(), newValue[i]);
+					}
+				}
+				else if (size < oldValue.Length)
+				{
+					for (int i = 0; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.IntField(i.ToString(), oldValue[i]);
+					}
+				}
+			}
+			return newValue;
+		}
+
+		public static long[] LongArrFieldValue(ref bool foldIntArr, string fieldDesc, long[] oldValue)
+		{
+			if (oldValue == null)
+			{
+				oldValue = new long[0];
+			}
+			long[] newValue = oldValue;
+
+			foldIntArr = EditorGUILayout.Foldout(foldIntArr, fieldDesc);
+			if (foldIntArr)
+			{
+				int size = EditorGUILayout.IntField("Size", oldValue.Length);
+
+				newValue = new long[size];
+				if (size >= oldValue.Length)
+				{
+					for (int i = 0; i < oldValue.Length; i++)
+					{
+						newValue[i] = EditorGUILayout.LongField(i.ToString(), oldValue[i]);
+					}
+					for (int i = oldValue.Length; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.LongField(i.ToString(), newValue[i]);
+					}
+				}
+				else if (size < oldValue.Length)
+				{
+					for (int i = 0; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.LongField(i.ToString(), oldValue[i]);
+					}
+				}
+			}
+			return newValue;
+		}
+
+		public static float[] FloatArrFieldValue(ref bool foldIntArr, string fieldDesc, float[] oldValue)
+		{
+			if (oldValue == null)
+			{
+				oldValue = new float[0];
+			}
+			float[] newValue = oldValue;
+
+			foldIntArr = EditorGUILayout.Foldout(foldIntArr, fieldDesc);
+			if (foldIntArr)
+			{
+				int size = EditorGUILayout.IntField("Size", oldValue.Length);
+
+				newValue = new float[size];
+				if (size >= oldValue.Length)
+				{
+					for (int i = 0; i < oldValue.Length; i++)
+					{
+						newValue[i] = EditorGUILayout.FloatField(i.ToString(), oldValue[i]);
+					}
+					for (int i = oldValue.Length; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.FloatField(i.ToString(), newValue[i]);
+					}
+				}
+				else if (size < oldValue.Length)
+				{
+					for (int i = 0; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.FloatField(i.ToString(), oldValue[i]);
+					}
+				}
+			}
+			return newValue;
+		}
+
+		public static double[] DoubleArrFieldValue(ref bool foldIntArr, string fieldDesc, double[] oldValue)
+		{
+			if (oldValue == null)
+			{
+				oldValue = new double[0];
+			}
+			double[] newValue = oldValue;
+
+			foldIntArr = EditorGUILayout.Foldout(foldIntArr, fieldDesc);
+			if (foldIntArr)
+			{
+				int size = EditorGUILayout.IntField("Size", oldValue.Length);
+
+				newValue = new double[size];
+				if (size >= oldValue.Length)
+				{
+					for (int i = 0; i < oldValue.Length; i++)
+					{
+						newValue[i] = EditorGUILayout.DoubleField(i.ToString(), oldValue[i]);
+					}
+					for (int i = oldValue.Length; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.DoubleField(i.ToString(), newValue[i]);
+					}
+				}
+				else if (size < oldValue.Length)
+				{
+					for (int i = 0; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.DoubleField(i.ToString(), oldValue[i]);
+					}
+				}
+			}
+			return newValue;
+		}
+
+		public static string[] StringArrFieldValue(ref bool foldIntArr, string fieldDesc, string[] oldValue)
+		{
+			if (oldValue == null)
+			{
+				oldValue = new string[0];
+			}
+			string[] newValue = oldValue;
+
+			foldIntArr = EditorGUILayout.Foldout(foldIntArr, fieldDesc);
+			if (foldIntArr)
+			{
+				int size = EditorGUILayout.IntField("Size", oldValue.Length);
+
+				newValue = new string[size];
+				if (size >= oldValue.Length)
+				{
+					for (int i = 0; i < oldValue.Length; i++)
+					{
+						newValue[i] = EditorGUILayout.TextField(i.ToString(), oldValue[i]);
+					}
+					for (int i = oldValue.Length; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.TextField(i.ToString(), newValue[i]);
+					}
+				}
+				else if (size < oldValue.Length)
+				{
+					for (int i = 0; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.TextField(i.ToString(), oldValue[i]);
+					}
+				}
+			}
+			return newValue;
+		}
+
+		public static Object[] ObjectArrFieldValue(ref bool fold, string fieldDesc, Object[] oldValue, NodeFieldDesc desc)
+		{
+			if (oldValue == null)
+			{
+				oldValue = new Object[0];
+			}
+			Object[] newValue = oldValue;
+
+			fold = EditorGUILayout.Foldout(fold, fieldDesc);
+			if (fold)
+			{
+				int size = EditorGUILayout.IntField("Size", oldValue.Length);
+
+				newValue = new Object[size];
+				if (size >= oldValue.Length)
+				{
+					for (int i = 0; i < oldValue.Length; i++)
+					{
+						newValue[i] = EditorGUILayout.ObjectField(i.ToString(), oldValue[i], desc.type.GetElementType(), false);
+						if (BehaviorTreeArgsDict.IsGameObjectArrayType(desc.type) &&
+						    !BehaviorTreeArgsDict.SatisfyCondition((GameObject) newValue[i], desc.constraintTypes))
+						{
+							newValue[i] = null;
+						}
+					}
+					for (int i = oldValue.Length; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.ObjectField(i.ToString(), newValue[i], desc.type.GetElementType(), false);
+						if (BehaviorTreeArgsDict.IsGameObjectArrayType(desc.type) &&
+						    !BehaviorTreeArgsDict.SatisfyCondition((GameObject) newValue[i], desc.constraintTypes))
+						{
+							newValue[i] = null;
+						}
+					}
+				}
+				else if (size < oldValue.Length)
+				{
+					for (int i = 0; i < size; i++)
+					{
+						newValue[i] = EditorGUILayout.ObjectField(i.ToString(), oldValue[i], desc.type.GetElementType(), false);
+						if (BehaviorTreeArgsDict.IsGameObjectArrayType(desc.type) &&
+						    !BehaviorTreeArgsDict.SatisfyCondition((GameObject) newValue[i], desc.constraintTypes))
+						{
+							newValue[i] = null;
+						}
+					}
+				}
+			}
+
+			return newValue;
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/CustomArrayField.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 5df2f5bafc6b6ac4a9ea1c1fb78fab83
+timeCreated: 1457606848
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 3a902cbd90500f548bc105b7137ec700
+folderAsset: yes
+timeCreated: 1471833564
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 14 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeAfterChangeNodeTypeEvent_SelectNode.cs

@@ -0,0 +1,14 @@
+using Model;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeAfterChangeNodeType)]
+	public class BehaviorTreeAfterChangeNodeTypeEvent_SelectNode: IEvent
+	{
+		public void Run()
+		{
+			NodeDesigner dstNode = BehaviorDesignerWindow.Instance.GraphDesigner.RootNode;
+			BehaviorDesignerWindow.Instance.OnSelectNode(dstNode.NodeData, dstNode);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeAfterChangeNodeTypeEvent_SelectNode.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4e86e5aa0b95e6a44ac642fdc8360fbb
+timeCreated: 1471924076
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeClickNodeEvent_SelectNode.cs

@@ -0,0 +1,13 @@
+using Model;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeClickNode)]
+	public class BehaviorTreeClickNodeEvent_SelectNode: IEvent<NodeDesigner>
+	{
+		public void Run(NodeDesigner dstNode)
+		{
+			BehaviorDesignerWindow.Instance.OnSelectNode(dstNode.NodeData, dstNode);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeClickNodeEvent_SelectNode.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: fa2ea9bc3d790404abce044731b65f71
+timeCreated: 1471855717
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeConnectStateEvent_HandleConnectLines.cs

@@ -0,0 +1,13 @@
+using Model;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeConnectState)]
+	public class BehaviorTreeConnectStateEvent_HandleConnectLines: IEvent<NodeDesigner, State>
+	{
+		public void Run(NodeDesigner nodeDesigner, State state)
+		{
+			BehaviorDesignerWindow.Instance.onStartConnect(nodeDesigner, state);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeConnectStateEvent_HandleConnectLines.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6460dd840fc43414082566badbe8e643
+timeCreated: 1471936138
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeCreateNodeEvent_SelectNode.cs

@@ -0,0 +1,13 @@
+using Model;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeCreateNode)]
+	public class BehaviorTreeCreateNodeEvent_SelectNode: IEvent<NodeDesigner>
+	{
+		public void Run(NodeDesigner dstNode)
+		{
+			BehaviorDesignerWindow.Instance.OnSelectNode(dstNode.NodeData, dstNode);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeCreateNodeEvent_SelectNode.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4fcb8d64039181d4f9b4757e526985c3
+timeCreated: 1471924076
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeMouseInNodeEvent_HandleOperate.cs

@@ -0,0 +1,13 @@
+using Model;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeMouseInNode)]
+	public class BehaviorTreeMouseInNodeEvent_HandleOperate: IEvent<BehaviorNodeData, NodeDesigner>
+	{
+		public void Run(BehaviorNodeData nodeData, NodeDesigner nodeDesigner)
+		{
+			BehaviorDesignerWindow.Instance.onMouseInNode(nodeData, nodeDesigner);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeMouseInNodeEvent_HandleOperate.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: b47f027d4544cfe4a90eee3dfbc43467
+timeCreated: 1471935347
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 14 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeNewCreateClickEvent_CreateNode.cs

@@ -0,0 +1,14 @@
+using Model;
+using UnityEngine;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreePropertyDesignerNewCreateClick)]
+	public class BehaviorTreeNewCreateClickEvent_CreateNode: IEvent<string, Vector2>
+	{
+		public void Run(string name, Vector2 pos)
+		{
+			BehaviorDesignerWindow.Instance.onCreateNode(name, pos);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeNewCreateClickEvent_CreateNode.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ed445ef8856006f4998ca80b4aac91ff
+timeCreated: 1471924726
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 20 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectNode.cs

@@ -0,0 +1,20 @@
+using Model;
+using UnityEngine;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeOpenEditor)]
+	public class BehaviorTreeOpenEditorEvent_SelectNode: IEvent
+	{
+		public void Run()
+		{
+            NodeDesigner dstNode = BehaviorDesignerWindow.Instance.onCreateTree();
+            if (dstNode == null)
+            {
+                Debug.LogError($"RootNode can not be null");
+                return;
+            }
+			BehaviorDesignerWindow.Instance.OnSelectNode(dstNode.NodeData, dstNode);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectNode.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 31b3074132b719a4398e25918a28d775
+timeCreated: 1471854631
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectTree.cs

@@ -0,0 +1,13 @@
+using Model;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeOpenEditor)]
+	public class BehaviorTreeOpenEditorEvent_SelectTree: IEvent
+	{
+		public void Run()
+		{
+			//BehaviorDesignerWindow.Instance.onSelectTree();
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_SelectTree.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 94b95889faab35842a12f6f1107ea71d
+timeCreated: 1471851414
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 13 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_UpdatePropList.cs

@@ -0,0 +1,13 @@
+using Model;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeOpenEditor)]
+	public class BehaviorTreeOpenEditorEvent_UpdatePropList: IEvent
+	{
+		public void Run()
+		{
+			BehaviorDesignerWindow.Instance.onUpdatePropList();
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeOpenEditorEvent_UpdatePropList.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 44203aa133917cd48a10fd9a1cef3e01
+timeCreated: 1471854631
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 14 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeReplaceClickEvent_ReplaceNode.cs

@@ -0,0 +1,14 @@
+using Model;
+using UnityEngine;
+
+namespace MyEditor
+{
+	[Event(EventIdType.BehaviorTreeReplaceClick)]
+	public class BehaviorTreeReplaceClickEvent_ReplaceNode: IEvent<string, Vector2>
+	{
+		public void Run(string name, Vector2 pos)
+		{
+			BehaviorDesignerWindow.Instance.onChangeNodeType(name, pos);
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeReplaceClickEvent_ReplaceNode.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 6833ca6aaa4da864eb2f86ecff2b80bf
+timeCreated: 1471937253
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 15 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRightDesignerDragEvent_ModifyRightBorder.cs

@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using Model;
+using MyEditor;
+
+namespace Controller
+{
+    [Event(EventIdType.BehaviorTreeRightDesignerDrag)]
+    public class BehaviorTreeRightDesignerDragEvent_ModifyRightBorder : IEvent<float>
+    {
+        public void Run(float deltaX)
+        {
+            BehaviorDesignerWindow.Instance.onDraggingRightDesigner(deltaX);
+        }
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRightDesignerDragEvent_ModifyRightBorder.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 993b72d69dfd5d74eb3e348bb13090f3
+timeCreated: 1473063257
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 21 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRunTreeEvent_ShowDebugInfo.cs

@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using Model;
+using MyEditor;
+
+namespace Controller
+{
+	[Event(EventIdType.BehaviorTreeRunTreeEvent)]
+	public class BehaviorTreeRunTreeEvent_ShowDebugInfo: IEvent<BehaviorTree, List<long>>
+	{
+		public void Run(BehaviorTree tree, List<long> pathList)
+		{
+			if (BehaviorManager.GetInstance().BehaviorTreeConfig != null &&
+			    tree.behaviorTreeConfig.name == BehaviorManager.GetInstance().BehaviorTreeConfig.name)
+			{
+				BehaviorManager.treePathList.Add(pathList);
+				BehaviorManager.GetInstance().ClearDebugState();
+				BehaviorManager.GetInstance().SetDebugState(tree, pathList);
+			}
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Event/BehaviorTreeRunTreeEvent_ShowDebugInfo.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: ddb7b97e3d06c2a478e896aed128905d
+timeCreated: 1471418167
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 290 - 0
Unity/Assets/Editor/BehaviorTreeEditor/ExportNodeTypeConfig.cs

@@ -0,0 +1,290 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Base;
+using Model;
+using UnityEditor;
+using UnityEngine;
+using Object = UnityEngine.Object;
+
+namespace MyEditor
+{
+	public enum NodeChildLimitType
+	{
+		WithChild,
+		WithoutChild,
+		All
+	}
+
+	public static class ExportNodeTypeConfig
+	{
+		public static Dictionary<NodeClassifyType, int> NodeTypeCountDict { get; } = new Dictionary<NodeClassifyType, int>
+		{
+			{ NodeClassifyType.Action, 0 },
+			{ NodeClassifyType.Composite, 999 },
+			{ NodeClassifyType.Condition, 0 },
+			{ NodeClassifyType.Decorator, 999 },
+			{ NodeClassifyType.Root, 999 },
+			{ NodeClassifyType.DataTransform, 0 }
+		};
+
+		public static Dictionary<string, ClientNodeTypeProto> ExportToDict()
+		{
+			Dictionary<string, ClientNodeTypeProto> name2NodeProtoDict = new Dictionary<string, ClientNodeTypeProto>();
+			Assembly assembly = GetControllerAssembly();
+			Type[] types = assembly.GetTypes();
+			foreach (Type type in types)
+			{
+				ClientNodeTypeProto proto = GetNodeTypeProtoFromType(type);
+				if (proto == null)
+				{
+					continue;
+				}
+				name2NodeProtoDict.Add(proto.name, proto);
+			}
+			return name2NodeProtoDict;
+		}
+		
+
+		public static Assembly GetControllerAssembly()
+		{
+			return Game.EntityEventManager.GetAssembly("Controller");
+		}
+
+
+		public static Assembly LoadAssembly()
+		{
+			AssetDatabase.Refresh();
+			Assembly assembly = DllHelper.GetController();
+			Game.EntityEventManager.Register("Controller", assembly);
+			return assembly;
+		}
+
+		public static ClientNodeTypeProto GetNodeTypeProtoFromDll(string name)
+		{
+			Type type = GetNodeType(name);
+			if (type == null)
+			{
+				Log.Error($"不存在类型type:{name}");
+			}
+			return GetNodeTypeProtoFromType(type);
+		}
+
+		public static ClientNodeTypeProto GetNodeTypeProtoFromType(Type type)
+		{
+			object[] nodeAttrs = type.GetCustomAttributes(typeof (NodeAttribute), false);
+			if (nodeAttrs.Length == 0)
+			{
+				return null;
+			}
+			object[] nodeDeprecatedAttrs = type.GetCustomAttributes(typeof (NodeDeprecatedAttribute), false);
+			NodeAttribute nodeAttribute = nodeAttrs[0] as NodeAttribute;
+			NodeDeprecatedAttribute nodeDeprecatedAttribute = null;
+			if (nodeDeprecatedAttrs.Length != 0)
+			{
+				nodeDeprecatedAttribute = nodeDeprecatedAttrs[0] as NodeDeprecatedAttribute;
+			}
+
+			ClientNodeTypeProto proto = new ClientNodeTypeProto();
+			proto.type = nodeAttribute.ClassifytType.ToString();
+			proto.name = type.Name;
+			proto.describe = nodeAttribute.Desc;
+			if (nodeDeprecatedAttribute != null)
+			{
+				proto.isDeprecated = true;
+				proto.deprecatedDesc = nodeDeprecatedAttribute.Desc;
+			}
+
+			proto.new_args_desc.AddRange(GetNodeFieldDesc(type, typeof (NodeInputAttribute)));
+			proto.new_args_desc.AddRange(GetNodeFieldDesc(type, typeof (NodeOutputAttribute)));
+			proto.new_args_desc.AddRange(GetNodeFieldDesc(type, typeof (NodeFieldAttribute)));
+
+			proto.child_limit = NodeTypeCountDict[nodeAttribute.ClassifytType];
+			proto.classify = nodeAttribute.ClassifytType.ToString();
+			return proto;
+		}
+
+		public static List<NodeFieldDesc> GetNodeFieldInOutPutDescList(string nodeName, Type fieldAttributeType)
+		{
+			Type nodeType = GetNodeType(nodeName);
+			if (nodeType == null)
+			{
+				Log.Error($"{nodeName}节点不存在!!!");
+				return null;
+			}
+			return GetNodeFieldDesc(nodeType, fieldAttributeType);
+		}
+
+		public static List<NodeFieldDesc> GetNodeFieldInOutPutFilterDescList(string nodeName, Type fieldAttributeType, Type paramType)
+		{
+			List<NodeFieldDesc> list = GetNodeFieldInOutPutDescList(nodeName, fieldAttributeType);
+			List<NodeFieldDesc> filterList = new List<NodeFieldDesc>();
+			foreach (var item in list)
+			{
+				if (item.envKeyType == paramType ||  item.envKeyType.IsSubclassOf(paramType) || paramType.IsAssignableFrom(item.envKeyType))
+				{
+					filterList.Add(item);
+				}
+			}
+			return filterList;
+		}
+
+		public static List<NodeFieldDesc> GetNodeFieldDesc(Type type, Type fieldAttributeType)
+		{
+			List<NodeFieldDesc> list = new List<NodeFieldDesc>();
+			BindingFlags flag = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
+			FieldInfo[] fields = type.GetFields(flag);
+			foreach (FieldInfo field in fields)
+			{
+				object[] field_attrs = field.GetCustomAttributes(fieldAttributeType, false);
+				if (field_attrs.Length > 0)
+				{
+					NodeFieldBaseAttribute attri = field_attrs[0] as NodeFieldBaseAttribute;
+					NodeFieldDesc desc = new NodeFieldDesc();
+					desc.name = field.Name;
+					desc.desc = attri.Desc;
+					desc.type = field.FieldType;
+					desc.value = GetDefaultValue(field.FieldType, attri);
+					desc.attributeType = fieldAttributeType;
+					desc.envKeyType = attri.envKeyType;
+					if ((typeof (NodeInputAttribute) == fieldAttributeType || typeof (NodeInputAttribute) == fieldAttributeType) && desc.envKeyType == null)
+					{
+						Log.Error($"Node:{type.Name} Field:{desc.name}  _envKeyType can not be null");
+						return null;
+					}
+					object[] constraints = field.GetCustomAttributes(typeof (NodeFieldConstraintAttribute), false);
+					if (constraints.Length > 0)
+					{
+						NodeFieldConstraintAttribute constraint = constraints[0] as NodeFieldConstraintAttribute;
+						desc.constraintTypes = constraint.Types;
+					}
+
+					list.Add(desc);
+				}
+			}
+			return list;
+		}
+
+		private static object GetDefaultValue(Type type, NodeFieldBaseAttribute att)
+		{
+			if (att.DefaultValue != null)
+			{
+				if ((BehaviorTreeArgsDict.IsEnumType(type) && BTEnvKey.None.ToString() != att.DefaultValue.ToString()) || !BehaviorTreeArgsDict.IsEnumType(type))
+				{
+					return att.DefaultValue;
+				}
+			}
+			object value = null;
+			if (BehaviorTreeArgsDict.IsDoubleType(type))
+			{
+				value = default(double);
+			}
+			else if (BehaviorTreeArgsDict.IsStringType(type))
+			{
+				value = default(string);
+			}
+			else if (BehaviorTreeArgsDict.IsFloatType(type))
+			{
+				value = default(float);
+			}
+			else if (BehaviorTreeArgsDict.IsBoolType(type))
+			{
+				value = default(bool);
+			}
+			else if (BehaviorTreeArgsDict.IsIntType(type))
+			{
+				value = default(int);
+			}
+			else if (BehaviorTreeArgsDict.IsLongType(type))
+			{
+				value = default(long);
+			}
+			else if (BehaviorTreeArgsDict.IsIntArrType(type))
+			{
+				value = default(int[]);
+			}
+			else if (BehaviorTreeArgsDict.IsLongArrType(type))
+			{
+				value = default(long[]);
+			}
+			else if (BehaviorTreeArgsDict.IsDoubleArrType(type))
+			{
+				value = default(double[]);
+			}
+			else if (BehaviorTreeArgsDict.IsFloatArrType(type))
+			{
+				value = default(float[]);
+			}
+			else if (BehaviorTreeArgsDict.IsStringArrType(type))
+			{
+				value = default(string[]);
+			}
+			else if (BehaviorTreeArgsDict.IsObjectType(type))
+			{
+				value = default(Object);
+			}
+			else if (BehaviorTreeArgsDict.IsEnumType(type))
+			{
+				Array array = Enum.GetValues(type);
+				value = array.GetValue(0).ToString();
+			}
+			else if (BehaviorTreeArgsDict.IsUnitConfigArrayType(type))
+			{
+			}
+			else if (BehaviorTreeArgsDict.IsSpriteArrayType(type))
+			{
+				value = default(Sprite[]);
+			}
+			else if (BehaviorTreeArgsDict.IsObjectArrayType(type))
+			{
+				value = default(Object[]);
+			}
+            else if (BehaviorTreeArgsDict.IsConvertble(type))
+            {
+                value = 1f;
+            }
+			else
+			{
+				Log.Error($"行为树节点暂时未支持此类型:{type}!");
+				return null;
+			}
+			return value;
+		}
+
+		public static Type GetFieldType(string nodeName, string fieldName)
+		{
+			Type nodeType = GetNodeType(nodeName);
+			FieldInfo fieldInfo = nodeType.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+			if (fieldInfo == null)
+			{
+				Log.Error(string.Format("{0}节点不存在此属性:{1}", nodeName, fieldName));
+			}
+			return fieldInfo.FieldType;
+		}
+        public static bool NodeHasField(string nodeName, string fieldName)
+        {
+            Type nodeType = GetNodeType(nodeName);
+            FieldInfo fieldInfo = nodeType.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+            return fieldInfo != null;
+        }
+
+		public static FieldInfo[] GetFieldInfos(string nodeName)
+		{
+			Type nodeType = GetNodeType(nodeName);
+			FieldInfo[] fieldInfos = nodeType.GetFields();
+			return fieldInfos;
+		}
+
+		public static Type GetNodeType(string nodeName)
+		{
+			Assembly assembly = GetControllerAssembly();
+			Type nodeType = assembly.GetType("Controller." + nodeName);
+			if (nodeType == null)
+			{
+				Log.Error(string.Format("不存在此节点:{0}", nodeName));
+				return null;
+			}
+			return nodeType;
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/ExportNodeTypeConfig.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 29b94d266875cf5408874b581cd9b12d
+timeCreated: 1448265008
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 172 - 0
Unity/Assets/Editor/BehaviorTreeEditor/FoldoutNode.cs

@@ -0,0 +1,172 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+namespace MyEditor
+{
+	public class FoldoutNode //折叠的节点
+	{
+		public string folderName { get; set; }
+
+		public delegate void DelegateMethod(FoldoutNode self);
+
+		private readonly DelegateMethod mCallback;
+
+		public string Text { get; } = "...";
+
+		public bool Hide { get; set; } = false;
+
+		public bool Select { get; set; } = false;
+
+		public int Depth { get; set; }
+
+		public FoldoutNode(string text, DelegateMethod callback = null)
+		{
+			this.Text = text;
+			mCallback = callback;
+		}
+
+		public void Draw()
+		{
+			if (!this.Hide)
+			{
+				GUILayout.BeginHorizontal();
+				GUILayout.Space(15 * this.Depth);
+
+				string str = "";
+				if (this.Select)
+				{
+					str = str + "[" + this.Text + "]";
+				}
+				else
+				{
+					str = str + this.Text;
+				}
+				if (GUILayout.Button(str, GUI.skin.GetStyle("Label")))
+				{
+					mCallback.Invoke(this);
+				}
+				GUILayout.EndHorizontal();
+			}
+		}
+	}
+
+	public class FoldoutFolder //折叠的目录
+	{
+		private bool mHide;
+
+		public delegate void DelegateMethod(FoldoutFolder self);
+
+		private readonly DelegateMethod mCallback;
+
+		public string Text { get; } = "...";
+
+		public bool Hide
+		{
+			get
+			{
+				return mHide;
+			}
+			set
+			{
+				mHide = value;
+			}
+		}
+
+		public bool Fold { get; set; }
+
+		public int Depth { get; set; }
+
+		public bool Select { get; set; } = false;
+
+		public List<FoldoutFolder> Folders { get; } = new List<FoldoutFolder>();
+
+		public List<FoldoutNode> Nodes { get; } = new List<FoldoutNode>();
+
+		public FoldoutFolder(string text, DelegateMethod callback = null)
+		{
+			this.Text = text;
+			mCallback = callback;
+		}
+
+		//添加折叠
+		public FoldoutFolder AddFolder(string text, DelegateMethod callback)
+		{
+			FoldoutFolder folder = new FoldoutFolder(text, callback);
+			this.Folders.Add(folder);
+			folder.Depth = this.Depth + 1;
+			return folder;
+		}
+
+		//添加叶子节点
+		public FoldoutNode AddNode(string folderName, string text, FoldoutNode.DelegateMethod callback)
+		{
+			FoldoutNode node = new FoldoutNode(text, callback);
+			node.folderName = folderName;
+			this.Nodes.Add(node);
+			node.Depth = this.Depth + 1;
+			return node;
+		}
+
+		public FoldoutNode FindNode(string text)
+		{
+			foreach (FoldoutNode node in this.Nodes)
+			{
+				if (node.Text == text)
+				{
+					return node;
+				}
+			}
+			return null;
+		}
+
+		public FoldoutFolder FindFolder(string text)
+		{
+			foreach (FoldoutFolder folder in this.Folders)
+			{
+				if (folder.Text == text)
+				{
+					return folder;
+				}
+			}
+			return null;
+		}
+
+		public void Draw()
+		{
+			GUILayout.BeginHorizontal();
+			GUILayout.Space(15 * this.Depth);
+
+			string str = "+";
+			if (this.Fold)
+			{
+				str = " -";
+			}
+			if (this.Select)
+			{
+				str = str + "[" + this.Text + "]";
+			}
+			else
+			{
+				str = str + this.Text;
+			}
+			if (GUILayout.Button(str, GUI.skin.GetStyle("Label")))
+			{
+				this.Fold = !this.Fold;
+				mCallback.Invoke(this);
+			}
+			GUILayout.EndHorizontal();
+
+			if (this.Fold)
+			{
+				foreach (FoldoutFolder folder in this.Folders)
+				{
+					folder.Draw();
+				}
+				foreach (FoldoutNode node in this.Nodes)
+				{
+					node.Draw();
+				}
+			}
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/FoldoutNode.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 364f87a660f33ef41aaa7d9c89905b08
+timeCreated: 1459149729
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 801 - 0
Unity/Assets/Editor/BehaviorTreeEditor/GraphDesigner.cs

@@ -0,0 +1,801 @@
+using System;
+using System.Collections.Generic;
+using Base;
+using Model;
+using UnityEditor;
+using UnityEngine;
+
+namespace MyEditor
+{
+	public enum State
+	{
+		Normal, //普通
+		Shift, //正在交换位置
+		Ctrl, //正在移动位置
+		Drag, //正在拖拽节点
+		ConnectLeft, //正在连线左
+		ConnectRight //正在连线右
+	}
+
+	public class GraphDesigner: Editor
+	{
+		public State mState = State.Normal;
+
+		/// 绘图相关
+		private Rect mBorderRect; //边框
+
+		private Rect mGraphRect = new Rect(0, 0, 2000, 2000); //绘图区域
+		private float mLeftWidth = 380f;
+         private float mRightWidth = 0;
+        private Vector2 mScrollPosition = Vector2.zero;
+
+		public void Draw(Rect windowRect)
+		{
+			mBorderRect = new Rect(mLeftWidth, 0, windowRect.width - mLeftWidth - 16 - mRightWidth, windowRect.height - 16);
+			mScrollPosition = GUI.BeginScrollView(new Rect(mBorderRect.x, mBorderRect.y, mBorderRect.width + 15f, mBorderRect.height + 15f), mScrollPosition,
+					mGraphRect, true, true);
+
+			DrawBackground();
+			DrawConnectingLine();
+			DrawNodes();
+
+			GUI.EndScrollView();
+
+			//更改鼠标光标
+			if (mDragingLeftBorder || mDragingRightBorder || mState == State.Drag)
+			{
+				Cursor.visible = false;
+				DrawMouseIcon("DragIcon");
+			}
+			else if (mState == State.Shift || mState == State.Ctrl)
+			{
+				Cursor.visible = false;
+				DrawMouseIcon("ShiftIcon");
+			}
+			else
+			{
+				Cursor.visible = true;
+			}
+
+			HandleEvents();
+			CalcGraphRect();
+		}
+        
+
+		public void DrawNodes()
+		{
+			RootNode?.Draw();
+			foreach (var node in mDetachedNodes)
+			{
+				node.Draw();
+			}
+		}
+
+		//正在连线
+		public void DrawConnectingLine()
+		{
+			if (mSelectedNode == null)
+			{
+				return;
+			}
+			var curPos = Event.current.mousePosition; //MousePosToGraphPos(Event.current.mousePosition);
+			if (mState == State.ConnectLeft)
+			{
+				BehaviorDesignerUtility.DrawConnection(mSelectedNode.LeftPos, curPos);
+			}
+			if (mState == State.ConnectRight)
+			{
+				BehaviorDesignerUtility.DrawConnection(mSelectedNode.RightPos, curPos);
+			}
+		}
+
+		private Vector2 mMousePos = Vector2.zero;
+		private Vector2 mSrcOffset = Vector2.zero;
+		private bool mLock = true;
+		private bool mDragingLeftBorder;
+        private bool mDragingRightBorder;
+
+        public void HandleEvents()
+		{
+			var e = Event.current;
+			switch (e.type)
+			{
+				case EventType.MouseDown:
+
+                   
+                    GUI.FocusControl("");
+					mMousePos = e.mousePosition;
+                    if (!BehaviorDesignerWindow.windowRect.Contains(mMousePos))
+                    {
+                        BehaviorDesignerWindow.Instance.CloseSubWin();
+                    }
+                    if (BehaviorDesignerWindow.windowRect.Contains(mMousePos) && BehaviorDesignerWindow.IsShowSubWin)
+                    {
+                        break;
+                    }
+                    //单击选中
+                    if (e.button == 0)
+					{
+						CheckMouseInNode();
+					}
+					//双击折叠
+					if (e.button == 0 && e.clickCount == 2 && mState != State.ConnectLeft && mState != State.ConnectRight)
+					{
+						mSelectedNode?.Fold();
+						CalcGraphRect();
+					}
+					//右键
+					if (e.button == 1)
+					{
+						//取消选中
+						mSelectedNode?.onSelect(false);
+						mSelectedNode = null;
+						//重新选中
+						CheckMouseInNode();
+						//右键菜单
+						PopMenu();
+					}
+					if (e.button == 0 && e.mousePosition.x < mLeftWidth + 30 && e.mousePosition.x > mLeftWidth)
+					{
+						mDragingLeftBorder = true;
+					}
+                    if (e.button == 0 && e.mousePosition.x < mLeftWidth + mBorderRect.width && e.mousePosition.x > mLeftWidth + mBorderRect.width - 30)
+                    {
+                        mDragingRightBorder = true;
+                    } 
+                    
+                    break;
+				case EventType.MouseUp:
+                    if (BehaviorDesignerWindow.windowRect.Contains(mMousePos) && BehaviorDesignerWindow.IsShowSubWin)
+                    {
+                        break;
+                    }
+                    if (e.button == 0 && e.shift)
+					{
+						mSelectedNode.Offset = mSrcOffset;
+						mSelectedNode.Parent.AutoSort();
+						CheckMouseInNode();
+					}
+					if (e.button == 0)
+					{
+						CheckMouseInNode();
+					}
+					mState = State.Normal;
+					mDragingLeftBorder = false;
+                    mDragingRightBorder = false;
+					break;
+				case EventType.MouseDrag:
+					//中键
+					if (e.button == 2 || (e.button == 0 && e.alt))
+					{
+						mScrollPosition.x -= e.delta.x;
+						mScrollPosition.y -= e.delta.y;
+						mState = State.Normal;
+						return;
+					}
+					if (e.button == 0 && e.shift)
+					{
+						if (mSelectedNode != null)
+						{
+							mSrcOffset = mSelectedNode.Offset;
+							mSelectedNode.onDrag(e.delta);
+							mState = State.Shift;
+						}
+
+						return;
+					}
+					if (e.button == 0 && e.control)
+					{
+						if (mSelectedNode != null)
+						{
+							mSrcOffset = mSelectedNode.Offset;
+							mSelectedNode.onDrag(e.delta);
+							mState = State.Ctrl;
+						}
+						return;
+					}
+					if (mDragingLeftBorder)
+					{
+						mLeftWidth += e.delta.x;
+						return;
+					}
+                    if (mDragingRightBorder)
+                    {
+                        mRightWidth -= e.delta.x;
+                        Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeRightDesignerDrag, e.delta.x);
+                        return;
+                    }
+
+                    //左键
+                    if (e.button == 0 && (e.control || !mLock))
+					{
+						if (mSelectedNode != null)
+						{
+							mSelectedNode.onDrag(e.delta);
+							mState = State.Drag;
+							DrawMouseIcon("DragIcon");
+						}
+					}
+					break;
+				case EventType.KeyUp:
+					//F1自动排序
+					if (e.keyCode == KeyCode.F1)
+					{
+						RootNode?.AutoSort();
+						RootNode.UpdateChildren();
+					}
+					if (e.keyCode == KeyCode.F2)
+					{
+						mLock = !mLock;
+						if (mLock)
+						{
+							BehaviorTreeTipsHelper.ShowMessage("节点位置已锁定");
+						}
+						else
+						{
+							BehaviorTreeTipsHelper.ShowMessage("节点位置已解锁");
+						}
+					}
+					if (e.keyCode == KeyCode.Delete)
+					{
+						RemoveNode();
+					}
+					break;
+				case EventType.MouseMove:
+					DrawMouseIcon("DragIcon2");
+					break;
+			}
+		}
+
+		public void DrawMouseIcon(string resName)
+		{
+			GUI.DrawTexture(new Rect(Event.current.mousePosition.x - 10, Event.current.mousePosition.y - 20, 17, 20),
+					BehaviorDesignerUtility.GetTexture(resName));
+		}
+
+		public void CheckMouseInNode()
+		{
+			var pos = MousePosToGraphPos(Event.current.mousePosition);
+			RootNode?.OnMousePos(pos);
+			for (int i = 0; i < mDetachedNodes.Count; i++)
+			{
+				var node = mDetachedNodes[i];
+				node.OnMousePos(pos);
+			}
+		}
+
+		public void CalcGraphRect()
+		{
+			if (RootNode == null)
+			{
+				mGraphRect.width = mBorderRect.width;
+				mGraphRect.height = mBorderRect.height;
+			}
+			else
+			{
+				mGraphRect = RootNode.Size;
+				mGraphRect.width += RootNode.Width * 4;
+				mGraphRect.height += RootNode.Height;
+				if (mGraphRect.width < mBorderRect.width)
+				{
+					mGraphRect.width = mBorderRect.width;
+				}
+				if (mGraphRect.height < mBorderRect.height)
+				{
+					mGraphRect.height = mBorderRect.height;
+				}
+
+				RootNode.Pos.x = RootNode.Width;
+				RootNode.Pos.y = RootNode.Size.height / 2 + RootNode.Height / 2;
+				RootNode.UpdateChildrenPos(RootNode.Offset);
+			}
+		}
+
+		public Vector2 MousePosToGraphPos(Vector2 mousePos)
+		{
+			Vector2 graphPos = new Vector2();
+			graphPos.x = mousePos.x + mScrollPosition.x - mLeftWidth;
+			graphPos.y = mousePos.y + mScrollPosition.y;
+			return graphPos;
+		}
+
+		public Vector2 CenterPosInBorder()
+		{
+			var pos = new Vector2();
+			pos.x = mScrollPosition.x + mBorderRect.width / 2;
+			pos.y = mScrollPosition.y + mBorderRect.height / 2;
+			return pos;
+		}
+
+		public void DrawBackground()
+		{
+			float width = 15f;
+			var bgTex = BehaviorDesignerUtility.GetTexture("Bg");
+			GUI.DrawTexture(new Rect(0, 0, mGraphRect.width, mGraphRect.height), bgTex);
+
+			var lineTex = BehaviorDesignerUtility.GetTexture("BgLine");
+			for (int i = 0; i < mGraphRect.width / width; i++)
+			{
+				GUI.DrawTexture(new Rect(width * i, 0, 1f, mGraphRect.height), lineTex);
+			}
+			for (int j = 0; j < mGraphRect.height / width; j++)
+			{
+				GUI.DrawTexture(new Rect(0, width * j, mGraphRect.width, 1f), lineTex);
+			}
+		}
+
+        public List<string>GetCanRepalceList()
+        {
+            List<string> result = new List<string>();
+            if (mSelectedNode != null)
+            {
+                if (mSelectedNode.NodeData.Proto.classify == NodeClassifyType.Root.ToString() || BehaviorManager.GetInstance().CurTree.Root.nodeId == mSelectedNode.NodeData.nodeId)
+                {
+                    List<ClientNodeTypeProto> list = BehaviorManager.GetInstance().Classify2NodeProtoList[NodeClassifyType.Root.ToString()];
+                    foreach (ClientNodeTypeProto nodeType in list)
+                    {
+                        result.Add(nodeType.name);
+                       // menu.AddItem(new GUIContent(string.Format("{0}/{1}", "替换为", nodeType.name)), false, new GenericMenu.MenuFunction2(this.ChangeNodeType), nodeType.name);
+                    }
+                }
+                else
+                {
+                   // NodeChildLimitType nodeChildLimitType = mSelectedNode.NodeData.IsLeaf() ? NodeChildLimitType.All : NodeChildLimitType.WithChild;
+                    List<ClientNodeTypeProto> canSubtituteList = BehaviorManager.GetInstance().AllNodeProtoList;
+                    canSubtituteList.Sort(CompareShowName);
+                    foreach (ClientNodeTypeProto nodeType in canSubtituteList)
+                    {
+                        if (nodeType.classify == NodeClassifyType.Root.ToString())
+                        {
+                            continue;
+                        }
+                        // menu.AddItem(new GUIContent(string.Format("{0}/{1}", "替换为", nodeType.name)), false, new GenericMenu.MenuFunction2(this.ChangeNodeType), nodeType.name);
+                        if (mSelectedNode.NodeData.Proto.child_limit <= nodeType.child_limit)
+                        {
+                            result.Add(nodeType.name);
+                        }
+                        
+                    }
+                }
+
+            }
+            return result;
+        }
+        public List<string> GetCanCreateList()
+        {
+            List<string> result = new List<string>();
+
+            foreach (KeyValuePair<string, List<ClientNodeTypeProto>> kv in BehaviorManager.GetInstance().Classify2NodeProtoList)
+            {
+                string classify = kv.Key;
+                List<ClientNodeTypeProto> nodeProtoList = kv.Value;
+                nodeProtoList.Sort(CompareShowName);
+                if (classify == NodeClassifyType.Root.ToString())
+                {
+                    continue;
+                }
+                foreach (var node in nodeProtoList)
+                {
+                    if (mSelectedNode != null && mSelectedNode.NodeData.Children.Count < mSelectedNode.NodeData.Proto.child_limit)
+                    {
+                        result.Add(node.name);
+                    }
+                }
+            }
+            return result;
+        }
+        ///菜单相关
+        public void PopMenu()
+		{
+			var menu = new GenericMenu();
+			
+            menu.AddItem(new GUIContent("创建子节点"), false, this.PopUpCreate);
+            menu.AddItem(new GUIContent("替换当前节点"), false, this.PopUpReplace);
+            string selectNodeName = BehaviorManager.GetInstance().selectNodeName;
+			string selectNodeType = BehaviorManager.GetInstance().selectNodeType;
+			if (mSelectedNode != null && selectNodeName != "")
+			{
+				if (selectNodeType != NodeClassifyType.Root.ToString() && mSelectedNode.NodeData.Children.Count < mSelectedNode.NodeData.Proto.child_limit)
+				{
+					menu.AddItem(new GUIContent(string.Format($"新建{selectNodeName}")), false, this.CreateNode);
+				}
+				else
+				{
+					menu.AddDisabledItem(new GUIContent("新建"));
+				}
+				if (mSelectedNode.NodeData.Proto.classify == NodeClassifyType.Root.ToString())
+				{
+					string menuName = string.Format($"替换成{selectNodeName}");
+					if (selectNodeType == NodeClassifyType.Root.ToString())
+					{
+						menu.AddItem(new GUIContent(menuName), false, this.ChangeNodeType);
+					}
+					else
+					{
+						menu.AddDisabledItem(new GUIContent(menuName));
+					}
+				}
+				else
+				{
+					string menuName = string.Format($"替换成{selectNodeName}");
+					NodeClassifyType value = (NodeClassifyType) Enum.Parse(typeof (NodeClassifyType), selectNodeType);
+					int count = ExportNodeTypeConfig.NodeTypeCountDict[value];
+					if (selectNodeType == NodeClassifyType.Root.ToString() || (count == 0 && mSelectedNode.NodeData.Proto.child_limit > 0))
+					{
+						menu.AddDisabledItem(new GUIContent(menuName));
+					}
+					else
+					{
+						menu.AddItem(new GUIContent(menuName), false, this.ChangeNodeType);
+					}
+				}
+			}
+			else
+			{
+				menu.AddDisabledItem(new GUIContent("新建"));
+				menu.AddDisabledItem(new GUIContent("替换"));
+			}
+            menu.AddItem(new GUIContent("自动排序"), false, this.AutoSort);
+            menu.AddItem(new GUIContent("复制"), false, this.CopyNode);
+			menu.AddItem(new GUIContent("剪切"), false, this.CutNode);
+			menu.AddItem(new GUIContent("粘贴"), false, this.PasteNode);
+			menu.AddItem(new GUIContent("删除节点"), false, this.RemoveNode);
+            menu.ShowAsContext();
+		}
+        private void PopUpCreate()
+        {
+            BehaviorDesignerWindow.Instance.ShowSubWin(mMousePos,SubWinType.CreateNode);
+        }
+        private void PopUpReplace()
+        {
+            BehaviorDesignerWindow.Instance.ShowSubWin(mMousePos, SubWinType.ReplaceNode);
+        }
+        private static int CompareShowName(ClientNodeTypeProto clientNodeType1, ClientNodeTypeProto clientNodeType2)
+		{
+			if (string.IsNullOrEmpty(clientNodeType1.name) || string.IsNullOrEmpty(clientNodeType2.name))
+			{
+				Log.Error("字符串输入参数有误");
+			}
+			return string.Compare(clientNodeType1.name, clientNodeType2.name);
+		}
+
+		public void AutoSort()
+		{
+			RootNode?.AutoSort();
+		}
+
+		private void AddNodeMenuCallback(object obj)
+		{
+			string nodeType = (string) obj;
+			var nodeProto = BehaviorManager.GetInstance().GetNodeTypeProto(nodeType);
+			var nodeData = BehaviorManager.GetInstance().CreateNode((int) BehaviorManager.GetInstance().CurTree.Id, nodeProto.name);
+			var node = CreateNode(nodeData, MousePosToGraphPos(mMousePos));
+		}
+
+		private void CreateNode()
+		{
+			var nodeProto = BehaviorManager.GetInstance().GetNodeTypeProto(BehaviorManager.GetInstance().selectNodeName);
+			var nodeData = BehaviorManager.GetInstance().CreateNode((int) BehaviorManager.GetInstance().CurTree.Id, nodeProto.name);
+			var node = CreateNode(nodeData, MousePosToGraphPos(mMousePos));
+		}
+
+		public void CopyNode()
+		{
+			mCutNode = null;
+			mCopyNode = mSelectedNode;
+			if (mSelectedNode != null)
+			{
+				BehaviorTreeTipsHelper.ShowMessage("复制节点" + mSelectedNode.NodeData.nodeId);
+			}
+		}
+
+		public void CutNode()
+		{
+			mCopyNode = null;
+			mCutNode = mSelectedNode;
+			if (mSelectedNode != null)
+			{
+				BehaviorTreeTipsHelper.ShowMessage("剪切节点" + mSelectedNode.NodeData.nodeId);
+			}
+		}
+
+		public void PasteNode()
+		{
+			if (mCutNode != null && mCutNode != mSelectedNode)
+			{
+				ConnectNode(mCutNode, mSelectedNode);
+			}
+			if (mCopyNode != null && mCopyNode != mSelectedNode)
+			{
+				var data = BehaviorManager.GetInstance().CopyNode(mCopyNode.NodeData);
+                BehaviorManager.GetInstance().ResetTreeId();
+				var node = CreateNode(data, Vector2.zero);
+				ConnectNode(node, mSelectedNode);
+			}
+		}
+
+		public void RemoveConnection()
+		{
+			if (mSelectedNode == null || mSelectedNode == RootNode)
+			{
+				return;
+			}
+
+			foreach (var node in mDetachedNodes)
+			{
+				if (node == mSelectedNode)
+				{
+					return;
+				}
+			}
+			mSelectedNode.Parent?.RemoveChild(mSelectedNode);
+			mDetachedNodes.Add(mSelectedNode);
+		}
+
+		public void RemoveNode()
+		{
+			if (mSelectedNode == null)
+			{
+				return;
+			}
+			if (mSelectedNode.Parent != null)
+			{
+				mSelectedNode.Parent.RemoveChild(mSelectedNode);
+				return;
+			}
+			mDetachedNodes.Remove(mSelectedNode);
+            BehaviorManager.GetInstance().ResetTreeId();
+        }
+
+		private void ChangeNodeType()
+		{
+			ChangeNodeType(BehaviorManager.GetInstance().selectNodeName);
+		}
+
+		//有待优化
+		private void ChangeNodeType(object obj)
+		{
+			string nodeType = (string) obj;
+			var nodeProto = BehaviorManager.GetInstance().GetNodeTypeProto(nodeType);
+			var nodeData = BehaviorManager.GetInstance().CreateNode((int) BehaviorManager.GetInstance().CurTree.Id, nodeProto.name);
+			var oldNode = mSelectedNode;
+			var newNode = new NodeDesigner(nodeData);
+
+			if (oldNode == RootNode)
+			{
+				newNode.NodeData.nodeId = RootNode.NodeData.nodeId;
+				RootNode = newNode;
+				var oldTree = BehaviorManager.GetInstance().CurTree;
+				var newTree = new BehaviorTreeData(oldTree.Id);
+				newTree.classify = oldTree.classify;
+				newTree.Root = nodeData;
+				BehaviorManager.GetInstance().CurTree = newTree;
+			}
+			else
+			{
+				int idx = oldNode.Parent.Children.IndexOf(oldNode);
+				oldNode.Parent.AddChild(newNode, idx);
+				oldNode.Parent.RemoveChild(oldNode);
+			}
+
+			foreach (var child in oldNode.Children)
+			{
+				newNode.AddChild(child);
+			}
+            BehaviorManager.GetInstance().ResetTreeId();
+            Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeAfterChangeNodeType);
+		}
+
+		public void onChangeNodeType(params object[] list)
+		{
+			ChangeNodeType(list[0]);
+		}
+
+		/// 节点逻辑相关
+		private readonly List<NodeDesigner> mDetachedNodes = new List<NodeDesigner>();
+
+		private NodeDesigner mRootNode;
+		private NodeDesigner mSelectedNode;
+		private NodeDesigner mCopyNode;
+		private NodeDesigner mCutNode;
+
+		public NodeDesigner RootNode
+		{
+			get
+			{
+				return mRootNode;
+			}
+			set
+			{
+				mRootNode = value;
+			}
+		}
+
+		public NodeDesigner CreateNode(BehaviorNodeData nodeData, Vector2 pos)
+		{
+			NodeDesigner node = new NodeDesigner(nodeData);
+			node.Pos = pos == Vector2.zero? CenterPosInBorder() : pos;
+			if (mSelectedNode != null)
+			{
+				mSelectedNode.AddChild(node);
+				mSelectedNode.AutoSort();
+			}
+			else
+			{
+				mDetachedNodes.Add(node);
+			}
+            BehaviorManager.GetInstance().ResetTreeId();
+            Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeCreateNode, node);
+			return node;
+		}
+
+		/// 事件相关
+		public NodeDesigner onCreateTree(params object[] list)
+		{
+            if (BehaviorManager.GetInstance().CurTree == null)
+            {
+                Log.Error($"CurTree can not be null");
+                return null;
+            }
+			RootNode = new NodeDesigner(BehaviorManager.GetInstance().CurTree.Root);
+			CalcGraphRect();
+            return RootNode;
+		}
+
+		public void onSelectNode(params object[] list)
+		{
+			mSelectedNode?.onSelect(false);
+			mSelectedNode = (NodeDesigner) list[1];
+			mSelectedNode.onSelect(true);
+		}
+
+		public void onCreateNode(params object[] list)
+		{
+			string name = (string) list[0];
+			Vector2 pos = (Vector2) list[1];
+
+			var nodeProto = BehaviorManager.GetInstance().GetNodeTypeProto(name);
+			var nodeData = BehaviorManager.GetInstance().CreateNode((int) BehaviorManager.GetInstance().CurTree.Id, nodeProto.name);
+			CreateNode(nodeData, pos);
+		}
+
+		public void onStartConnect(params object[] list)
+		{
+			var node = (NodeDesigner) list[0];
+			var state = (State) list[1];
+			if (node == RootNode && state == State.ConnectLeft) //根节点不让左连接
+			{
+				return;
+			}
+			mState = state;
+		}
+
+		public void onMouseInNode(params object[] list)
+		{
+			var dstNode = (NodeDesigner) list[1];
+			if (dstNode == mSelectedNode || dstNode == null)
+			{
+				return;
+			}
+			switch (mState)
+			{
+				case State.Normal:
+					ClickNode(dstNode);
+					break;
+				case State.Drag:
+					break;
+				case State.Shift:
+					ShiftNode(dstNode);
+					break;
+				case State.Ctrl:
+					MoveNode(dstNode);
+					break;
+				case State.ConnectLeft:
+					ConnectNode(mSelectedNode, dstNode);
+					break;
+				case State.ConnectRight:
+					ConnectNode(dstNode, mSelectedNode);
+					break;
+			}
+		}
+
+		//src接到dst的子节点
+		public void ConnectNode(NodeDesigner srcNode, NodeDesigner dstNode)
+		{
+			if (srcNode == null || dstNode == null || !dstNode.NodeData.CanAddChild())
+			{
+				return;
+			}
+			if (srcNode.FindChild(dstNode))
+			{
+				//src有dst这个子节点不让连,避免死循环
+				//Log.Info("found child");
+				return;
+			}
+
+			var parent = srcNode.Parent;
+			if (parent != null)
+			{
+				parent.RemoveChild(srcNode);
+			}
+			dstNode.AddChild(srcNode);
+			dstNode.AutoSort();
+
+			mDetachedNodes.Remove(srcNode);
+		}
+
+		public void ClickNode(NodeDesigner dstNode)
+		{
+			Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeClickNode, dstNode);
+		}
+
+		public void ShiftNode(NodeDesigner dstNode)
+		{
+			Log.Info("shift node");
+
+			if (mSelectedNode == null)
+			{
+				return;
+			}
+			var node1 = dstNode;
+			var node2 = mSelectedNode;
+			var parent1 = node1.Parent;
+			var parent2 = node2.Parent;
+			//根节点不可交换
+			if (parent2 == null)
+			{
+				return;
+			}
+			//同父交换位置
+			if (parent1 == parent2)
+			{
+				parent1.RemoveChild(node2);
+				int idx = parent1.Children.IndexOf(node1);
+				parent1.AddChild(node2, idx);
+				parent1.AutoSort();
+				//BehaviorManager.GetInstance().ResetTreeId();
+			}
+
+			//             //不同父,插到node1的子节点
+			//             if (!node1.NodeData.CanAddChild())
+			//                 return;
+			// 
+			//             parent2.RemoveChild(node2);
+			//             parent2.AutoSort();
+			//             node1.AddChild(node2);
+			//             node1.AutoSort();
+			//             BehaviorManager.GetInstance().ResetTreeId();
+		}
+
+		public void MoveNode(NodeDesigner dstNode)
+		{
+			Log.Info("Move  node");
+
+			if (mSelectedNode == null)
+			{
+				return;
+			}
+			var node1 = dstNode;
+			var node2 = mSelectedNode;
+			var parent1 = node1.Parent;
+			var parent2 = node2.Parent;
+			//根节点不可交换
+			if (parent2 == null)
+			{
+				return;
+			}
+
+			//不同父,插到node1的子节点
+			if (!node1.NodeData.CanAddChild())
+			{
+				return;
+			}
+
+			parent2.RemoveChild(node2);
+			parent2.AutoSort();
+			node1.AddChild(node2);
+			node1.AutoSort();
+			//BehaviorManager.GetInstance().ResetTreeId();
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/GraphDesigner.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 834873f3d04ba7249a372bb9c5d2d705
+timeCreated: 1445249041
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 373 - 0
Unity/Assets/Editor/BehaviorTreeEditor/NodeDesigner.cs

@@ -0,0 +1,373 @@
+using System.Collections.Generic;
+using Base;
+using Model;
+using UnityEngine;
+
+namespace MyEditor
+{
+	public class NodeDesigner
+	{
+		private NodeDesigner mParent;
+		private Texture2D mBoxHighLight;
+		private Texture2D mBoxSelectHighLight;
+		private bool isSelected;
+
+		public NodeDesignerProto DesignerData { get; set; }
+
+		public NodeDesigner(BehaviorNodeData data)
+		{
+			NodeData = data;
+			data.NodeDesigner = this;
+			DesignerData = new NodeDesignerProto();
+			Init();
+			UpdateChildren();
+		}
+
+		public List<NodeDesigner> Children { get; } = new List<NodeDesigner>();
+
+		public NodeDesigner Parent
+		{
+			get
+			{
+				return mParent;
+			}
+			set
+			{
+				mParent = value;
+			}
+		}
+
+		public void UpdateChildren()
+		{
+			if (!DesignerData.fold)
+			{
+				this.Children.Clear();
+				foreach (var childData in NodeData.Children)
+				{
+					var child = new NodeDesigner(childData);
+					this.Children.Add(child);
+					child.Parent = this;
+				}
+			}
+			else
+			{
+				this.Children.Clear();
+				return;
+			}
+			UpdateChildrenPos(this.Offset);
+		}
+
+		public BehaviorNodeData NodeData { get; set; }
+		//坐标位置相关
+		public float Width;
+		public float Height;
+		public Vector2 Pos = Vector2.zero; //中心点
+
+		public Vector2 Offset
+		{
+			get
+			{
+				return new Vector2(DesignerData.x, DesignerData.y);
+			}
+			set
+			{
+				DesignerData.x = value.x;
+				DesignerData.y = value.y;
+			}
+		}
+
+		public Vector2 LeftPos //左边坐标
+		{
+			get
+			{
+				return new Vector2(Pos.x - Width / 2, Pos.y);
+			}
+		}
+
+		public Vector2 RightPos //右边坐标
+		{
+			get
+			{
+				return new Vector2(Pos.x + Width / 2, Pos.y);
+			}
+		}
+
+		public Rect Size;
+
+		private bool mShowValue;
+		private Texture2D mBoxTex;
+		private Texture2D mLeftConnectTex;
+		private Texture2D mRightConnectTex;
+		private Texture2D mFoldTrueTex = null;
+		private Texture2D mFoldFalseTex = null;
+
+		public void Init()
+		{
+			NodeData.Proto = BehaviorManager.GetInstance().GetNodeTypeProto(NodeData.name);
+			string[] arr = NodeData.Proto.style.Split('/');
+			if (arr.Length > 1 && arr[1] == "value")
+			{
+				mShowValue = true;
+			}
+			string style = arr.Length > 0? arr[0] : "";
+			if (style == "")
+			{
+				switch (NodeData.Classify)
+				{
+					case "装饰节点":
+						style = "green";
+						break;
+					case "复合节点":
+						style = "blue";
+						break;
+					case "条件节点":
+						style = "orange";
+						break;
+				}
+				switch (NodeData.name)
+				{
+					case "Sequence":
+						style = "blue";
+						break;
+					case "Selector":
+						style = "green";
+						break;
+					default:
+						style = "default";
+						break;
+				}
+			}
+			mBoxTex = BehaviorDesignerUtility.GetTexture(style);
+			mBoxHighLight = BehaviorDesignerUtility.GetTexture("HighLight");
+			mBoxSelectHighLight = BehaviorDesignerUtility.GetTexture("SelectHighLight");
+
+			if (mBoxTex == null)
+			{
+				mBoxTex = BehaviorDesignerUtility.GetTexture("default");
+			}
+			if (mBoxTex == null)
+			{
+				Log.Info("mBoxTex null " + NodeData.nodeId);
+			}
+			Width = mBoxTex.width / 2;
+			Height = mBoxTex.height / 2;
+
+			mLeftConnectTex = BehaviorDesignerUtility.GetTexture("LeftConnect");
+			mRightConnectTex = BehaviorDesignerUtility.GetTexture("RightConnect");
+			mFoldTrueTex = BehaviorDesignerUtility.GetTexture("FoldTrue");
+			mFoldFalseTex = BehaviorDesignerUtility.GetTexture("FoldFalse");
+		}
+
+		public void Draw()
+		{
+			foreach (var child in this.Children)
+			{
+				//先画子节点,让线条在最低层
+				BehaviorDesignerUtility.DrawConnection(this.RightPos, child.LeftPos);
+				child.Draw();
+			}
+
+			//左链接
+			var tex = mLeftConnectTex;
+			var rect = new Rect(Pos.x - Width / 2 - tex.width / 6, Pos.y - tex.height / 4, tex.width / 2, tex.height / 2);
+			GUI.DrawTexture(rect, tex);
+			//右链接
+			if (NodeData.Proto.child_limit > 0)
+			{
+				tex = mRightConnectTex;
+				rect = new Rect(Pos.x + Width / 2 - tex.width / 6 * 2, Pos.y - tex.height / 4.1f, tex.width / 2, tex.height / 2);
+				GUI.DrawTexture(rect, tex);
+
+				if (NodeData.Children.Count > 0)
+				{
+					if (DesignerData.fold)
+					{
+						GUI.Label(new Rect(Pos.x + Width / 2 - 5f, Pos.y - 9f, tex.width, tex.height), "+");
+					}
+					else
+					{
+						GUI.Label(new Rect(Pos.x + Width / 2 - 8f, Pos.y - 9f, tex.width, tex.height), "—");
+					}
+				}
+			}
+
+			rect = new Rect(Pos.x - Width / 2, Pos.y - Height / 2, Width, Height);
+			GUI.DrawTexture(rect, mBoxTex);
+			if (isSelected)
+			{
+				GUI.DrawTexture(rect, mBoxSelectHighLight);
+			}
+			else if (BehaviorManager.GetInstance().IsHighLight(this.NodeData))
+			{
+				GUI.DrawTexture(rect, mBoxHighLight);
+			}
+
+			GUIStyle style = new GUIStyle();
+			style.normal.background = null;
+			style.normal.textColor = new Color(1, 1, 1);
+			style.fontSize = 15;
+			if (!this.isSelected)
+			{
+				style.clipping = TextClipping.Clip;
+			}
+			GUI.Label(new Rect(Pos.x - Width / 2 + 5f, Pos.y - Height / 3, Width - 10f, Height / 2), NodeData.Proto.name, style);
+
+			style.normal.textColor = new Color(0.8f, 0.8f, 0.8f);
+			style.fontSize = 12;
+			style.wordWrap = true;
+			string deprecatedDesc = NodeData.Proto.isDeprecated? $"({NodeData.Proto.deprecatedDesc})" : "";
+			GUI.Label(new Rect(Pos.x - Width / 2 + 6f, Pos.y, Width - 12f, Height / 2.1f), NodeData.describe + deprecatedDesc, style);
+
+			tex = null;
+			switch (NodeData.NodeDeubgState)
+			{
+				case DebugState.True:
+					tex = BehaviorDesignerUtility.GetTexture("Execute");
+					break;
+				//                 case DebugState.False:
+				//                     tex = BehaviorDesignerUtility.GetTexture("False");
+				//                     break;
+				//                 case DebugState.Error:
+				//                     tex = BehaviorDesignerUtility.GetTexture("Error");
+				//                     break;
+			}
+			if (tex != null)
+			{
+				GUI.DrawTexture(rect, tex);
+				//                 string time = System.DateTime.Now.ToString();
+				//                 GUI.Label(new Rect(Pos.x + Width / 2, Pos.y -20, Width - 12f, Height / 2.1f), time, style);
+			}
+		}
+
+		public void AddChild(NodeDesigner child, int index = -1)
+		{
+			index = index == -1? this.Children.Count : index;
+			this.Children.Insert(index, child);
+			child.Parent = this;
+			NodeData.AddChild(child.NodeData, index);
+		}
+
+		public void RemoveChild(NodeDesigner child)
+		{
+			this.Children.Remove(child);
+			child.Parent = null;
+			NodeData.RemoveChild(child.NodeData);
+		}
+
+		public void UpdateSize()
+		{
+			Size.width = Width * 1.5f;
+			Size.height = Height;
+			if (this.Children.Count == 0)
+			{
+				return;
+			}
+			foreach (var child in this.Children)
+			{
+				child.UpdateSize();
+			}
+
+			float max = 0;
+			foreach (var child in this.Children)
+			{
+				max = max < child.Size.width? child.Size.width : max;
+			}
+			Size.width += max;
+
+			Size.height = 0;
+			foreach (var child in this.Children)
+			{
+				Size.height += child.Size.height;
+			}
+		}
+
+		public void UpdateChildrenPos(Vector2 offset)
+		{
+			UpdateSize();
+			float y = this.Pos.y - this.Size.height / 2;
+			foreach (var child in this.Children)
+			{
+				child.Pos.x = this.Pos.x + Width * 1.5f + child.Offset.x;
+				child.Pos.y = y + child.Size.height / 2 + child.Offset.y;
+				y += child.Size.height;
+				child.UpdateChildrenPos(offset);
+			}
+		}
+
+		public void OnMousePos(Vector2 mouse)
+		{
+			//判断是否被点中
+			if (!isSelected && mouse.x > Pos.x - Width / 2 - 30f && mouse.x < Pos.x + Width / 2 + 30f && mouse.y > Pos.y - Height / 2 &&
+			    mouse.y < Pos.y + Height / 2)
+			{
+				Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeMouseInNode, NodeData, this);
+			}
+			//并判断是否点中了连线柄
+			if (mouse.x > LeftPos.x - 30f && mouse.x < LeftPos.x + 10f && mouse.y > LeftPos.y - 30f && mouse.y < LeftPos.y + 30f)
+			{
+				Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeConnectState, this, State.ConnectLeft);
+			}
+
+			if (mouse.x > RightPos.x - 10f && mouse.x < RightPos.x + 30f && mouse.y > RightPos.y - 30f && mouse.y < RightPos.y + 30f && NodeData.CanAddChild())
+			{
+				Game.Scene.GetComponent<EventComponent>().Run(EventIdType.BehaviorTreeConnectState, this, State.ConnectRight);
+			}
+
+			for (int i = 0; i < this.Children.Count; i++)
+			{
+				this.Children[i].OnMousePos(mouse);
+			}
+		}
+
+		public void onSelect(bool flag)
+		{
+			isSelected = flag;
+			if (flag)
+			{
+				BehaviorManager.GetInstance().SelectNode(this.NodeData);
+			}
+		}
+
+		public void onDrag(Vector2 delta)
+		{
+			Offset = new Vector2(Offset.x + delta.x, Offset.y + delta.y);
+			Pos.x += delta.x;
+			Pos.y += delta.y;
+			UpdateChildrenPos(this.Offset);
+		}
+
+		//折叠
+		public void Fold()
+		{
+			DesignerData.fold = !DesignerData.fold;
+			UpdateChildren();
+		}
+
+		//自动排序
+		public void AutoSort()
+		{
+			this.Offset = Vector2.zero;
+			foreach (var child in this.Children)
+			{
+				child.AutoSort();
+			}
+			UpdateChildrenPos(this.Offset);
+		}
+
+		public bool FindChild(NodeDesigner dstNode)
+		{
+			if (this == dstNode)
+			{
+				return true;
+			}
+			foreach (var child in this.Children)
+			{
+				if (child.FindChild(dstNode))
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+	}
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/NodeDesigner.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9b9dab93ac8426c49abf1e0f3c557047
+timeCreated: 1445224516
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 284 - 0
Unity/Assets/Editor/BehaviorTreeEditor/NodeExtension.cs

@@ -0,0 +1,284 @@
+using MyEditor;
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using UnityEditor;
+using UnityEngine;
+
+namespace Model
+{
+    public class BTEditorTree
+    {
+        private int _id = BehaviorManager.NodeIdStartIndex;
+        private Node _root;
+        private BehaviorTreeConfig _config;
+        public BTEditorTree(BehaviorTreeConfig config)
+        {
+            Type rootType = Game.EntityEventManager.GetAssembly("Controller").GetType($"Controller.{config.RootNodeProto.name}");
+            Node root = (Node)Activator.CreateInstance(rootType, config.RootNodeProto);
+            root.Id = BehaviorManager.NodeIdStartIndex;
+            Queue<NodeProto> protoStack = new Queue<NodeProto>();
+            Queue<Node> nodeStack = new Queue<Node>();
+            protoStack.Enqueue(config.RootNodeProto);
+            nodeStack.Enqueue(root);
+            while (protoStack.Count > 0)
+            {
+                NodeProto p = protoStack.Dequeue();
+                Node node = nodeStack.Dequeue();
+
+                foreach (var argsItem in p.args_dict)
+                {
+                    FieldInfo fieldInfo = node.GetType().GetField(argsItem.Key, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
+                    fieldInfo.SetValue(node, argsItem.Value.GetValueByType(fieldInfo.FieldType));
+                }
+                foreach (NodeProto child in p.Children)
+                {
+                    Type t = Game.EntityEventManager.GetAssembly("Controller").GetType($"Controller.{child.name}");
+                    Node childNode = (Node)Activator.CreateInstance(t, child);
+                    AddChild(childNode, node);
+                    protoStack.Enqueue(child);
+                    nodeStack.Enqueue(childNode);
+                }
+            }
+            _config = config;
+            _root = root;
+        }
+
+        public T CreateNode<T>(Node parent) where T : Node
+        {
+            T node = (T)Activator.CreateInstance(typeof(T), new NodeProto());
+            AddChild(node, parent);
+            return node;
+        }
+
+        public string Description
+        {
+            get { return _root.Description; }
+            set { _root.Description = value; }
+        }
+
+        public BehaviorTreeConfig BTConfig
+        {
+            get { return _config; }
+        }
+
+        public T GetRoot<T>() where T : Node
+        {
+            return _root as T;
+        }
+
+        private BTEditorTree(Node root, BehaviorTreeConfig config)
+        {
+            _root = root;
+            _root.Id = BehaviorManager.NodeIdStartIndex;
+            _config = config;
+        }
+       
+        public static BTEditorTree CreateTree<T>(GameObject source)
+        {
+            BehaviorTreeConfig sourceTree = source.GetComponent<BehaviorTreeConfig>();
+            if (sourceTree == null)
+            {
+                sourceTree = source.AddComponent<BehaviorTreeConfig>();
+            }
+            Node root = (Node)Activator.CreateInstance(typeof(T), new NodeProto());
+            BTEditorTree tree = new BTEditorTree(root, sourceTree);
+            return tree;
+        }
+
+        public static BTEditorTree OpenFromGameObject(GameObject source)
+        {
+            BehaviorTreeConfig sourceTree = source.GetComponent<BehaviorTreeConfig>();
+            if (sourceTree == null)
+            {
+                throw new GameException($"{source.name}预制中不包含行为树");
+            }
+            return new BTEditorTree(sourceTree);
+        }
+
+        public T GetChildInType<T>() where T : Node
+        {
+            Queue<Node> nodeStack = new Queue<Node>();
+            nodeStack.Enqueue(_root);
+            while (nodeStack.Count > 0)
+            {
+                Node c = nodeStack.Dequeue();
+                if (c.GetType() == typeof(T))
+                {
+                    return c as T;
+                }
+                foreach (Node child in c.GetChildren)
+                {
+                    nodeStack.Enqueue(child);
+                }
+            }
+            return null;
+        }
+
+        public void AddChild(Node child, Node parent)
+        {
+            parent.AddChild(child);
+            child.Id = ++_id;
+        }
+
+        public T[] GetChildrenInType<T>() where T : Node
+        {
+            Queue<Node> nodeStack = new Queue<Node>();
+            List<T> list = new List<T>();
+            nodeStack.Enqueue(_root);
+            while (nodeStack.Count > 0)
+            {
+                Node c = nodeStack.Dequeue();
+                if (c.GetType() == typeof(T))
+                {
+                    list.Add(c as T);
+                }
+                foreach (Node child in c.GetChildren)
+                {
+                    nodeStack.Enqueue(child);
+                }
+            }
+            return list.ToArray();
+        }
+
+        public void SaveToBehaviorTreeConfig(BehaviorTreeConfig config)
+        {
+            _root.Serialize(config);
+        }
+
+        public void Save()
+        {
+            if (IsPrefab(_config.gameObject))
+            {
+                GameObject go = GameObject.Instantiate(_config.gameObject);
+                go.name = _config.gameObject.name;
+                BehaviorTreeConfig newConfig = go.GetComponent<BehaviorTreeConfig>();
+                _root.Serialize(newConfig);
+                PrefabUtility.ReplacePrefab(go, _config, ReplacePrefabOptions.ReplaceNameBased);
+                GameObject.DestroyImmediate(go);
+            }
+            else
+            {
+                _root.Serialize(_config);
+            }
+        }
+
+        private bool IsPrefab(GameObject go)
+        {
+            string path = AssetDatabase.GetAssetPath(_config);
+            return !string.IsNullOrEmpty(path);
+        }
+    }
+
+    public static class NodeExtension
+    {
+        public static T FindChildOnDesc<T>(this Node node, string desc) where T : Node
+        {
+            foreach (Node child in node.GetChildren)
+            {
+                if (child.Description == desc)
+                {
+                    return node as T;
+                }
+            }
+            return null;
+        }
+
+        public static T GetChildInType<T>(this Node root) where T : Node
+        {
+            Queue<Node> nodeStack = new Queue<Node>();
+            nodeStack.Enqueue(root);
+            while (nodeStack.Count > 0)
+            {
+                Node c = nodeStack.Dequeue();
+                foreach (Node child in c.GetChildren)
+                {
+                    if (child.GetType() == typeof(T))
+                    {
+                        return child as T;
+                    }
+                    nodeStack.Enqueue(child);
+                }
+            }
+            return null;
+        }
+
+        public static T[] GetChildrenInType<T>(this Node root) where T : Node
+        {
+            Queue<Node> nodeStack = new Queue<Node>();
+            List<T> list = new List<T>();
+            nodeStack.Enqueue(root);
+            while (nodeStack.Count > 0)
+            {
+                Node c = nodeStack.Dequeue();
+                foreach (Node child in c.GetChildren)
+                {
+                    if (child.GetType() == typeof(T))
+                    {
+                        list.Add(child as T);
+                    }
+                    nodeStack.Enqueue(child);
+                }
+            }
+            return list.ToArray();
+        }
+        public static void Serialize(this Node root, BehaviorTreeConfig config)
+        {
+            config.Clear();
+            BehaviorNodeConfig rootNp = config.AddRootNode(root.GetType().Name);
+            Queue<Node> queue = new Queue<Node>();
+            Queue<BehaviorNodeConfig> npQue = new Queue<BehaviorNodeConfig>();
+            rootNp.describe = root.Description;
+            queue.Enqueue(root);
+            npQue.Enqueue(rootNp);
+            while (queue.Count > 0)
+            {
+                Node cur = queue.Dequeue();
+                BehaviorNodeConfig np = npQue.Dequeue();
+                foreach (Node child in cur.GetChildren)
+                {
+                    BehaviorNodeConfig childNp = GetNodeConfigFromNode(child);
+                    queue.Enqueue(child);
+                    npQue.Enqueue(childNp);
+                    config.AddChild(np, childNp);
+                }
+            }
+//             PrintNode(root);
+//             PrintConfigNode(config.RootNodeConfig);
+        }
+//         private static void PrintNode(Node node)
+//         {
+//             Log.Info($"id:{node.Id}  type:{node.GetType().Name}");
+//             foreach (var child in node.GetChildren)
+//             {
+//                 PrintNode(child);
+//             }
+//         }
+//         private static void PrintConfigNode(BehaviorNodeConfig node)
+//         {
+//             Log.Info($"nodeConfigId:{node.id}  nodeConfigType:{node.name} childCount:{node.transform.childCount}");
+//             foreach (Transform child in node.transform)
+//             {
+//                 PrintConfigNode(child.gameObject.GetComponent<BehaviorNodeConfig>());
+//             }
+//         }
+
+        private static NodeProto GetNodeProtoFromNode(Node node)
+        {
+            NodeProto np = new NodeProto();
+            np.nodeId = (int)node.Id;
+            FieldInfo[] mens = node.GetType().GetFields();
+            np.describe = node.Description;
+            np.name = node.GetType().Name;
+            foreach (FieldInfo men in mens)
+            {
+                np.args_dict.SetKeyValueComp(men.FieldType, men.Name, men.GetValue(node));
+            }
+            return np;
+        }
+        private static BehaviorNodeConfig GetNodeConfigFromNode(Node node)
+        {
+            return BehaviorNodeConfigExtension.ProtoToConfig(GetNodeProtoFromNode(node));
+        }
+    }
+}

+ 12 - 0
Unity/Assets/Editor/BehaviorTreeEditor/NodeExtension.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 06fc66bf8a0291c4e89ef15ec6486f24
+timeCreated: 1474533109
+licenseType: Pro
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 1313c2b359c675b4e88c8c4d38dc59b4
+folderAsset: yes
+timeCreated: 1486458634
+licenseType: Pro
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/Bg.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/Bg.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: e32dde63ad92af041877969749ee8c63
+timeCreated: 1449654354
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/BgLine.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/BgLine.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: e8377c9eb02990742a168c9b3b910129
+timeCreated: 1449654318
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/DragIcon.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/DragIcon.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: efe6db2837926714eb5bcd0cb75cf145
+timeCreated: 1451531865
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/Error.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/Error.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: d60673d4340350b458ae68fb0289bf24
+timeCreated: 1450344240
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/Execute.png


+ 57 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/Execute.png.meta

@@ -0,0 +1,57 @@
+fileFormatVersion: 2
+guid: 86520959e840cd74db5a81c9f8287fa9
+timeCreated: 1467167597
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 7
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+    outline: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/False.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/False.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: 0e365bf6c03d807499f2e752286db1b0
+timeCreated: 1450085031
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/HighLight.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/HighLight.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: 468d8ad9125387641bf8844cff5912b5
+timeCreated: 1449811576
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/LeftConnect.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/LeftConnect.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: 9eadb585690aeef4fa4c051dc7d26cfd
+timeCreated: 1450060197
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/RightConnect.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/RightConnect.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: f81309799121cb344abab8c27226923a
+timeCreated: 1450060197
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/SelectHighLight.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/SelectHighLight.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: 1222e9b63c7117c47bf9ec8b5f347dfd
+timeCreated: 1450064233
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/ShiftIcon.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/ShiftIcon.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: 0744818daf7d82d45b534869e9746462
+timeCreated: 1451531865
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/True.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/True.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: e7ccf46f66171bb4491c1f77d88b7858
+timeCreated: 1450082734
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/blue.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/blue.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: ac809af2a0ce2d1489b5db1d8b668f61
+timeCreated: 1449731762
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/default.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/default.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: b21f78cb47cab8a409bbe7c7331f8be7
+timeCreated: 1449731945
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/green.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/green.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: a82cc1b059d7d0b4681eda29d2bce920
+timeCreated: 1449731762
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/orange.png


+ 56 - 0
Unity/Assets/Editor/BehaviorTreeEditor/Pic/orange.png.meta

@@ -0,0 +1,56 @@
+fileFormatVersion: 2
+guid: 1027c8091bd4a41419f3be5a4bf5d137
+timeCreated: 1449731762
+licenseType: Pro
+TextureImporter:
+  fileIDToRecycleName: {}
+  serializedVersion: 2
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 1
+    linearTexture: 0
+    correctGamma: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: .25
+    normalMapFilter: 0
+  isReadable: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 0
+  cubemapConvolution: 0
+  cubemapConvolutionSteps: 8
+  cubemapConvolutionExponent: 1.5
+  seamlessCubemap: 0
+  textureFormat: -1
+  maxTextureSize: 2048
+  textureSettings:
+    filterMode: -1
+    aniso: -1
+    mipBias: -1
+    wrapMode: -1
+  nPOTScale: 1
+  lightmap: 0
+  rGBM: 0
+  compressionQuality: 50
+  allowsAlphaSplitting: 0
+  spriteMode: 0
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: .5, y: .5}
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spritePixelsToUnits: 100
+  alphaIsTransparency: 0
+  textureType: -1
+  buildTargetSettings: []
+  spriteSheet:
+    sprites: []
+  spritePackingTag: 
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Unity/Assets/Editor/BehaviorTreeEditor/Pic/pink.png


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor