123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using UnityEditor;
- using UnityEditor.SceneManagement;
- using UnityEngine;
- using UnityEngine.SceneManagement;
- using UnityObject = UnityEngine.Object;
-
- namespace Unity.VisualScripting
- {
- internal class DropdownOptions
- {
- internal bool interactable = true;
- internal string label;
- internal string tooltip;
- internal Action callback;
- }
-
- internal class SplitDropdown
- {
- private bool reset;
- private List<DropdownOptions> listOfOptions;
-
- internal SplitDropdown(List<DropdownOptions> listOfOptions)
- {
- this.listOfOptions = listOfOptions;
- }
-
- internal DropdownOptions GetOption(int index)
- {
- return listOfOptions[index];
- }
-
- internal void Reset()
- {
- reset = true;
- }
-
- internal bool Draw(Rect area, string label, ref bool toggleState)
- {
- GUI.Box(area, string.Empty, EmptyGraphWindow.buttonStyle);
-
- if (GUI.Button(new Rect(area.x, area.y, area.width - area.height, area.height), label,
- EmptyGraphWindow.labelStyleButton))
- {
- toggleState = false;
-
- return true;
- }
-
- Rect toggleRect = new Rect(area.x + area.width - area.height - 2, area.y - 1, area.height + 3,
- area.height + 3);
-
- toggleState = GUI.Toggle(toggleRect, toggleState, "", EmptyGraphWindow.labelStyleButton);
-
- GUI.Label(toggleRect, EmptyGraphWindow.dropdownIcon, EmptyGraphWindow.titleStyle);
-
- if (toggleState)
- {
- GUI.BeginGroup(new Rect(area.x, area.y + area.height - 1, area.width, area.height * 2),
- EmptyGraphWindow.buttonStyle);
- Rect areaChild = new Rect(0, 0, EmptyGraphWindow.buttonWidth,
- EmptyGraphWindow.buttonHeight);
-
- GUIContent contentOption;
-
- foreach (DropdownOptions dropdownOption in listOfOptions)
- {
- EditorGUI.BeginDisabledGroup(!dropdownOption.interactable);
-
- if (dropdownOption.interactable)
- {
- contentOption = new GUIContent(dropdownOption.label);
- }
- else
- {
- contentOption = new GUIContent(dropdownOption.label, dropdownOption.tooltip);
- }
-
- if (GUI.Button(areaChild, contentOption, EmptyGraphWindow.labelStyleDropdownOptions))
- {
- toggleState = false;
-
- dropdownOption.callback();
- }
-
- EditorGUI.EndDisabledGroup();
-
- areaChild.y += areaChild.height;
- }
-
- GUI.EndGroup();
- }
-
- if (reset)
- {
- toggleState = false;
- reset = false;
- }
-
- return false;
- }
- }
-
- internal class EmptyGraphWindow : EditorWindow
- {
- internal static GUIContent dropdownIcon;
-
- private bool toggleOnScript = false;
- private bool toggleOnState = false;
-
- internal static GUIStyle buttonStyle;
- internal static GUIStyle labelStyleButton;
- internal static GUIStyle labelStyleDropdownOptions;
- internal static GUIStyle titleStyle;
-
- internal static int titleHeight = 120;
- internal static int buttonWidth = 200;
- internal static int buttonHeight = 22;
-
- private bool shouldCloseWindow;
- private Vector2 scrollPosition;
- private Rect scrollArea;
-
- private SplitDropdown splitDropdownScriptGraph;
- private SplitDropdown splitDropdownStateGraph;
-
- const string k_OnSelectedGameObject = "...on selected GameObject";
- const string k_OnNewGameObject = "...on new GameObject";
- const string k_SelectedGameObject = "Please, select a GameObject";
-
- [MenuItem("Window/Visual Scripting/Visual Scripting Graph", false, 3010)]
- private static void ShowWindow()
- {
- EmptyGraphWindow window = GetWindow<EmptyGraphWindow>();
-
- window.titleContent = new GUIContent("Visual Scripting");
- }
-
- private void OnEnable()
- {
- string pathRoot = PathUtility.GetPackageRootPath();
-
- UnityObject icon = EditorGUIUtility.Load(Path.Combine(pathRoot,
- "Editor/VisualScripting.Shared/EditorAssetResources/SplitButtonArrow.png"));
-
- dropdownIcon = new GUIContent(icon as Texture2D);
-
- scrollArea = new Rect(0, 0, 630, 300);
-
- toggleOnScript = false;
- toggleOnState = false;
- shouldCloseWindow = false;
-
- var listOfOptions = new List<DropdownOptions>
- {
- new DropdownOptions
- {
- label = k_OnSelectedGameObject,
- tooltip = k_SelectedGameObject,
- callback = CreateScriptGraphOnSelectedGameObject
- },
- new DropdownOptions
- {
- label = k_OnNewGameObject,
- callback = CreateScriptGraphOnNewGameObject
- }
- };
-
- splitDropdownScriptGraph = new SplitDropdown(listOfOptions);
-
- listOfOptions = new List<DropdownOptions>
- {
- new DropdownOptions
- {
- label = k_OnSelectedGameObject,
- tooltip = k_SelectedGameObject,
- callback = CreateStateGraphOnSelectedGameObject
- },
- new DropdownOptions
- {
- label = k_OnNewGameObject,
- callback = CreateStateGraphOnNewGameObject
- }
- };
-
- splitDropdownStateGraph = new SplitDropdown(listOfOptions);
- }
-
- private void OpenGraphAsset(UnityObject unityObject, bool shouldSetSceneAsDirty)
- {
- shouldCloseWindow = true;
-
- ScriptGraphAsset scriptGraphAsset = unityObject as ScriptGraphAsset;
-
- GraphReference graphReference = null;
-
- if (scriptGraphAsset != null)
- {
- graphReference = GraphReference.New(scriptGraphAsset, true);
- }
- else
- {
- StateGraphAsset stateGraphAsset = unityObject as StateGraphAsset;
-
- if (stateGraphAsset != null)
- {
- graphReference = GraphReference.New(stateGraphAsset, true);
- }
- }
-
- if (shouldSetSceneAsDirty)
- {
- EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
- }
-
- GraphWindow.OpenActive(graphReference);
- }
-
- private void OpenGraphFromPath(string path, bool shouldSetSceneAsDirty)
- {
- path = path.Replace(Application.dataPath, "Assets");
-
- UnityObject unityObject = AssetDatabase.LoadAssetAtPath(path, typeof(UnityObject));
-
- OpenGraphAsset(unityObject, shouldSetSceneAsDirty);
- }
-
- private void OpenGraph()
- {
- EditorGUIUtility.ShowObjectPicker<MacroScriptableObject>(null, false, String.Empty,
- EditorGUIUtility.GetControlID(FocusType.Passive));
- }
-
- private bool CreateScriptGraphAsset(GameObject gameObject = null, bool updateName = false)
- {
- var path = EditorUtility.SaveFilePanelInProject("Save Graph", "New Script Graph", "asset", null);
-
- if (string.IsNullOrEmpty(path))
- {
- return false;
- }
-
- VSUsageUtility.isVisualScriptingUsed = true;
-
- var macro = (IMacro)CreateInstance(typeof(ScriptGraphAsset));
- var macroObject = (UnityObject)macro;
- macro.graph = FlowGraph.WithStartUpdate();
-
- if (gameObject != null)
- {
- ScriptMachine flowMachine = gameObject.AddComponent<ScriptMachine>();
-
- flowMachine.nest.macro = (ScriptGraphAsset)macro;
- }
-
- string filename = Path.GetFileNameWithoutExtension(path);
-
- if (updateName)
- {
- gameObject.name = filename;
- }
-
- macroObject.name = filename;
-
- AssetDatabase.CreateAsset(macroObject, path);
-
- bool shouldSetSceneAsDirty = gameObject != null;
-
- OpenGraphFromPath(path, shouldSetSceneAsDirty);
-
- return true;
- }
-
- private void CreateScriptGraph()
- {
- Selection.activeGameObject = null;
-
- if (CreateScriptGraphAsset())
- {
- shouldCloseWindow = true;
- }
- }
-
- private void CreateScriptGraphOnNewGameObject()
- {
- Selection.activeGameObject = null;
-
- GameObject newGameObject = new GameObject();
-
- if (!CreateScriptGraphAsset(newGameObject, true))
- {
- DestroyImmediate(newGameObject);
- }
- }
-
- private void CreateScriptGraphOnSelectedGameObject()
- {
- if (Selection.activeGameObject != null)
- {
- if (CreateScriptGraphAsset(Selection.activeGameObject))
- {
- shouldCloseWindow = true;
- }
- }
- }
-
- private bool CreateStateGraphAsset(GameObject gameObject = null, bool updateName = false)
- {
- var path = EditorUtility.SaveFilePanelInProject("Save Graph", "New State Graph", "asset", null);
-
- if (string.IsNullOrEmpty(path))
- {
- return false;
- }
-
- VSUsageUtility.isVisualScriptingUsed = true;
-
- var macro = (IMacro)CreateInstance(typeof(StateGraphAsset));
- var macroObject = (UnityObject)macro;
- macro.graph = StateGraph.WithStart();
-
- if (gameObject != null)
- {
- StateMachine stateMachine = gameObject.AddComponent<StateMachine>();
-
- stateMachine.nest.macro = (StateGraphAsset)macro;
- }
-
- string filename = Path.GetFileNameWithoutExtension(path);
-
- if (updateName)
- {
- gameObject.name = filename;
- }
-
- macroObject.name = filename;
-
- AssetDatabase.CreateAsset(macroObject, path);
-
- bool shouldSetSceneAsDirty = gameObject != null;
-
- OpenGraphFromPath(path, shouldSetSceneAsDirty);
-
- return true;
- }
-
- private void CreateStateGraph()
- {
- Selection.activeGameObject = null;
-
- if (CreateStateGraphAsset())
- {
- shouldCloseWindow = true;
- }
- }
-
- private void CreateStateGraphOnNewGameObject()
- {
- Selection.activeGameObject = null;
-
- GameObject newGameObject = new GameObject();
-
- if (!CreateStateGraphAsset(newGameObject, true))
- {
- DestroyImmediate(newGameObject);
- }
- }
-
- private void CreateStateGraphOnSelectedGameObject()
- {
- if (Selection.activeGameObject != null)
- {
- if (CreateStateGraphAsset(Selection.activeGameObject))
- {
- shouldCloseWindow = true;
- }
- }
- }
-
- private void CreateStyles()
- {
- if (buttonStyle == null)
- {
- buttonStyle = new GUIStyle("Button");
- }
-
- if (labelStyleButton == null)
- {
- labelStyleButton = new GUIStyle("Label") { alignment = TextAnchor.MiddleCenter };
- }
-
- if (labelStyleDropdownOptions == null)
- {
- labelStyleDropdownOptions = new GUIStyle("ToolbarButton")
- {
- alignment = TextAnchor.MiddleLeft,
- padding = new RectOffset(20, 0, 0, 0)
- };
- }
-
- if (titleStyle == null)
- {
- titleStyle = new GUIStyle("Label") { alignment = TextAnchor.MiddleCenter, fontSize = 20 };
- }
- }
-
- private void ResetToggle()
- {
- if (Event.current.rawType == EventType.MouseUp)
- {
- if (toggleOnScript)
- {
- splitDropdownScriptGraph.Reset();
-
- Repaint();
- }
-
- if (toggleOnState)
- {
- splitDropdownStateGraph.Reset();
-
- Repaint();
- }
- }
- }
-
- private void OpenGraphFromPicker()
- {
- if (Event.current.commandName == "ObjectSelectorUpdated")
- {
- UnityObject selectedObject = EditorGUIUtility.GetObjectPickerObject();
-
- OpenGraphAsset(selectedObject, false);
- }
- }
-
- private void OnGUI()
- {
- CreateStyles();
-
- ResetToggle();
-
- DropAreaGUI();
-
- OpenGraphFromPicker();
-
- scrollPosition = GUI.BeginScrollView(new Rect(0, 0, position.width, position.height), scrollPosition,
- scrollArea);
- GUILayout.BeginVertical(GUILayout.ExpandHeight(true));
-
- Vector2 groupSize = new Vector2(scrollArea.width, 280);
-
- GUI.BeginGroup(new Rect((position.width / 2) - (groupSize.x / 2), (position.height / 2) - (groupSize.y / 2),
- groupSize.x, groupSize.y));
-
- GUI.Label(new Rect(0, 0, groupSize.x, titleHeight), "Drag and drop a Visual Scripting Graph asset here\nor",
- titleStyle);
-
- int buttonX = 10;
-
- if (GUI.Button(new Rect(buttonX, titleHeight, buttonWidth, buttonHeight), "Browse to open a Graph"))
- {
- OpenGraph();
- }
-
- buttonX += (buttonWidth + 10);
-
- Rect area = new Rect(buttonX, titleHeight, buttonWidth, buttonHeight);
-
- splitDropdownScriptGraph.GetOption(0).interactable = Selection.activeGameObject != null;
-
- if (splitDropdownScriptGraph.Draw(area, "Create new Script Graph", ref toggleOnScript))
- {
- CreateScriptGraph();
- }
-
- if (toggleOnScript)
- {
- toggleOnState = false;
- }
-
- buttonX += (buttonWidth + 10);
-
- area = new Rect(buttonX, titleHeight, buttonWidth, buttonHeight);
-
- splitDropdownStateGraph.GetOption(0).interactable = Selection.activeGameObject != null;
-
- if (splitDropdownStateGraph.Draw(area, "Create new State Graph", ref toggleOnState))
- {
- CreateStateGraph();
- }
-
- if (toggleOnState)
- {
- toggleOnScript = false;
- }
-
- GUI.EndGroup();
- GUILayout.EndVertical();
- GUI.EndScrollView();
-
- if (shouldCloseWindow)
- {
- Close();
- }
- }
-
- private void DropAreaGUI()
- {
- Event currentEvent = Event.current;
-
- Rect activeArea = GUILayoutUtility.GetRect(0, 0, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
-
- switch (currentEvent.type)
- {
- case EventType.DragUpdated:
- case EventType.DragPerform:
- if (!activeArea.Contains(currentEvent.mousePosition))
- {
- return;
- }
-
- DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
-
- if (currentEvent.type == EventType.DragPerform)
- {
- DragAndDrop.AcceptDrag();
-
- foreach (UnityObject draggedObject in DragAndDrop.objectReferences)
- {
- ScriptGraphAsset scriptGraphAsset = draggedObject as ScriptGraphAsset;
-
- if (scriptGraphAsset != null)
- {
- shouldCloseWindow = true;
-
- GraphWindow.OpenActive(GraphReference.New(scriptGraphAsset, true));
- break;
- }
- }
- }
-
- break;
- }
- }
- }
- }
|