123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- using System;
- using System.Linq;
- using System.Collections.Generic;
- using UnityEngine;
- using UnityEditor;
- using UnityEditor.EditorTools;
- using UnityEditor.U2D.Path.GUIFramework;
- using UnityObject = UnityEngine.Object;
-
- namespace UnityEditor.U2D.Path
- {
- public static class PathEditorToolContents
- {
- internal static readonly GUIContent shapeToolIcon = IconContent("ShapeTool", "Start editing the Shape in the Scene View.");
- internal static readonly GUIContent shapeToolPro = IconContent("ShapeToolPro", "Start editing the Shape in the Scene View.");
-
- internal static GUIContent IconContent(string name, string tooltip = null)
- {
- return new GUIContent(AssetDatabase.LoadAssetAtPath<Texture2D>("Packages/com.unity.2d.path/Editor/Handles/" + name + ".png"), tooltip);
- }
-
- public static GUIContent icon
- {
- get
- {
- if (EditorGUIUtility.isProSkin)
- return shapeToolPro;
-
- return shapeToolIcon;
- }
- }
- }
-
- internal interface IDuringSceneGuiTool
- {
- void DuringSceneGui(SceneView sceneView);
- bool IsAvailable();
- }
-
- [InitializeOnLoad]
- internal class EditorToolManager
- {
- private static List<IDuringSceneGuiTool> m_Tools = new List<IDuringSceneGuiTool>();
-
- static EditorToolManager()
- {
- SceneView.duringSceneGui += DuringSceneGui;
- }
-
- internal static void Add(IDuringSceneGuiTool tool)
- {
- if (!m_Tools.Contains(tool) && tool is EditorTool)
- m_Tools.Add(tool);
- }
-
- internal static void Remove(IDuringSceneGuiTool tool)
- {
- if (m_Tools.Contains(tool))
- m_Tools.Remove(tool);
- }
-
- internal static bool IsActiveTool<T>() where T : EditorTool
- {
- return ToolManager.activeToolType.Equals(typeof(T));
- }
-
- internal static bool IsAvailable<T>() where T : EditorTool
- {
- var tool = GetEditorTool<T>();
-
- if (tool != null)
- return tool.IsAvailable();
-
- return false;
- }
-
- internal static T GetEditorTool<T>() where T : EditorTool
- {
- foreach(var tool in m_Tools)
- {
- if (tool.GetType().Equals(typeof(T)))
- return tool as T;
- }
-
- return null;
- }
-
- private static void DuringSceneGui(SceneView sceneView)
- {
- foreach (var tool in m_Tools)
- {
- if (tool.IsAvailable() && ToolManager.IsActiveTool(tool as EditorTool))
- tool.DuringSceneGui(sceneView);
- }
- }
- }
-
- public abstract class PathEditorTool<T> : EditorTool, IDuringSceneGuiTool where T : ScriptablePath
- {
- private Dictionary<UnityObject, T> m_Paths = new Dictionary<UnityObject, T>();
- private IGUIState m_GUIState = new GUIState();
- private Dictionary<UnityObject, PathEditor> m_PathEditors = new Dictionary<UnityObject, PathEditor>();
- private Dictionary<UnityObject, SerializedObject> m_SerializedObjects = new Dictionary<UnityObject, SerializedObject>();
- private MultipleEditablePathController m_Controller = new MultipleEditablePathController();
- private PointRectSelector m_RectSelector = new PointRectSelector();
- private bool m_IsActive = false;
-
- internal T[] paths
- {
- get { return m_Paths.Values.ToArray(); }
- }
-
- public bool enableSnapping
- {
- get { return m_Controller.enableSnapping; }
- set { m_Controller.enableSnapping = value; }
- }
-
- public override GUIContent toolbarIcon
- {
- get { return PathEditorToolContents.icon; }
- }
-
- public override bool IsAvailable()
- {
- return targets.Count() > 0;
- }
-
- public T GetPath(UnityObject targetObject)
- {
- var path = default(T);
- m_Paths.TryGetValue(targetObject, out path);
- return path;
- }
-
- public void SetPath(UnityObject target)
- {
- var path = GetPath(target);
- path.localToWorldMatrix = Matrix4x4.identity;
-
- var undoName = Undo.GetCurrentGroupName();
- var serializedObject = GetSerializedObject(target);
-
- serializedObject.UpdateIfRequiredOrScript();
-
- SetShape(path, serializedObject);
-
- Undo.SetCurrentGroupName(undoName);
- }
-
- private void RepaintInspectors()
- {
- var editorWindows = Resources.FindObjectsOfTypeAll<EditorWindow>();
-
- foreach (var editorWindow in editorWindows)
- {
- if (editorWindow.titleContent.text == "Inspector")
- editorWindow.Repaint();
- }
- }
-
- private void OnEnable()
- {
- m_IsActive = false;
- EditorToolManager.Add(this);
-
- SetupRectSelector();
- HandleActivation();
-
- ToolManager.activeToolChanged += HandleActivation;
- }
-
- private void OnDestroy()
- {
- EditorToolManager.Remove(this);
-
- ToolManager.activeToolChanged -= HandleActivation;
- UnregisterCallbacks();
- }
-
- private void HandleActivation()
- {
- if (m_IsActive == false && ToolManager.IsActiveTool(this))
- Activate();
- else if (m_IsActive)
- Deactivate();
- }
-
- private void Activate()
- {
- m_IsActive = true;
- RegisterCallbacks();
- InitializeCache();
- OnActivate();
- }
-
- private void Deactivate()
- {
- OnDeactivate();
- DestroyCache();
- UnregisterCallbacks();
- m_IsActive = false;
- }
-
- private void RegisterCallbacks()
- {
- UnregisterCallbacks();
- Selection.selectionChanged += SelectionChanged;
- EditorApplication.playModeStateChanged += PlayModeStateChanged;
- Undo.undoRedoPerformed += UndoRedoPerformed;
- }
-
- private void UnregisterCallbacks()
- {
- Selection.selectionChanged -= SelectionChanged;
- EditorApplication.playModeStateChanged -= PlayModeStateChanged;
- Undo.undoRedoPerformed -= UndoRedoPerformed;
- }
-
- private void DestroyCache()
- {
- foreach (var pair in m_Paths)
- {
- var path = pair.Value;
-
- if (path != null)
- {
- Undo.ClearUndo(path);
- UnityObject.DestroyImmediate(path);
- }
- }
- m_Paths.Clear();
- m_Controller.ClearPaths();
- m_PathEditors.Clear();
- m_SerializedObjects.Clear();
- }
-
- private void UndoRedoPerformed()
- {
- ForEachTarget((target) =>
- {
- var path = GetPath(target);
-
- if (!path.modified)
- InitializePath(target);
- });
- }
-
- private void SelectionChanged()
- {
- InitializeCache();
- }
-
- private void PlayModeStateChanged(PlayModeStateChange stateChange)
- {
- if (stateChange == PlayModeStateChange.EnteredEditMode)
- EditorApplication.delayCall += () => { InitializeCache(); }; //HACK: At this point target is null. Let's wait to next frame to refresh.
- }
-
- private void SetupRectSelector()
- {
- m_RectSelector.onSelectionBegin = BeginSelection;
- m_RectSelector.onSelectionChanged = UpdateSelection;
- m_RectSelector.onSelectionEnd = EndSelection;
- }
-
- private void ForEachTarget(Action<UnityObject> action)
- {
- foreach(var target in targets)
- {
- if (target == null)
- continue;
-
- action(target);
- }
- }
-
- private void InitializeCache()
- {
- m_Controller.ClearPaths();
-
- ForEachTarget((target) =>
- {
- var path = GetOrCreatePath(target);
- var pointCount = path.pointCount;
-
- InitializePath(target);
-
- if (pointCount != path.pointCount)
- path.selection.Clear();
-
- CreatePathEditor(target);
-
- m_Controller.AddPath(path);
- });
- }
-
- private void InitializePath(UnityObject target)
- {
- IShape shape = null;
- ControlPoint[] controlPoints = null;
-
- try
- {
- shape = GetShape(target);
- controlPoints = shape.ToControlPoints();
- }
- catch (Exception e)
- {
- Debug.LogError(e.Message);
- }
-
- var path = GetPath(target);
- path.Clear();
-
- if (shape != null && controlPoints != null)
- {
- path.localToWorldMatrix = Matrix4x4.identity;
- path.shapeType = shape.type;
- path.isOpenEnded = shape.isOpenEnded;
-
- foreach (var controlPoint in controlPoints)
- path.AddPoint(controlPoint);
- }
-
- Initialize(path, GetSerializedObject(target));
- }
-
- private T GetOrCreatePath(UnityObject targetObject)
- {
- var path = GetPath(targetObject);
-
- if (path == null)
- {
- path = ScriptableObject.CreateInstance<T>();
- path.hideFlags = HideFlags.HideAndDontSave;
- path.owner = targetObject;
- m_Paths[targetObject] = path;
- }
-
- return path;
- }
-
- private PathEditor GetPathEditor(UnityObject target)
- {
- PathEditor pathEditor;
- m_PathEditors.TryGetValue(target, out pathEditor);
- return pathEditor;
- }
-
- private void CreatePathEditor(UnityObject target)
- {
- var pathEditor = new PathEditor();
- pathEditor.controller = m_Controller;
- pathEditor.drawerOverride = GetCustomDrawer(target);
- m_PathEditors[target] = pathEditor;
- }
-
- private SerializedObject GetSerializedObject(UnityObject target)
- {
- var serializedObject = default(SerializedObject);
-
- if (!m_SerializedObjects.TryGetValue(target, out serializedObject))
- {
- serializedObject = new SerializedObject(target);
- m_SerializedObjects[target] = serializedObject;
- }
-
- return serializedObject;
- }
-
- void IDuringSceneGuiTool.DuringSceneGui(SceneView sceneView)
- {
- if (m_GUIState.eventType == EventType.Layout)
- m_Controller.ClearClosestPath();
-
- m_RectSelector.OnGUI();
-
- bool changed = false;
-
- ForEachTarget((target) =>
- {
- var path = GetPath(target);
-
- if (path != null)
- {
- path.localToWorldMatrix = GetLocalToWorldMatrix(target);
- path.forward = GetForward(target);
- path.up = GetUp(target);
- path.right = GetRight(target);
- m_Controller.editablePath = path;
-
- using (var check = new EditorGUI.ChangeCheckScope())
- {
- var pathEditor = GetPathEditor(target);
- pathEditor.linearTangentIsZero = GetLinearTangentIsZero(target);
- pathEditor.OnGUI();
- OnCustomGUI(path);
- changed |= check.changed;
- }
- }
- });
-
- if (changed)
- {
- SetShapes();
- RepaintInspectors();
- }
- }
-
- private void BeginSelection(ISelector<Vector3> selector, bool isAdditive)
- {
- m_Controller.RegisterUndo("Selection");
-
- if (isAdditive)
- {
- ForEachTarget((target) =>
- {
- var path = GetPath(target);
- path.selection.BeginSelection();
- });
- }
- else
- {
- UpdateSelection(selector);
- }
- }
-
- private void UpdateSelection(ISelector<Vector3> selector)
- {
- var repaintInspectors = false;
-
- ForEachTarget((target) =>
- {
- var path = GetPath(target);
-
- repaintInspectors |= path.Select(selector);
- });
-
- if (repaintInspectors)
- RepaintInspectors();
- }
-
- private void EndSelection(ISelector<Vector3> selector)
- {
- ForEachTarget((target) =>
- {
- var path = GetPath(target);
- path.selection.EndSelection(true);
- });
- }
-
- internal void SetShapes()
- {
- ForEachTarget((target) =>
- {
- SetPath(target);
- });
- }
-
- private Transform GetTransform(UnityObject target)
- {
- return (target as Component).transform;
- }
-
- private Matrix4x4 GetLocalToWorldMatrix(UnityObject target)
- {
- return GetTransform(target).localToWorldMatrix;
- }
-
- private Vector3 GetForward(UnityObject target)
- {
- return GetTransform(target).forward;
- }
-
- private Vector3 GetUp(UnityObject target)
- {
- return GetTransform(target).up;
- }
-
- private Vector3 GetRight(UnityObject target)
- {
- return GetTransform(target).right;
- }
-
- protected abstract IShape GetShape(UnityObject target);
- protected virtual void Initialize(T path, SerializedObject serializedObject) { }
- protected abstract void SetShape(T path, SerializedObject serializedObject);
- protected virtual void OnActivate() { }
- protected virtual void OnDeactivate() { }
- protected virtual void OnCustomGUI(T path) { }
- protected virtual bool GetLinearTangentIsZero(UnityObject target) { return false; }
- protected virtual IDrawer GetCustomDrawer(UnityObject target) { return null; }
- }
- }
|