From 8a52585a726e0f7c9b9bea4aa1a4379a66a35a6a Mon Sep 17 00:00:00 2001 From: Child of the Beast Date: Tue, 2 Mar 2021 00:05:01 -0500 Subject: [PATCH] fixed namespace issues made namespace names more consistent --- Tools/ACMerge/Editor/MergeAC.cs | 542 ++++++++++++++++++ Tools/EasyDoors/PlayerInteractTeleport.cs | 2 +- .../EasyLocks/Debug/Debug_EasyLocks_Button.cs | 2 +- .../Debug/Debug_EasyLocks_Password.cs | 2 +- Tools/Editor/SortChild.cs | 93 +++ Tools/Utility/EditorHelper.cs | 283 +++++++++ Tools/Utility/PlayerTransforms.cs | 276 +++++++++ 7 files changed, 1197 insertions(+), 3 deletions(-) create mode 100644 Tools/ACMerge/Editor/MergeAC.cs create mode 100644 Tools/Editor/SortChild.cs create mode 100644 Tools/Utility/EditorHelper.cs create mode 100644 Tools/Utility/PlayerTransforms.cs diff --git a/Tools/ACMerge/Editor/MergeAC.cs b/Tools/ACMerge/Editor/MergeAC.cs new file mode 100644 index 0000000..3b8e4ff --- /dev/null +++ b/Tools/ACMerge/Editor/MergeAC.cs @@ -0,0 +1,542 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditor.Animations; +using UnityEngine; + +namespace UdonVR.Tools +{ + //using System; + public class MergeAC : EditorWindow + { + public AnimatorController baseController; + public AnimatorController addController; + public bool saveAsNewController = true; + + public string newPath = " "; + private GUILayoutOption[] space = new GUILayoutOption[] { GUILayout.Height(16), GUILayout.MinHeight(16), GUILayout.MaxHeight(16) }; + private GUILayoutOption[] noExpandWidth = new GUILayoutOption[] { GUILayout.Height(16), GUILayout.MinHeight(16), GUILayout.MaxHeight(16), GUILayout.ExpandWidth(false) }; + private GUIStyle style; + public GUIStyle logoStyle; + private bool[] canAddLayer; + private string[] layerNames; + private bool ChangeCheck; + private bool showLayer = true; + private string currLayer; + private int currLayerNum; + private int canLayerNum; + private AnimatorController tempAddController; + public AnimatorController tempController; + + private bool disableMerge; + private string warning = "None"; + private Vector2 scrollPos; + + [MenuItem("UdonVR/Merge Controllers")] + public static void ShowWindow() + { + MergeAC window = GetWindow("Merge Controllers"); + window.minSize = new Vector2(385, 250); + } + + private void GUIWarning(string text) + { + EditorGUILayout.LabelField(new GUIContent(text, EditorGUIUtility.FindTexture("d_console.warnicon")), style); + } + + private void GUIError(string text) + { + disableMerge = true; + EditorGUILayout.LabelField(new GUIContent(text, EditorGUIUtility.FindTexture("d_console.erroricon")), style); + } + + private void InitGuiStyles() + { + style = new GUIStyle(EditorStyles.helpBox); + style.richText = true; + style.fontSize = 15; + + logoStyle = new GUIStyle("flow node hex 0") + { + fontSize = 15, + richText = true, + alignment = TextAnchor.MiddleCenter, + hover = ((GUIStyle)"flow node hex 1").normal, + active = ((GUIStyle)"flow node hex 1 on").normal + }; + + logoStyle.padding.top = 17; + logoStyle.normal.textColor = Color.cyan; + } + + private void OnGUI() + { + if (style == null) + InitGuiStyles(); + + EditorGUI.BeginChangeCheck(); + baseController = EditorGUILayout.ObjectField("BaseController", baseController, typeof(AnimatorController), false) as AnimatorController; + bool ChangeBaseCheck = EditorGUI.EndChangeCheck(); + if (baseController != null) + { + EditorGUI.BeginChangeCheck(); + addController = EditorGUILayout.ObjectField("AddController", addController, typeof(AnimatorController), false) as AnimatorController; + ChangeCheck = EditorGUI.EndChangeCheck(); + } + else + { + EditorGUILayout.BeginVertical(space); + EditorGUILayout.Space(); + EditorGUILayout.EndVertical(); + } + if (addController != null) + { + if (canAddLayer == null || ChangeCheck) + { + canAddLayer = Enumerable.Repeat(true, addController.layers.Length).ToArray(); + layerNames = new string[addController.layers.Length]; + } + + EditorGUILayout.BeginHorizontal(); + Rect foldRect = EditorGUILayout.GetControlRect(true); + if (GUILayout.Button("All", noExpandWidth)) + { + canAddLayer = Enumerable.Repeat(true, addController.layers.Length).ToArray(); + } + if (GUILayout.Button("None", noExpandWidth)) + { + canAddLayer = Enumerable.Repeat(false, addController.layers.Length).ToArray(); + } + EditorGUILayout.EndHorizontal(); + showLayer = EditorGUI.Foldout(foldRect, showLayer, "Layers", true); + if (showLayer) + { + scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUILayout.ExpandHeight(false)); + for (int i = 0; i < addController.layers.Length; i++) + { + string addLayerName = addController.layers[i].name; + + if (layerNames[i] == null) + { + layerNames[i] = baseController.MakeUniqueLayerName(addLayerName); + } + EditorGUILayout.BeginHorizontal(); + + canAddLayer[i] = EditorGUILayout.ToggleLeft(addLayerName, canAddLayer[i], noExpandWidth); + + layerNames[i] = EditorGUILayout.TextField(layerNames[i]); + + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.EndScrollView(); + } + } + else + { + canAddLayer = null; + } + EditorGUI.BeginDisabledGroup(baseController == null); + Rect rect = EditorGUILayout.BeginHorizontal(); + EditorGUI.BeginChangeCheck(); + saveAsNewController = EditorGUILayout.Toggle("Save As New Controller", saveAsNewController, noExpandWidth); + if (saveAsNewController) + { + newPath = EditorGUILayout.TextField(newPath); + + if (GUILayout.Button(EditorGUIUtility.IconContent("Folder Icon"), noExpandWidth)) + { + string tempNewPath = UnityEditor.EditorUtility.SaveFilePanelInProject("Save New BaseController", "New" + baseController.name + ".controller", "controller", "Please enter a file name to save the New Controller to", Path.GetDirectoryName(AssetDatabase.GetAssetPath(baseController))); + if (tempNewPath != "") + newPath = tempNewPath; + } + } + bool pathChangeCheck = EditorGUI.EndChangeCheck(); + if (ChangeBaseCheck || baseController != null && newPath.Trim() == "" && !EditorGUIUtility.editingTextField) + { + //Debug.Log("makePath!"); + newPath = AssetDatabase.GenerateUniqueAssetPath(Path.GetDirectoryName(AssetDatabase.GetAssetPath(baseController)) + "/New " + baseController.name + ".controller"); + pathChangeCheck = true; + } + if (pathChangeCheck) + { + if (!saveAsNewController) + { + disableMerge = false; + warning = "SaveToBase"; + } + else + { + if (newPath.StartsWith("Assets/", true, null)) + { + if (newPath.EndsWith(".controller", true, null)) + { + string mvcheck = AssetDatabase.ValidateMoveAsset(AssetDatabase.GetAssetPath(baseController), newPath); + if (mvcheck == "") + { + disableMerge = false; + warning = "None"; + } + else if (mvcheck.EndsWith("Destination path name does already exist")) + { + disableMerge = false; + warning = "Overwrite"; + } + else if (mvcheck.StartsWith("Trying to move asset as a sub directory of a directory that does not exist")) + { + disableMerge = true; + warning = "NoFolder"; + } + else if (mvcheck.StartsWith("Trying to move asset to location it came from")) + { + warning = "SaveOverBase"; + disableMerge = true; + } + } + else + { + disableMerge = true; + warning = "Extension"; + } + } + else + { + disableMerge = true; + warning = "AssetsFolder"; + } + } + } + EditorGUILayout.EndHorizontal(); + EditorGUI.EndDisabledGroup(); + + EditorGUI.BeginDisabledGroup(disableMerge || baseController == null || addController == null); + if (GUILayout.Button("Merge!")) + { + Merge(); + } + EditorGUI.EndDisabledGroup(); + if (baseController == null) + EditorGUILayout.LabelField("Insert a Base AnimatorController to add to.", style); + else if (addController == null) + EditorGUILayout.LabelField("Now add an AnimatorController to put on the Base", style); + else + EditorGUILayout.LabelField("Select Layers you want and click Merge!", style); + + switch (warning) + { + case "AssetsFolder": + GUIError("Can not Save Controller outside of Assets Folder!"); + break; + + case "Extension": + GUIError("Save file extension is not \".controller\"!"); + break; + + case "NoFolder": + GUIError("Can not save to this location, Folder does not exist!"); + break; + + case "Overwrite": + GUIWarning("Overwrite Warning! This will delete the controller at this location and save a new controller at the same location. This will unlink the controller from every thing!"); + break; + + case "SaveOverBase": + GUIError("Overwrite Error! You can not Save a new controller over the Base Controller, Uncheck Save As New Controller if you want to save to the Base Controller."); + break; + + case "SaveToBase": + GUIWarning("This will save to the Base Controller."); + break; + + case "None": + + break; + + default: + GUIError("Unknown Error"); + break; + } + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.Space(); + if (GUILayout.Button("UdonVR\nVRCUdon.com", logoStyle, GUILayout.ExpandWidth(false))) + { + Application.OpenURL("https://VRCUdon.com"); + } + EditorGUILayout.Space(); + EditorGUILayout.EndHorizontal(); + } + + private void OnInspectorUpdate() + { + Repaint(); + } + + private void Merge() + { + try + { + DoMerge(); + } + finally + { + } + } + + public void DoMerge() + { + string path = AssetDatabase.GetAssetPath(baseController); + string pathAdd = AssetDatabase.GetAssetPath(addController); + string tempPath = "Assets/TempController.controller"; + string tempPathAdd = "Assets/TempAddController.controller"; + + canLayerNum = canAddLayer.Count(b => b == true); + + if (saveAsNewController) + AssetDatabase.CopyAsset(path, tempPath); + AssetDatabase.CopyAsset(pathAdd, tempPathAdd); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + + if (saveAsNewController) + tempController = AssetDatabase.LoadAssetAtPath(tempPath); + else + tempController = baseController; + + tempAddController = AssetDatabase.LoadAssetAtPath(tempPathAdd); + if (tempController == null) + { + Debug.LogError("TempController not found!"); + return; + } + + Debug.Log("Merging Controllers"); + AnimatorControllerParameter[] baseParameters = baseController.parameters; + AnimatorControllerParameter[] addParameters = tempAddController.parameters; + ParameterComparer parameterComparer = new ParameterComparer(); + if (addParameters.Length > 0) + { + //Debug.Log("Merging Stage: Parameters"); + + for (int iPar = 0; iPar < addParameters.Length; iPar++) + { + AnimatorControllerParameter addPar = addParameters[iPar]; + if (!baseParameters.Contains(addPar, parameterComparer)) + { + tempController.AddParameter(addPar); + } + } + } + + AnimatorControllerLayer[] addLayers = tempAddController.layers; + if (addLayers.Length > 0) + { + //Debug.Log("Merging Stage: Layers"); + currLayerNum = 0; + + List baseLayers = baseController.layers.ToList(); + for (int i = 0; i < addLayers.Length; i++) + { + if (canAddLayer[i]) + { + currLayer = layerNames[i]; + currLayerNum++; + + float p = (float)i / addLayers.Length; + UnityEditor.EditorUtility.DisplayProgressBar("Merging Stage: Layers Build Layer: " + currLayer + " " + p, "Building Layer: " + layerNames[i], p); + AnimatorControllerLayer addLayer = addLayers[i]; + if (i == 0) + addLayer.defaultWeight = 1; + + addLayer.name = baseController.MakeUniqueLayerName(layerNames[i]); + AnimatorStateMachine sm = addLayer.stateMachine; + MoveStateMachine(sm, tempController); + baseLayers.Add(addLayer); + } + } + tempController.layers = baseLayers.ToArray(); + } + UnityEditor.EditorUtility.DisplayProgressBar("Merging Stage: Layers", "Done", 1); + AssetDatabase.SaveAssets(); + addController = null; + if (saveAsNewController) + { + AssetDatabase.CopyAsset(tempPath, newPath); + AssetDatabase.DeleteAsset(tempPath); + } + AssetDatabase.DeleteAsset(tempPathAdd); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + UnityEditor.EditorUtility.ClearProgressBar(); + } + + private string ln; + + private void MoveStateMachine(AnimatorStateMachine sm, AnimatorController tempController) + { + DoMove(sm, tempController); + + ln = " " + currLayerNum + "/" + canLayerNum; + + if (sm.states.Length != 0) + { + int sl = sm.states.Length; + + for (int i = 0; i < sl; i++) + { + var s = sm.states[i]; + + float p = (i + 1) / (float)sl; + + UnityEditor.EditorUtility.DisplayProgressBar("Merging Stage: Layers Build Layer: " + currLayer + ln + " > States " + p, "Building State: " + s.state.name, p); + DoMove(s.state, tempController); + + if (s.state.motion != null) + { + if (s.state.motion.GetType() == typeof(BlendTree)) + { + BlendTree blendTree = (BlendTree)s.state.motion; + MoveBlendTree(blendTree, tempController); + } + } + + //Debug.Log("transition: " + s.state.name + " > "+ s.state.transitions.Length); + if (s.state.transitions.Length != 0) + { + int l = s.state.transitions.Length; + //Debug.Log("transition: "+ l); + for (int iTrans = 0; iTrans < s.state.transitions.Length; iTrans++) + { + var t = s.state.transitions[iTrans]; + //Debug.Log("Building State: " + s.state.name + " > transition: " + iTrans + "/" + l); + UnityEditor.EditorUtility.DisplayProgressBar("Merging Stage: Layers Build Layer: " + currLayer + ln + " > States " + p, "Building State: " + s.state.name + " > transition: " + iTrans + "/" + l, p); + DoMove(t, tempController); + } + } + } + } + + //Debug.Log("transition: AnyState > " + sm.anyStateTransitions.Length); + if (sm.anyStateTransitions.Length != 0) + { + MoveTransitions(sm.anyStateTransitions, tempController, "AnyState"); + } + + //Debug.Log("transition: Entry > " + sm.entryTransitions.Length); + if (sm.entryTransitions.Length != 0) + { + MoveTransitions(sm.entryTransitions, tempController, "Entry"); + } + + if (sm.stateMachines.Length != 0) + { + foreach (var csm in sm.stateMachines) + { + AnimatorTransition[] animatorTransitions = sm.GetStateMachineTransitions(csm.stateMachine); + //Debug.Log("transition stateMachine: "+csm.stateMachine.name+" > " + animatorTransitions.Length); + if (animatorTransitions.Length != 0) + MoveTransitions(animatorTransitions, tempController, csm.stateMachine.name); + MoveStateMachine(csm.stateMachine, tempController); + } + } + } + + private void DoMove(Object assObj, AnimatorController tempController) + { + if (AssetDatabase.GetAssetPath(assObj) == AssetDatabase.GetAssetPath(tempAddController)) + { + AssetDatabase.RemoveObjectFromAsset(assObj); + AssetDatabase.SaveAssets(); + + AssetDatabase.AddObjectToAsset(assObj, tempController); + assObj.hideFlags = HideFlags.HideInHierarchy; + //Debug.Log("Adding"); + } + } + + private void MoveTransitions(AnimatorStateTransition[] transitions, AnimatorController tempController, string stateName) + { + //Debug.Log("transition: "+stateName+" > " + transitions.Length); + if (transitions.Length != 0) + { + int l = transitions.Length; + + for (int iTrans = 0; iTrans < l; iTrans++) + { + float p = (iTrans + 1) / (float)l; + var t = transitions[iTrans]; + //Debug.Log("Building State: " + stateName + " > transition: " + iTrans + "/" + l); + UnityEditor.EditorUtility.DisplayProgressBar("Merging Stage: Layers Build Layer: " + currLayer + ln + " > States ", "Building State: " + stateName + " > transition: " + iTrans + "/" + l, p); + DoMove(t, tempController); + } + } + } + + private void MoveTransitions(AnimatorTransition[] transitions, AnimatorController tempController, string stateName) + { + //Debug.Log("transition: " + stateName + " > " + transitions.Length); + if (transitions.Length != 0) + { + int l = transitions.Length; + + for (int iTrans = 0; iTrans < l; iTrans++) + { + float p = (iTrans + 1) / (float)l; + var t = transitions[iTrans]; + //Debug.Log("Building State: " + stateName + " > transition: " + iTrans + "/" + l); + UnityEditor.EditorUtility.DisplayProgressBar("Merging Stage: Layers Build Layer: " + currLayer + ln + " > States ", "Building State: " + stateName + " > transition: " + iTrans + "/" + l, p); + DoMove(t, tempController); + } + } + } + + private void MoveBlendTree(BlendTree bT, AnimatorController tempController) + { + DoMove(bT, tempController); + + if (bT.children.Length != 0) + { + foreach (var m in bT.children) + { + if (m.motion != null) + { + if (m.motion.GetType() == typeof(BlendTree)) + { + MoveBlendTree((BlendTree)m.motion, tempController); + } + } + } + } + } + } + + internal class ParameterComparer : IEqualityComparer + { + // AnimatorControllerParameters are equal if their names are equal. + public bool Equals(AnimatorControllerParameter x, AnimatorControllerParameter y) + { + //Check whether the compared objects reference the same data. + if (UnityEngine.Object.ReferenceEquals(x, y)) return true; + + //Check whether any of the compared objects is null. + if (UnityEngine.Object.ReferenceEquals(x, null) || UnityEngine.Object.ReferenceEquals(y, null)) + return false; + + //Check whether the properties are equal. + return x.name == y.name; + } + + // If Equals() returns true for a pair of objects + // then GetHashCode() must return the same value for these objects. + + public int GetHashCode(AnimatorControllerParameter parameter) + { + //Check whether the object is null + if (UnityEngine.Object.ReferenceEquals(parameter, null)) return 0; + + //Get hash code for the Name field if it is not null. + int hashAnimatorControllerParameterName = parameter.nameHash; + + return hashAnimatorControllerParameterName; + } + } +} \ No newline at end of file diff --git a/Tools/EasyDoors/PlayerInteractTeleport.cs b/Tools/EasyDoors/PlayerInteractTeleport.cs index 16bda07..2f3ad14 100644 --- a/Tools/EasyDoors/PlayerInteractTeleport.cs +++ b/Tools/EasyDoors/PlayerInteractTeleport.cs @@ -12,7 +12,7 @@ #endif -namespace UdonVR.Takato.PlayerTools +namespace UdonVR.Tools.PlayerTools { /// /// diff --git a/Tools/EasyLocks/Debug/Debug_EasyLocks_Button.cs b/Tools/EasyLocks/Debug/Debug_EasyLocks_Button.cs index b1a85c7..019b3ff 100644 --- a/Tools/EasyLocks/Debug/Debug_EasyLocks_Button.cs +++ b/Tools/EasyLocks/Debug/Debug_EasyLocks_Button.cs @@ -5,7 +5,7 @@ using VRC.Udon; using UnityEngine.UI; -namespace UdonVR.Childofthebeast.EasyLocks.Button +namespace UdonVR.Tools.EasyLocks.Button { public class Debug_EasyLocks_Button : UdonSharpBehaviour { diff --git a/Tools/EasyLocks/Debug/Debug_EasyLocks_Password.cs b/Tools/EasyLocks/Debug/Debug_EasyLocks_Password.cs index 4984c21..eea14fb 100644 --- a/Tools/EasyLocks/Debug/Debug_EasyLocks_Password.cs +++ b/Tools/EasyLocks/Debug/Debug_EasyLocks_Password.cs @@ -5,7 +5,7 @@ using VRC.Udon; using UnityEngine.UI; -namespace UdonVR.Childofthebeast.EasyLocks.Password +namespace UdonVR.Tools.EasyLocks.Password { public class Debug_EasyLocks_Password : UdonSharpBehaviour { diff --git a/Tools/Editor/SortChild.cs b/Tools/Editor/SortChild.cs new file mode 100644 index 0000000..17505a6 --- /dev/null +++ b/Tools/Editor/SortChild.cs @@ -0,0 +1,93 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System.Linq; +using UnityEditor; +using UnityEngine.UI; +using static UdonVR.EditorUtility.EditorHelper; +using System.Text; +using System; + +public class SortChild : EditorWindow +{ + + public string newPath = " "; + private GUILayoutOption[] space = new GUILayoutOption[] { GUILayout.Height(16), GUILayout.MinHeight(16), GUILayout.MaxHeight(16) }; + private GUILayoutOption[] noExpandWidth = new GUILayoutOption[] { GUILayout.Height(16), GUILayout.MinHeight(16), GUILayout.MaxHeight(16), GUILayout.ExpandWidth(false) }; + private GUIStyle style; + public GUIStyle logoStyle; + + Transform parentTransform; + + + [MenuItem("UdonVR/Sort Children")] + public static void ShowWindow() + { + SortChild window = GetWindow("Sort Children"); + window.minSize = new Vector2(385, 250); + } + private void GUIWarning(string text) + { + + EditorGUILayout.LabelField(new GUIContent(text, EditorGUIUtility.FindTexture("d_console.warnicon")), style); + + } + private void GUIError(string text) + { + EditorGUILayout.LabelField(new GUIContent(text, EditorGUIUtility.FindTexture("d_console.erroricon")), style); + + } + private void InitGuiStyles() + { + style = new GUIStyle(EditorStyles.helpBox); + style.richText = true; + style.fontSize = 15; + + logoStyle = new GUIStyle("flow node hex 0") + { + fontSize = 15, + richText = true, + alignment = TextAnchor.MiddleCenter, + hover = ((GUIStyle)"flow node hex 1").normal, + active = ((GUIStyle)"flow node hex 1 on").normal + }; + + logoStyle.padding.top = 17; + logoStyle.normal.textColor = Color.cyan; + } + public static string PadNumbers(string input) + { + return System.Text.RegularExpressions.Regex.Replace(input, "[0-9]+", match => match.Value.PadLeft(10, '0')); + } + private void OnGUI() + { + if (style == null) + InitGuiStyles(); + + EditorGUILayout.LabelField("Sort", style); + EditorGUILayout.Space(); + + parentTransform = (Transform)EditorGUILayout.ObjectField("Parent", parentTransform, typeof(Transform), true); + + if (GUILayout.Button("Sort")) + { + if (parentTransform != null && !UnityEditor.EditorUtility.IsPersistent(parentTransform)) + { + + List children = new List(); + foreach (Transform child in parentTransform) + { + children.Add(child); + } + + var sorted = children.OrderBy(child => PadNumbers(child.name)).ToList(); + + for (int i = 0; i < sorted.Count; i++) + { + sorted[i].SetSiblingIndex(i); + } + } + } + } + +} diff --git a/Tools/Utility/EditorHelper.cs b/Tools/Utility/EditorHelper.cs new file mode 100644 index 0000000..26724f7 --- /dev/null +++ b/Tools/Utility/EditorHelper.cs @@ -0,0 +1,283 @@ +#if UNITY_EDITOR +using UnityEngine; +using UdonVR.Tools.Utility; +using UnityEditor.SceneManagement; +using UdonSharpEditor; +using System.Collections.Generic; +using UnityEditor; +using System; + +namespace UdonVR.EditorUtility +{ + public static class EditorHelper + { + public struct PopupData + { + public GUIContent[] names; + public int[] ints; + } + + public static PopupData MakeTransformPopup(Transform[] transforms = null) + { + PopupData data = new PopupData(); + List transformNames; + List transformInts; + + if (transforms.IsNullOrEmpty()) + { + data.ints = new int[] { -1 }; + data.names = new GUIContent[] { new GUIContent("No Teleport") }; + return data; + } + transformInts = new List(); + transformNames = new List(); + transformInts.Add(-1); + transformNames.Add(new GUIContent("No Teleport")); + for (int i = 0; i < transforms.Length; i++) + { + if (transforms[i] != null) + { + transformInts.Add(i); + transformNames.Add(new GUIContent(transforms[i].name)); + } + } + data.ints = transformInts.ToArray(); + data.names = transformNames.ToArray(); + return data; + } + + public static PlayerTransforms GetPlayerTransforms() + { + GameObject[] rootGameObjects = EditorSceneManager.GetActiveScene().GetRootGameObjects(); + + foreach (var go in rootGameObjects) + { + //Debug.Log(go); + + try + { + var temp = go.GetUdonSharpComponentsInChildren(); + + if (temp != null && temp.Length > 0) + { + return temp[0]; + } + } + catch (System.Exception) + { + //Debug.LogError(go, go); + + //Debug.LogException(e, this); + } + } + return null; + } + + public static void ShowPositionHandles(Transform transform, Space space = Space.World) + { + Quaternion baseRot = (space == Space.World) ? Quaternion.identity : transform.rotation * Quaternion.LookRotation(Vector3.forward); + Handles.zTest = UnityEngine.Rendering.CompareFunction.Always; + EditorGUI.BeginChangeCheck(); + Vector3 newTargetPosition = Handles.PositionHandle(transform.position, baseRot); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(transform, "Change Transform Position"); + transform.position = newTargetPosition; + } + } + + public static void ShowRotationHandles(Transform transform, Space space = Space.World) + { + Quaternion baseRot = (space == Space.World) ? transform.rotation : transform.localRotation; + Handles.zTest = UnityEngine.Rendering.CompareFunction.Always; + EditorGUI.BeginChangeCheck(); + Quaternion newRot = Handles.RotationHandle(baseRot, transform.position); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(transform, "Change Transform Rotation"); + transform.rotation = newRot; + } + } + + public static void ShowTransform(Transform transform, Transform drawLineFrom = null, bool _Handel = true) + { + if (drawLineFrom != null) + ShowTransform(transform, true, drawLineFrom.position, _Handel); + else + ShowTransform(transform,false, new Vector3(), _Handel); + } + + public static void ShowTransform(Transform transform, Vector3 drawLineFrom, bool _Handel = true) + { + ShowTransform(transform, true, drawLineFrom, _Handel); + } + + private static void ShowTransform(Transform transform,bool drawLine = false, Vector3 drawLineFrom = new Vector3(),bool _Handel = true) + { + float size = 0.5f; + Color color = new Color(0.14f, 0, 0.5f, 0.9f); + if (drawLine) + { + Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual; + Color lineColor = new Color(0.5f, 0.5f, 0.5f, 1); + Handles.color = lineColor; + Handles.DrawLine(drawLineFrom, transform.position); + Handles.zTest = UnityEngine.Rendering.CompareFunction.GreaterEqual; + lineColor.a = 0.7f; + Handles.color = lineColor; + Handles.DrawDottedLine(drawLineFrom, transform.position, size * 10); + } + if (_Handel == true) + { + if (Event.current.type == EventType.Repaint) + { + Handles.lighting = false; + Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual; + //Handles.color = Handles.zAxisColor; + //Handles.color = new Color(1, 0, 1, 1); + Handles.color = color; + Handles.ArrowHandleCap( + 0, + transform.position + transform.forward * 0.1f, + transform.rotation * Quaternion.LookRotation(Vector3.forward), + size * 0.5f, + EventType.Repaint + ); + Handles.SphereHandleCap( + 0, + transform.position, + transform.rotation * Quaternion.LookRotation(Vector3.forward), + size * 0.5f, + EventType.Repaint + ); + Handles.zTest = UnityEngine.Rendering.CompareFunction.GreaterEqual; + Handles.color = new Color(1, 0, 1, 0.2f); + color.a *= 0.5f; + Handles.color = color; + + Handles.ArrowHandleCap( + 0, + transform.position + transform.forward * 0.1f, + transform.rotation * Quaternion.LookRotation(Vector3.forward), + size * 0.5f, + EventType.Repaint + ); + Handles.SphereHandleCap( + 0, + transform.position, + transform.rotation * Quaternion.LookRotation(Vector3.forward), + size * 0.5f, + EventType.Repaint + ); + } + } + } + + public static void TranformPosRotFields(Transform transform, Space space) + { + + if (space == Space.World) + { + EditorGUI.BeginChangeCheck(); + Vector3 newPos = EditorGUILayout.Vector3Field("Target Position", transform.position); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(transform, "Change Target Position"); + transform.position = newPos; + } + EditorGUI.BeginChangeCheck(); + Vector3 newRot = EditorGUILayout.Vector3Field("Target Rotation", WrapAngles(transform.eulerAngles)); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(transform, "Change Target Rotation"); + transform.eulerAngles = UnwrapAngles(newRot); + } + } + else + { + EditorGUI.BeginChangeCheck(); + Vector3 newPos = EditorGUILayout.Vector3Field("Target Position", transform.localPosition); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(transform, "Change Target Position"); + transform.localPosition = newPos; + } + Vector3 newRot = TransformUtils.GetInspectorRotation(transform); + EditorGUI.BeginChangeCheck(); + newRot = EditorGUILayout.Vector3Field("Target Rotation", newRot); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(transform, "Change Target Rotation"); + TransformUtils.SetInspectorRotation(transform, newRot); + } + } + } + + public static void LookAt(Transform transform, float newSize = 1.5f) + { + LookAt(transform.position, newSize); + } + + public static void LookAt(Vector3 position, float newSize = 1.5f) + { + SceneView.lastActiveSceneView.LookAt(position); + SceneView.lastActiveSceneView.size = newSize; + } + + public static void LookAt(Vector3 position, Quaternion rotation, float newSize = 1.5f) + { + SceneView.lastActiveSceneView.LookAt(position,rotation,newSize); + } + /// Editor Only Indicates whether the specified array is null or has a length of zero. + /// The array to test. + /// true if the array parameter is null or has a length of zero; otherwise, false. + public static bool IsNullOrEmpty(this Array array) + { + return (array == null || array.Length == 0); + } + + public static string GetfileDirectory([System.Runtime.CompilerServices.CallerFilePath] string filepath = "") + { + return System.IO.Path.GetDirectoryName(filepath); + } + + private static Vector3 WrapAngles(Vector3 angles) + { + + angles.x = WrapAngle(angles.x); + angles.y = WrapAngle(angles.y); + angles.z = WrapAngle(angles.z); + return angles; + } + private static Vector3 UnwrapAngles(Vector3 angles) + { + + angles.x = UnwrapAngle(angles.x); + angles.y = UnwrapAngle(angles.y); + angles.z = UnwrapAngle(angles.z); + return angles; + } + + private static float WrapAngle(float angle) + { + angle %= 360; + if (angle > 180) + return angle - 360; + + return angle; + } + + private static float UnwrapAngle(float angle) + { + if (angle >= 0) + return angle; + + angle = -angle % 360; + + return 360 - angle; + } + } + + +} +#endif diff --git a/Tools/Utility/PlayerTransforms.cs b/Tools/Utility/PlayerTransforms.cs new file mode 100644 index 0000000..881eeac --- /dev/null +++ b/Tools/Utility/PlayerTransforms.cs @@ -0,0 +1,276 @@ +using UnityEngine; +using UdonSharp; +using System; + +#if !COMPILER_UDONSHARP && UNITY_EDITOR // These using statements must be wrapped in this check to prevent issues on builds +using UnityEditor; +using UdonSharpEditor; +using UdonVR.EditorUtility; +#endif + +namespace UdonVR.Tools.Utility +{ + [AddComponentMenu("UdonVR/Tools/Player Teleports")] + /// + /// Holds Transforms for scripts + /// WIP + /// + public class PlayerTransforms : UdonSharpBehaviour + { + public Transform[] transforms; + } + +#if !COMPILER_UDONSHARP && UNITY_EDITOR + + [Flags] + enum EditMode + { + Position = 1 << 0, + Rotation = 1 << 1 + } + + [CustomEditor(typeof(PlayerTransforms))] + public class PlayerTransformsEditor : Editor + { + private SerializedProperty transforms; + + private GUIContent[] teleportSpotsNames; + //private Transform editTransform; + private static int editInt; + private static EditMode editMode = EditMode.Position; + //private string[] toolbarButtons = new string[] {"Pos","Rot"}; + GUIStyle[] buttons; + + + + + private int[] teleportSpotsInts; + private bool foldout=true; + private static Rect transformRect; + + // private string[] notProps = new string[] { "Base", "m_Script", "size", "data" }; + //private PlayerTransforms pTransforms; + + private void OnEnable() + { + transforms = serializedObject.FindProperty("transforms"); + editInt = -1; + //color1 = serializedObject.FindProperty("color1"); + + //Debug.Log("Enable"); + buttons = new GUIStyle[4]; + buttons[0] = new GUIStyle(EditorStyles.miniButtonLeft); + buttons[1] = new GUIStyle(buttons[0]); + buttons[1].normal = buttons[1].active; + buttons[2] = new GUIStyle(EditorStyles.miniButtonRight); + buttons[3] = new GUIStyle(buttons[2]); + buttons[3].normal = buttons[3].active; + + } + + + public override void OnInspectorGUI() + { + // Draws the default convert to UdonBehaviour button, program asset field, sync settings, etc. + if (UdonSharpGUI.DrawDefaultUdonSharpBehaviourHeader(target)) return; + + if(buttons == null) + { + buttons = new GUIStyle[4]; + buttons[0] = new GUIStyle(EditorStyles.miniButtonLeft); + buttons[1] = new GUIStyle(buttons[0]); + buttons[1].normal = buttons[1].active; + buttons[2] = new GUIStyle(EditorStyles.miniButtonRight); + buttons[3] = new GUIStyle(buttons[2]); + buttons[3].normal = buttons[3].active; + } + //PlayerTransforms PlayerTransforms = (PlayerTransforms)target; + //Debug.Log("GUI"); + //Debug.Log($"OnInspectorGUI {editInt} < {transforms.arraySize} + {GetInstanceID()}"); + transformRect = EditorGUILayout.BeginHorizontal(); + //GUI.Box(transformRect,"",EditorStyles.helpBox); + foldout = EditorGUILayout.Foldout(foldout, "Transforms",true); + //GUILayout.FlexibleSpace(); + if(editInt != -1) + { + if (editMode.HasFlag(EditMode.Position)) + { + if (GUILayout.Button("Position", buttons[1])) + { + editMode &= ~EditMode.Position; + //if (editMode == 0) + // editMode = EditMode.Rotation; + } + } + else + { + if (GUILayout.Button("Position", buttons[0])) + { + editMode |= EditMode.Position; + + } + } + if (editMode.HasFlag(EditMode.Rotation)) + { + if (GUILayout.Button("Rotation", buttons[3])) + { + editMode &= ~EditMode.Rotation; + //if (editMode == 0) + // editMode = EditMode.Position; + } + } + else + { + if (GUILayout.Button("Rotation", buttons[2])) + { + editMode |= EditMode.Rotation; + } + } + } + EditorGUILayout.EndHorizontal(); + if (foldout) + { + + transforms.arraySize = EditorGUILayout.DelayedIntField("Size", transforms.arraySize); + + for (int i = 0; i < transforms.arraySize; i++) + { + var transform = transforms.GetArrayElementAtIndex(i); + Rect rect = EditorGUILayout.BeginHorizontal(); + //EditorGUILayout.PropertyField(transforms.GetArrayElementAtIndex(i)); + EditorGUILayout.PrefixLabel(transform.displayName); + if (GUILayout.Button("Find", buttons[0], GUILayout.ExpandWidth(false))) + { + //editInt = -1; + var t = (Transform)transform.objectReferenceValue; + if (t != null) + { + + EditorHelper.LookAt(t); + editInt = i; + + } + //Debug.Log(editMode); + //SceneView.RepaintAll(); + } + if (editInt == i) + { + + if (GUILayout.Button("Edit", buttons[3], GUILayout.ExpandWidth(false))) + { + editInt = -1; + Debug.Log(editMode); + //SceneView.RepaintAll(); + } + } + else { + if (GUILayout.Button("Edit",buttons[2], GUILayout.ExpandWidth(false))) + { + editInt = i; + //SceneView.RepaintAll(); + } + } + EditorGUILayout.PropertyField(transform, GUIContent.none); + EditorGUILayout.EndHorizontal(); + } + } + //EditorGUILayout.PropertyField(transforms,true); + + //EditorGUILayout.PropertyField(color1); + //transforms. + + + if (Event.current.type == EventType.DragUpdated) + { + if (transformRect.Contains(Event.current.mousePosition)) + { + //Debug.Log(Event.current.type+ " Contained " + Event.current.mousePosition); + DragAndDrop.visualMode = DragAndDropVisualMode.Copy; + Debug.Log("Drag Updated!"); + Event.current.Use(); + } + else + { + //Debug.Log(Event.current.type + " Not Contained " + Event.current.mousePosition); + } + } + else if (Event.current.type == EventType.DragPerform) + { + if (transformRect.Contains(Event.current.mousePosition)) + { + Debug.Log(Event.current.type + " Contained " + Event.current.mousePosition); + Debug.Log("Drag Perform!"); + Debug.Log(DragAndDrop.objectReferences.Length); + for (int i = 0; i < DragAndDrop.objectReferences.Length; i++) + { + GameObject obj = DragAndDrop.objectReferences[i] as GameObject; + if (obj != null) + { + + int j = transforms.arraySize; + transforms.InsertArrayElementAtIndex(j); + transforms.GetArrayElementAtIndex(j).objectReferenceValue = obj.transform; + Debug.Log(obj.transform); + } + } + Event.current.Use(); + } + + } + + + serializedObject.ApplyModifiedProperties(); + } + + public void OnSceneGUI() + { + + //float size = 0.5f; + //Color color1 = new Color(0.14f, 0, 0.5f, 0.9f); //PRTT.color1; + + + if (editInt > -1 && editInt < transforms.arraySize) + { + //Debug.Log("SceneGUI Edit"); + Transform transform = (Transform)transforms.GetArrayElementAtIndex(editInt).objectReferenceValue; + + if (transform != null) + { + + if (editMode.HasFlag(EditMode.Position)) + EditorHelper.ShowPositionHandles(transform); + + if (editMode.HasFlag(EditMode.Rotation)) + EditorHelper.ShowRotationHandles(transform); + + EditorHelper.ShowTransform(transform); + + } + } + } + + private void MakePopup(Transform[] teleportToSpots = null) + { + if (teleportToSpots == null) + { + teleportSpotsInts = new int[] { -1 }; + teleportSpotsNames = new GUIContent[] { new GUIContent("No Teleport") }; + return; + } + teleportSpotsInts = new int[teleportToSpots.Length + 1]; + teleportSpotsNames = new GUIContent[teleportToSpots.Length + 1]; + teleportSpotsInts[0] = -1; + teleportSpotsNames[0] = new GUIContent("No Teleport"); + for (int i = 0; i < teleportToSpots.Length; i++) + { + teleportSpotsInts[i + 1] = i; + teleportSpotsNames[i + 1] = new GUIContent(teleportToSpots[i].name); + } + } + } + +#endif + + + +}