Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #if UNITY_EDITOR
- using UnityEditor;
- using UnityEngine;
- using System.IO;
- using System.Collections.Generic;
- using BehaviourTree;
- public class BehaviourTreeEditorWindow : EditorWindow
- {
- [MenuItem("Window/Behaviour Tree Editor")]
- static void ShowWindow()
- {
- EditorWindow.GetWindow(typeof(BehaviourTreeEditorWindow));
- }
- static string[] _comparisonTypeLabels = new string[] {"equal to", "not equal to", "greater than", "greater than or equal to", "lesser than", "lesser than or equal to"};
- static ComparisonType[] _comparisonTypeValues = new ComparisonType[] {ComparisonType.EqualTo, ComparisonType.NotEqualTo, ComparisonType.GreaterThan, ComparisonType.GreaterThanOrEqualTo, ComparisonType.LesserThan, ComparisonType.LesserThanOrEqualTo};
- string _lastAssetPath = "";
- string _lastBehaviourTreeSelected = "";
- string _currentlyOpenBehaviourTree = "";
- Root<IUnit> _currentBehaviourTree = null;
- static GUISkin _guiSkin;
- static GUISkin GetSkin()
- {
- if (_guiSkin == null)
- {
- _guiSkin = Resources.Load("BehaviourTreeGuiSkin") as GUISkin;
- }
- return _guiSkin;
- }
- Vector2 _panOffset = Vector2.zero;
- bool IsFolder(string path)
- {
- return ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory);
- }
- void OnSelectionChange()
- {
- string assetTryPath = AssetDatabase.GetAssetPath(Selection.activeObject);
- if (assetTryPath.Length > 0)
- {
- string absPath = Application.dataPath;
- absPath = absPath.Substring(0, absPath.LastIndexOf('/')+1); // get rid of "Assets/"
- absPath += assetTryPath;
- _lastBehaviourTreeSelected = absPath;
- if (IsFolder(assetTryPath))
- {
- _lastAssetPath = assetTryPath;
- }
- else
- {
- _lastAssetPath = Path.GetDirectoryName(assetTryPath);
- }
- Repaint();
- }
- Debug.Log("Last Asset Path: " + _lastAssetPath);
- }
- BehaviourTree.Root<IUnit> PopulateTestValues()
- {
- BehaviourTree.Root<IUnit> root = new BehaviourTree.Root<IUnit>();
- root.Label = "Dragurian Gunner Test AI";
- BehaviourTree.Selector<IUnit> sel1 = new BehaviourTree.Selector<IUnit>();
- sel1.Label = "";
- BehaviourTree.Sequence<IUnit> retSeq = new BehaviourTree.Sequence<IUnit>();
- retSeq.Label = "Retreat";
- retSeq.Remarks = "Should I retreat now?";
- BehaviourTree.MyHealthPercentCheck<IUnit> myHealth = new BehaviourTree.MyHealthPercentCheck<IUnit>();
- myHealth.Label = "health low?";
- myHealth.Comparison = BehaviourTree.ComparisonType.LesserThanOrEqualTo;
- myHealth.Value = 0.25f;
- BehaviourTree.Retreat<IUnit> ret = new BehaviourTree.Retreat<IUnit>();
- ret.Label = "retreat!";
- ret.CheckForEnemiesDistance = 10.0f;
- ret.EnemiesNearEachOtherDistance = 10.0f;
- ret.DistanceToFlee = 20.0f;
- BehaviourTree.Sequence<IUnit> lungeSeq = new BehaviourTree.Sequence<IUnit>();
- lungeSeq.Label = "Attack";
- lungeSeq.Remarks = "Only melee attack for now.";
- BehaviourTree.AssignNearestEnemyAsTarget<IUnit> nearestEnemy = new BehaviourTree.AssignNearestEnemyAsTarget<IUnit>();
- nearestEnemy.Label = "find nearest enemy!";
- //BehaviourTree.HasSufficientStaminaToDo canLunge = new BehaviourTree.HasSufficientStaminaToDo();
- //canLunge.Label = "CanLungeNow?";
- BehaviourTree.GetInMeleeRangeOfTarget<IUnit> getInLungeRange = new BehaviourTree.GetInMeleeRangeOfTarget<IUnit>(); // can return running
- getInLungeRange.Label = "get in lunge range!";
- getInLungeRange.ActionName = "Strike";
- getInLungeRange.AttackName = "Lunge";
- BehaviourTree.GetInMeleeRangeOfTarget<IUnit> getInLungeRange2 = new BehaviourTree.GetInMeleeRangeOfTarget<IUnit>(); // can return running
- getInLungeRange2.Label = "get in lunge range!";
- getInLungeRange2.ActionName = "Strike";
- getInLungeRange2.AttackName = "Lunge";
- BehaviourTree.GetInMeleeRangeOfTarget<IUnit> getInLungeRange3 = new BehaviourTree.GetInMeleeRangeOfTarget<IUnit>(); // can return running
- getInLungeRange3.Label = "get in lunge range!";
- getInLungeRange3.ActionName = "Strike";
- getInLungeRange3.AttackName = "Lunge";
- BehaviourTree.DoActionOnTarget<IUnit> strike = new BehaviourTree.DoActionOnTarget<IUnit>();
- strike.Label = "strike!";
- strike.ActionName = "Strike";
- BehaviourTree.DoActionOnTarget<IUnit> strike2 = new BehaviourTree.DoActionOnTarget<IUnit>();
- strike2.Label = "strike!";
- strike2.ActionName = "Strike";
- BehaviourTree.EnoughStaminaTo<IUnit> canGetInRange = new BehaviourTree.EnoughStaminaTo<IUnit>();
- canGetInRange.Label = "enough stamina to";
- BehaviourTree.EnoughStaminaTo<IUnit> canLunge = new BehaviourTree.EnoughStaminaTo<IUnit>();
- canLunge.Label = "enough stamina to";
- BehaviourTree.PassTurn<IUnit> passTurn = new BehaviourTree.PassTurn<IUnit>();
- passTurn.Label = "pass turn!";
- BehaviourTree.Sequence<IUnit> shootSeq = new BehaviourTree.Sequence<IUnit>();
- shootSeq.Label = "ToShoot";
- // test decorators:
- BehaviourTree.EnoughStaminaTo<IUnit> d1 = new BehaviourTree.EnoughStaminaTo<IUnit>();
- d1.Label = "Inverse";
- BehaviourTree.EnoughStaminaTo<IUnit> d2 = new BehaviourTree.EnoughStaminaTo<IUnit>();
- d2.Label = "Semaphore B";
- d2.Adopt(d1);
- BehaviourTree.EnoughStaminaTo<IUnit> d3 = new BehaviourTree.EnoughStaminaTo<IUnit>();
- d3.Label = "Control Target";
- BehaviourTree.EnoughStaminaTo<IUnit> d4 = new BehaviourTree.EnoughStaminaTo<IUnit>();
- d4.Label = "Time Delay";
- BehaviourTree.EnoughStaminaTo<IUnit> d5 = new BehaviourTree.EnoughStaminaTo<IUnit>();
- d5.Label = "Semaphore A";
- d5.Adopt(d4);
- d4.Adopt(d3);
- root.Adopt(sel1);
- //sel1.Adopt(retSeq);
- sel1.Adopt(d5);
- d3.Adopt(retSeq);
- //retSeq.Adopt(myHealth);
- retSeq.Adopt(d2);
- d1.Adopt(myHealth);
- retSeq.Adopt(ret);
- sel1.Adopt(lungeSeq);
- lungeSeq.Adopt(nearestEnemy);
- BehaviourTree.Selector<IUnit> lungeOrCloseIn = new BehaviourTree.Selector<IUnit>();
- lungeOrCloseIn.Label = "";
- BehaviourTree.Sequence<IUnit> actualLungeSeq = new BehaviourTree.Sequence<IUnit>();
- actualLungeSeq.Label = "Lunge";
- actualLungeSeq.Remarks = "Checks first if unit has enough stamina to close in *and* do the attack. Bails out if it can't do both in this turn.";
- BehaviourTree.Sequence<IUnit> closeInSeq = new BehaviourTree.Sequence<IUnit>();
- closeInSeq.Label = "Close in";
- closeInSeq.Remarks = "Just close in on the enemy if can't do anything useful. Later on, I'll add higher priority behaviours like try ranged attack (if the Lunge failed).";
- lungeSeq.Adopt(lungeOrCloseIn);
- lungeOrCloseIn.Adopt(actualLungeSeq);
- lungeOrCloseIn.Adopt(closeInSeq);
- canGetInRange.Adopt(getInLungeRange);
- canLunge.Adopt(strike);
- //canLunge.Adopt(getInLungeRange);
- //canLunge.Adopt(strike);
- actualLungeSeq.Adopt(canGetInRange);
- actualLungeSeq.Adopt(canLunge);
- actualLungeSeq.Adopt(getInLungeRange2);
- actualLungeSeq.Adopt(strike2);
- closeInSeq.Adopt(getInLungeRange3);
- closeInSeq.Adopt(passTurn);
- return root;
- }
- Rect _windowRect = new Rect(0, 0, 100, 100);
- void DrawColorPickerWindow(int windowID)
- {
- Debug.Log("in window");
- GUI.Box(new Rect(0,0,20, 20), "");
- /*GUI.DragWindow(new Rect(0, 0, 10000, 20));
- GUIStyle windowStyle = GUI.skin.window;
- GUI.BeginGroup(new Rect(windowStyle.padding.left, windowStyle.padding.top, _windowRect.width-windowStyle.padding.horizontal, _windowRect.height-windowStyle.padding.vertical));
- if (ColorPicker.DrawControls(new Vector2(10, 100)))
- {
- Repaint();
- }
- GUI.EndGroup();*/
- }
- void OnGUI()
- {
- _windowRect = GUI.Window(1, _windowRect, DrawColorPickerWindow, "Color Picker");
- wantsMouseMove = true;
- GUI.skin = GetSkin();
- GUI.SetNextControlName("Unfocuser");
- GUI.TextField(new Rect(10, -50, 100, 20), "");
- if (_currentBehaviourTree != null)
- {
- DrawBehaviourTreeControl(_currentBehaviourTree);
- }
- EditorGUILayout.BeginVertical();
- EditorGUILayout.BeginHorizontal();
- if (GUILayout.Button("New..."))
- {
- GUI.FocusControl("Unfocuser");
- //_currentBehaviourTree = new Root();
- _currentBehaviourTree = PopulateTestValues();
- _currentlyOpenBehaviourTree = "";
- }
- if (_currentBehaviourTree != null && GUILayout.Button("Save as..."))
- {
- string finalPath = "";
- string savepath = "";
- if (_lastAssetPath.Length > 0)
- {
- savepath = EditorUtility.SaveFilePanel("Save Behaviour Tree file", _lastAssetPath, "New Behaviour Tree", "txt");
- finalPath = savepath;
- }
- else
- {
- savepath = EditorUtility.SaveFilePanelInProject("Save Behaviour Tree file", "New Behaviour Tree", "txt", "");
- finalPath = Application.dataPath;
- finalPath = finalPath.Substring(0, finalPath.LastIndexOf('/')+1); // get rid of "Assets/"
- finalPath += savepath;
- }
- if (finalPath.Length > 0)
- {
- //Debug.Log("save to: " + finalPath);
- Root<IUnit>.SaveToLocal(finalPath, _currentBehaviourTree);
- _currentlyOpenBehaviourTree = finalPath;
- AssetDatabase.ImportAsset(savepath, ImportAssetOptions.ForceUpdate);
- }
- }
- EditorGUILayout.EndHorizontal();
- if (GUILayout.Button("Open: " + Path.GetFileName(_lastBehaviourTreeSelected)))
- {
- GUI.FocusControl("Unfocuser");
- _currentBehaviourTree = Root<IUnit>.LoadFromLocal(_lastBehaviourTreeSelected);
- if (_currentBehaviourTree != null)
- {
- _currentlyOpenBehaviourTree = _lastBehaviourTreeSelected;
- }
- else
- {
- Debug.LogError("Behaviour Tree Editor: Error loading: " + _lastBehaviourTreeSelected);
- }
- }
- if (_currentBehaviourTree != null && _currentlyOpenBehaviourTree == _lastBehaviourTreeSelected && GUILayout.Button("Save: " + Path.GetFileName(_lastBehaviourTreeSelected)))
- {
- Root<IUnit>.SaveToLocal(_lastBehaviourTreeSelected, _currentBehaviourTree);
- AssetDatabase.Refresh();
- //AssetDatabase.ImportAsset(_lastBehaviourTreeSelected, ImportAssetOptions.ForceUpdate);
- }
- EditorGUILayout.EndVertical();
- }
- Node<IUnit> _lastDraggedNode = null;
- public void DrawBehaviourTreeControl(Root<IUnit> tree)
- {
- Event e = Event.current;
- //if (e.control)
- //{
- // EditorGUIUtility.AddCursorRect(new Rect(0,0,Mathf.Infinity,Mathf.Infinity), MouseCursor.MoveArrow);
- // Repaint();
- //}
- //else
- //{
- // EditorGUIUtility.AddCursorRect(new Rect(0,0,Mathf.Infinity,Mathf.Infinity), MouseCursor.Arrow);
- // Repaint();
- //}
- if (e.isMouse && e.type == EventType.MouseDrag && (((e.button == 0 || e.button > 2) && e.control) || e.button == 1))
- {
- _panOffset += e.delta;
- Repaint();
- }
- if (e.isKey && e.keyCode == KeyCode.F12)
- {
- _panOffset = Vector2.zero;
- Repaint();
- }
- GUI.BeginGroup(new Rect(_panOffset.x, _panOffset.y, Mathf.Infinity, Mathf.Infinity));
- Vector2 rootPos = new Vector2(tree.GetSelfDrawSize(GUI.skin).x * 0.5f, 0);
- Node<IUnit>.DragOperation dragOperation = new Node<IUnit>.DragOperation();
- tree.Draw(rootPos, this, 0, 0, dragOperation);
- // draw dragged node in 50% transparent
- if (dragOperation.DraggingNode != null)
- {
- Vector2 m = e.mousePosition;
- Color old = GUI.color;
- Color transp = old;
- transp.a = 0.5f;
- GUI.color = transp;
- dragOperation.DraggingNode.Draw(m, this, 0, 0, null);
- _lastDraggedNode = dragOperation.DraggingNode;
- GUI.color = old;
- Repaint();
- }
- if (e.type == EventType.MouseUp &&
- _lastDraggedNode != null && // something dragged
- dragOperation.DroppedNode != null && // somewhere to drop
- dragOperation.DroppedNode.CanHaveChildren && // drop allowed
- (_lastDraggedNode != dragOperation.DroppedNode)) // not dropping to self
- {
- Debug.Log("\"" + _lastDraggedNode.Label + "\" dropped to \"" + dragOperation.DroppedNode.Label + "\" at " + dragOperation.DroppedPos);
- _lastDraggedNode.Detach();
- dragOperation.DroppedNode.UserAttachNode(_lastDraggedNode, dragOperation.DroppedPos);
- _lastDraggedNode = null;
- }
- GUI.EndGroup();
- }
- }
- #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement