5 using System.Collections.Generic;
15 public class MRTKEditor : Editor
30 const string mrtkShowEditorKey =
"_Show_MRTK_Editors";
33 public static bool ShowCustomEditors
37 return GetEditorPref(mrtkShowEditorKey,
true);
41 SetEditorPref(mrtkShowEditorKey, value);
44 public static bool CustomEditorActive {
get;
private set; }
45 public static GameObject lastTarget;
48 private static GUIStyle toggleButtonOffStyle = null;
49 private static GUIStyle toggleButtonOnStyle = null;
50 private static GUIStyle sectionStyle = null;
51 private static GUIStyle toolTipStyle = null;
52 private static GUIStyle inProgressStyle = null;
55 protected readonly
static Color defaultColor =
new Color(1f, 1f, 1f);
56 protected readonly
static Color disabledColor =
new Color(0.6f, 0.6f, 0.6f);
57 protected readonly
static Color borderedColor =
new Color(0.8f, 0.8f, 0.8f);
58 protected readonly
static Color warningColor =
new Color(1f, 0.85f, 0.6f);
59 protected readonly
static Color errorColor =
new Color(1f, 0.55f, 0.5f);
60 protected readonly
static Color successColor =
new Color(0.8f, 1f, 0.75f);
61 protected readonly
static Color objectColor =
new Color(0.85f, 0.9f, 1f);
62 protected readonly
static Color helpBoxColor =
new Color(0.70f, 0.75f, 0.80f, 0.5f);
63 protected readonly
static Color sectionColor =
new Color(0.85f, 0.9f, 1f);
64 protected readonly
static Color darkColor =
new Color(0.1f, 0.1f, 0.1f);
65 protected readonly
static Color objectColorEmpty =
new Color(0.75f, 0.8f, 0.9f);
66 protected readonly
static Color profileColor =
new Color(0.88f, 0.7f, .97f);
67 protected readonly
static Color handleColorSquare =
new Color(0.0f, 0.9f, 1f);
68 protected readonly
static Color handleColorCircle =
new Color(1f, 0.5f, 1f);
69 protected readonly
static Color handleColorSphere =
new Color(1f, 0.5f, 1f);
70 protected readonly
static Color handleColorAxis =
new Color(0.0f, 1f, 0.2f);
71 protected readonly
static Color handleColorRotation =
new Color(0.0f, 1f, 0.2f);
72 protected readonly
static Color handleColorTangent =
new Color(0.1f, 0.8f, 0.5f, 0.7f);
74 public const float DottedLineScreenSpace = 4.65f;
77 private static bool showHelp =
false;
79 private static Dictionary<string, bool> displayedSections =
new Dictionary<string, bool>();
80 private static int indentOnSectionStart = 0;
82 private static BindingFlags defaultBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
84 private bool recordingUndo =
false;
88 public override void OnInspectorGUI()
91 CustomEditorActive =
true;
96 DrawInspectorHeader();
97 Undo.RecordObject(target, target.name);
99 if (ShowCustomEditors)
101 BeginInspectorStyle();
108 base.DrawDefaultInspector();
112 }
catch (Exception e)
114 DrawError(e.ToString());
117 CustomEditorActive =
false;
120 public void OnSceneGUI()
122 recordingUndo =
false;
123 DrawCustomSceneGUI();
126 protected virtual void BeginInspectorStyle()
131 protected virtual void EndInspectorStyle()
136 protected virtual bool DisplayHeader {
get {
return true; } }
141 private void DrawInspectorHeader()
148 EditorGUILayout.Space();
149 GUILayout.BeginHorizontal();
150 if (GUILayout.Button(ShowCustomEditors ?
"Toggle Custom Editors (ON)" :
"Toggle Custom Editors (OFF)", ShowCustomEditors ? toggleButtonOnStyle : toggleButtonOffStyle))
152 ShowCustomEditors = !ShowCustomEditors;
154 if (ShowCustomEditors)
156 if (GUILayout.Button(showHelp ?
"Toggle Help (ON)" :
"Toggle Help (OFF)", showHelp ? toggleButtonOnStyle : toggleButtonOffStyle))
158 showHelp = !showHelp;
160 if (GUILayout.Button(
"Expand Sections", toggleButtonOffStyle))
162 Type targetType = target.GetType();
163 foreach (MemberInfo member
in targetType.GetMembers(defaultBindingFlags))
165 if (member.IsDefined(typeof(HeaderAttribute),
true))
167 HeaderAttribute h = member.GetCustomAttributes(typeof(HeaderAttribute),
true)[0] as HeaderAttribute;
168 string lookupName = targetType.Name + h.header;
169 if (!displayedSections.ContainsKey(lookupName))
171 displayedSections.Add(lookupName,
true);
175 displayedSections[lookupName] =
true;
180 if (GUILayout.Button(
"Collapse Sections", toggleButtonOffStyle))
182 Type targetType = target.GetType();
183 foreach (MemberInfo member
in targetType.GetMembers(defaultBindingFlags))
185 if (member.IsDefined(typeof(HeaderAttribute),
true))
187 HeaderAttribute h = member.GetCustomAttributes(typeof(HeaderAttribute),
true)[0] as HeaderAttribute;
188 string lookupName = targetType.Name + h.header;
189 if (!displayedSections.ContainsKey(lookupName))
191 displayedSections.Add(lookupName,
false);
195 displayedSections[lookupName] =
false;
201 GUILayout.EndHorizontal();
203 if (ShowCustomEditors)
205 GUI.color = defaultColor;
207 GUILayout.BeginVertical();
208 GUILayout.BeginHorizontal();
209 Type targetType = target.GetType();
210 foreach (DocLinkAttribute attribute
in targetType.GetCustomAttributes(typeof(DocLinkAttribute),
true))
212 string description = attribute.Description;
213 if (
string.IsNullOrEmpty(description))
215 description =
"Click for documentation about " + targetType.Name;
218 if (GUILayout.Button(description, EditorStyles.toolbarButton))
220 Application.OpenURL(attribute.DocURL);
223 GUILayout.EndHorizontal();
224 GUILayout.BeginHorizontal();
225 foreach (TutorialAttribute attribute
in targetType.GetCustomAttributes(typeof(TutorialAttribute),
true))
227 string description = attribute.Description;
228 if (
string.IsNullOrEmpty(description))
230 description =
"Click for a tutorial on " + targetType.Name;
233 if (GUILayout.Button(description, EditorStyles.toolbarButton))
235 Application.OpenURL(attribute.TutorialURL);
238 GUILayout.EndHorizontal();
239 GUILayout.BeginHorizontal();
240 List<Type> missingTypes =
new List<Type>();
241 foreach (UseWithAttribute attribute
in targetType.GetCustomAttributes(typeof(UseWithAttribute),
true))
243 Component targetGo = (Component)target;
244 if (targetGo == null)
249 foreach (Type type
in attribute.UseWithTypes)
251 Component c = targetGo.GetComponent(type);
254 missingTypes.Add(type);
258 if (missingTypes.Count > 0)
260 string warningMessage =
"This class is designed to be accompanied by scripts of (or inheriting from) types: \n";
261 for (
int i = 0; i < missingTypes.Count; i++)
263 warningMessage +=
" - " + missingTypes[i].FullName;
264 if (i < missingTypes.Count - 1)
265 warningMessage +=
"\n";
267 warningMessage +=
"\nIt may not function correctly without them.";
268 DrawWarning(warningMessage);
270 GUILayout.EndHorizontal();
271 GUILayout.EndVertical();
273 EditorGUILayout.Space();
279 protected void DrawCustomEditor()
281 EditorGUILayout.BeginVertical();
283 Type targetType = target.GetType();
285 List<MemberInfo> members =
new List<MemberInfo>(targetType.GetMembers(defaultBindingFlags));
288 int currentIndentLevel = 0;
289 bool insideSectionBlock =
false;
290 bool drawCurrentSection =
true;
292 foreach (MemberInfo member
in members)
296 switch (member.MemberType)
302 case MemberTypes.Field:
303 case MemberTypes.Property:
308 if (member.IsDefined(typeof(HeaderAttribute),
true))
310 HeaderAttribute header = member.GetCustomAttributes(typeof(HeaderAttribute),
true)[0] as HeaderAttribute;
311 if (insideSectionBlock)
316 insideSectionBlock =
true;
317 drawCurrentSection = DrawSectionStart(target.GetType().Name, header.header);
321 if ((insideSectionBlock && !drawCurrentSection) || !ShouldDrawMember(member, targetType, target))
332 if (member.IsDefined(typeof(SetIndentAttribute),
true))
334 SetIndentAttribute indent = member.GetCustomAttributes(typeof(SetIndentAttribute),
true)[0] as SetIndentAttribute;
335 currentIndentLevel += indent.Indent;
336 EditorGUI.indentLevel = currentIndentLevel;
339 if (member.IsDefined(typeof(FeatureInProgressAttribute),
true))
341 GUI.color = helpBoxColor;
342 EditorGUILayout.LabelField(
"(This field or property is marked as 'In Progress' and may have no effect.)", inProgressStyle);
343 GUI.color = Color.Lerp(disabledColor, Color.clear, 0.5f);
347 GUI.color = defaultColor;
352 object[] drawOverrideAttributes = null;
353 if (member.MemberType == MemberTypes.Field)
355 FieldInfo field = targetType.GetField(member.Name, defaultBindingFlags);
356 if (!field.IsPrivate || field.IsDefined(typeof(SerializeField),
true))
359 if (IsSubclassOf(field.FieldType, typeof(ProfileBase)))
362 profile = DrawProfileField(target, profile, field.FieldType);
363 field.SetValue(target, profile);
367 drawOverrideAttributes = field.GetCustomAttributes(typeof(DrawOverrideAttribute),
true);
369 if (drawOverrideAttributes.Length > 0)
371 if (drawOverrideAttributes.Length > 1)
372 DrawWarning(
"You should only use one DrawOverride attribute per member. Drawing " + drawOverrideAttributes[0].GetType().Name +
" only.");
374 (drawOverrideAttributes[0] as DrawOverrideAttribute).DrawEditor(target, field, serializedObject.FindProperty(field.Name));
379 DrawSerializedField(serializedObject, field.Name);
387 PropertyInfo prop = targetType.GetProperty(member.Name, defaultBindingFlags);
388 drawOverrideAttributes = prop.GetCustomAttributes(typeof(DrawOverrideAttribute),
true);
390 if (IsSubclassOf(prop.PropertyType, typeof(ProfileBase)))
393 profile = DrawProfileField(target, profile, prop.PropertyType);
394 prop.SetValue(target, profile, null);
397 else if (drawOverrideAttributes.Length > 0)
399 if (drawOverrideAttributes.Length > 1)
401 DrawWarning(
"You should only use one DrawOverride attribute per member. Drawing " + drawOverrideAttributes[0].GetType().Name +
" only.");
404 (drawOverrideAttributes[0] as DrawOverrideAttribute).DrawEditor(target, prop);
410 DrawWarning(
"There was a problem drawing the member " + member.Name +
":");
411 DrawError(
System.Environment.NewLine + e.ToString());
415 if (insideSectionBlock)
420 EditorGUILayout.EndVertical();
426 protected virtual void DrawCustomSceneGUI()
435 protected virtual void DrawCustomFooter()
443 protected void SaveChanges()
445 serializedObject.ApplyModifiedProperties();
446 EditorUtility.SetDirty(target);
458 private bool ShouldDrawMember(MemberInfo member, Type targetType,
object target)
460 object[] hideAttributes = member.GetCustomAttributes(typeof(HideInInspector),
true);
461 if (hideAttributes != null && hideAttributes.Length > 0)
464 bool shouldBeVisible =
true;
466 switch (member.MemberType)
468 case MemberTypes.Field:
470 foreach (ShowIfAttribute attribute
in member.GetCustomAttributes(typeof(ShowIfAttribute),
true))
472 if (!attribute.ShouldShow(target))
474 shouldBeVisible =
false;
480 case MemberTypes.Property:
482 if (member.GetCustomAttributes(typeof(Attribute),
true).Length == 0)
484 shouldBeVisible =
false;
489 foreach (ShowIfAttribute attribute
in member.GetCustomAttributes(typeof(ShowIfAttribute),
true))
491 if (!attribute.ShouldShow(target))
493 shouldBeVisible =
false;
503 return shouldBeVisible;
511 protected void DrawSerializedField(SerializedObject serializedObject,
string propertyPath)
513 SerializedProperty prop = serializedObject.FindProperty(propertyPath);
516 EditorGUILayout.PropertyField(prop,
true);
528 public static bool DrawSectionStart(
string targetName,
string headerName,
bool toUpper =
true,
bool drawInitially =
true)
530 string lookupName = targetName + headerName;
531 if (!displayedSections.ContainsKey(lookupName))
532 displayedSections.Add(lookupName, drawInitially);
534 bool drawSection = displayedSections[lookupName];
535 EditorGUILayout.Space();
536 Color tColor = GUI.color;
537 GUI.color = sectionColor;
541 headerName = headerName.ToUpper();
544 drawSection = EditorGUILayout.Foldout(drawSection, headerName,
true, sectionStyle);
545 displayedSections[lookupName] = drawSection;
546 EditorGUILayout.BeginVertical();
549 indentOnSectionStart = EditorGUI.indentLevel;
550 EditorGUI.indentLevel = 0;
558 public static void DrawSectionEnd()
560 EditorGUILayout.EndVertical();
561 EditorGUI.indentLevel = indentOnSectionStart;
568 public static void DrawToolTip(MemberInfo member)
570 if (member.IsDefined(typeof(TooltipAttribute),
true))
572 TooltipAttribute tooltip = member.GetCustomAttributes(typeof(TooltipAttribute),
true)[0] as TooltipAttribute;
573 Color prevColor = GUI.color;
574 GUI.color = helpBoxColor;
575 EditorGUI.indentLevel--;
576 EditorGUILayout.LabelField(tooltip.tooltip, toolTipStyle);
577 EditorGUI.indentLevel++;
578 GUI.color = prevColor;
582 public static void DrawWarning(
string warning)
584 Color prevColor = GUI.color;
586 GUI.color = warningColor;
587 EditorGUILayout.BeginVertical(EditorStyles.textArea);
588 EditorGUILayout.LabelField(warning, EditorStyles.wordWrappedMiniLabel);
589 EditorGUILayout.EndVertical();
591 GUI.color = prevColor;
594 public static void DrawError(
string error)
596 Color prevColor = GUI.color;
598 GUI.color = errorColor;
599 EditorGUILayout.BeginVertical(EditorStyles.textArea);
600 EditorGUILayout.LabelField(error, EditorStyles.wordWrappedMiniLabel);
601 EditorGUILayout.EndVertical();
603 GUI.color = prevColor;
606 public static void DrawDivider()
608 GUIStyle styleHR =
new GUIStyle(GUI.skin.box);
609 styleHR.stretchWidth =
true;
610 styleHR.fixedHeight = 2;
611 GUILayout.Box(
"", styleHR);
614 private void CreateStyles()
616 if (toggleButtonOffStyle == null)
618 toggleButtonOffStyle =
"ToolbarButton";
619 toggleButtonOffStyle.fontSize = 9;
620 toggleButtonOnStyle =
new GUIStyle(toggleButtonOffStyle);
621 toggleButtonOnStyle.normal.background = toggleButtonOnStyle.active.background;
623 sectionStyle =
new GUIStyle(EditorStyles.foldout);
624 sectionStyle.fontStyle = FontStyle.Bold;
626 toolTipStyle =
new GUIStyle(EditorStyles.wordWrappedMiniLabel);
627 toolTipStyle.fontStyle = FontStyle.Normal;
628 toolTipStyle.alignment = TextAnchor.LowerLeft;
630 inProgressStyle =
new GUIStyle(EditorStyles.wordWrappedMiniLabel);
631 inProgressStyle.fontStyle = FontStyle.Italic;
632 inProgressStyle.alignment = TextAnchor.LowerLeft;
653 Color prevColor = GUI.color;
654 GUI.color = profileColor;
655 EditorGUILayout.BeginVertical(EditorStyles.helpBox);
656 GUI.color = Color.Lerp(Color.white, Color.gray, 0.25f);
657 EditorGUILayout.LabelField(
"Select a " + profileType.Name +
" or create a new profile", EditorStyles.miniBoldLabel);
659 EditorGUILayout.BeginHorizontal();
660 newProfile = EditorGUILayout.ObjectField(profile, profileType,
false);
662 if (profileType.IsAbstract)
664 EditorGUILayout.BeginVertical();
665 List<Type> types = GetDerivedTypes(profileType, Assembly.GetAssembly(profileType));
667 EditorGUILayout.BeginHorizontal();
668 foreach (Type derivedType
in types)
670 if (GUILayout.Button(
"Create " + derivedType.Name))
672 profile = CreateProfile(derivedType);
675 if (GUILayout.Button(
"What's a profile?"))
679 EditorGUILayout.EndHorizontal();
681 EditorGUILayout.EndVertical();
685 EditorGUILayout.BeginHorizontal();
686 if (GUILayout.Button(
"Create Profile"))
688 profile = CreateProfile(profileType);
690 if (GUILayout.Button(
"What's a profile?"))
694 EditorGUILayout.EndHorizontal();
696 EditorGUILayout.EndHorizontal();
700 DrawError(
"You must choose a profile.");
704 EditorGUI.indentLevel++;
707 if (DrawSectionStart(target.GetType().Name, profile.name +
" (Click to edit)",
false,
false))
710 Editor inspector = Editor.CreateEditor(profile);
711 ProfileInspector profileInspector = (ProfileInspector)inspector;
712 if (profileInspector != null)
714 profileInspector.targetComponent = target as Component;
716 inspector.OnInspectorGUI();
720 EditorGUI.indentLevel--;
723 EditorGUILayout.EndVertical();
725 GUI.color = prevColor;
732 private static void LaunchProfileHelp()
734 EditorUtility.DisplayDialog(
736 "Profiles are assets that contain a set of common settings like colors or sound files." 737 +
"\n\nThose settings can be shared and used by any objects that keep a reference to the profile." 738 +
"\n\nThey make changing the style of a set of objects quicker and easier, and they reduce memory usage." 739 +
"\n\nA purple icon indicates that you're looking at a profile asset." 740 +
"\n\nFor more information please see the documentation at:" 741 +
"\n https://github.com/Microsoft/MRDesignLabs_Unity/" 750 private static UnityEngine.Object CreateProfile(Type profileType)
752 UnityEngine.Object asset = ScriptableObject.CreateInstance(profileType);
755 AssetDatabase.CreateAsset(asset,
"Assets/New" + profileType.Name +
".asset");
756 AssetDatabase.SaveAssets();
760 Debug.LogError(
"Couldn't create profile of type " + profileType.Name);
765 private static List<Type> GetDerivedTypes(Type baseType, Assembly assembly)
767 Type[] types = assembly.GetTypes();
768 List<Type> derivedTypes =
new List<Type>();
770 for (
int i = 0, count = types.Length; i < count; i++)
772 Type type = types[i];
773 if (IsSubclassOf(type, baseType))
775 derivedTypes.Add(type);
782 private static bool IsSubclassOf(Type type, Type baseType)
784 if (type == null || baseType == null || type == baseType)
787 if (baseType.IsGenericType ==
false)
789 if (type.IsGenericType ==
false)
791 return type.IsSubclassOf(baseType);
796 baseType = baseType.GetGenericTypeDefinition();
799 type = type.BaseType;
800 Type objectType = typeof(
object);
802 while (type != objectType && type != null)
804 Type curentType = type.IsGenericType ?
805 type.GetGenericTypeDefinition() : type;
806 if (curentType == baseType)
811 type = type.BaseType;
821 protected float AxisMoveHandle(Vector3 origin, Vector3 direction,
float distance,
float handleSize = 0.2f,
bool autoSize =
true)
823 Vector3 position = origin + (direction.normalized * distance);
825 Handles.color = handleColorAxis;
828 handleSize = Mathf.Lerp(handleSize, HandleUtility.GetHandleSize(position) * handleSize, 0.75f);
831 Handles.DrawDottedLine(origin, position, DottedLineScreenSpace);
832 Handles.ArrowHandleCap(0, position, Quaternion.LookRotation(direction), handleSize * 2, EventType.Repaint);
833 Vector3 newPosition = Handles.FreeMoveHandle(position, Quaternion.identity, handleSize, Vector3.zero, Handles.CircleHandleCap);
837 float newDistance = Vector3.Distance(origin, newPosition);
839 if (distance != newDistance)
841 recordingUndo =
true;
842 Undo.RegisterCompleteObjectUndo(target, target.name);
843 distance = newDistance;
848 protected Vector3 CircleMoveHandle(Vector3 position,
float handleSize = 0.2f,
bool autoSize =
true,
float xScale = 1f,
float yScale = 1f,
float zScale = 1f)
850 Handles.color = handleColorCircle;
853 handleSize = Mathf.Lerp(handleSize, HandleUtility.GetHandleSize(position) * handleSize, 0.75f);
856 Vector3 newPosition = Handles.FreeMoveHandle(position, Quaternion.identity, handleSize, Vector3.zero, Handles.CircleHandleCap);
860 if (position != newPosition)
862 recordingUndo =
true;
863 Undo.RegisterCompleteObjectUndo(target, target.name);
865 position.x = Mathf.Lerp(position.x, newPosition.x, Mathf.Clamp01(xScale));
866 position.y = Mathf.Lerp(position.z, newPosition.y, Mathf.Clamp01(yScale));
867 position.z = Mathf.Lerp(position.y, newPosition.z, Mathf.Clamp01(zScale));
872 protected Vector3 SquareMoveHandle(Vector3 position,
float handleSize = 0.2f,
bool autoSize =
true,
float xScale = 1f,
float yScale = 1f,
float zScale = 1f)
874 Handles.color = handleColorSquare;
877 handleSize = Mathf.Lerp(handleSize, HandleUtility.GetHandleSize(position) * handleSize, 0.75f);
881 Vector3 newPosition = Handles.FreeMoveHandle(position, Quaternion.identity, handleSize * 0.8f, Vector3.zero, Handles.RectangleHandleCap);
885 if (position != newPosition)
887 recordingUndo =
true;
888 Undo.RegisterCompleteObjectUndo(target, target.name);
890 position.x = Mathf.Lerp(position.x, newPosition.x, Mathf.Clamp01(xScale));
891 position.y = Mathf.Lerp(position.z, newPosition.y, Mathf.Clamp01(yScale));
892 position.z = Mathf.Lerp(position.y, newPosition.z, Mathf.Clamp01(zScale));
897 protected Vector3 SphereMoveHandle(Vector3 position,
float handleSize = 0.2f,
bool autoSize =
true,
float xScale = 1f,
float yScale = 1f,
float zScale = 1f)
899 Handles.color = handleColorSphere;
902 handleSize = Mathf.Lerp(handleSize, HandleUtility.GetHandleSize(position) * handleSize, 0.75f);
906 Vector3 newPosition = Handles.FreeMoveHandle(position, Quaternion.identity, handleSize * 2, Vector3.zero, Handles.SphereHandleCap);
910 if (position != newPosition)
912 recordingUndo =
true;
913 Undo.RegisterCompleteObjectUndo(target, target.name);
915 position.x = Mathf.Lerp(position.x, newPosition.x, Mathf.Clamp01(xScale));
916 position.y = Mathf.Lerp(position.z, newPosition.y, Mathf.Clamp01(yScale));
917 position.z = Mathf.Lerp(position.y, newPosition.z, Mathf.Clamp01(zScale));
922 protected Vector3 VectorHandle(Vector3 origin, Vector3 vector,
bool normalize =
true,
float handleLength = 1f,
bool clamp =
true,
float handleSize = 0.1f,
bool autoSize =
true)
924 Handles.color = handleColorTangent;
927 handleSize = Mathf.Lerp(handleSize, HandleUtility.GetHandleSize(origin) * handleSize, 0.75f);
930 Vector3 handlePosition = origin + (vector * handleLength);
931 float distanceToOrigin = Vector3.Distance(origin, handlePosition) / handleLength;
940 Handles.color = Color.Lerp(Color.gray, handleColorTangent, distanceToOrigin * 0.85f);
944 if (distanceToOrigin >= 0.98f)
946 Handles.color = Color.Lerp(handleColorTangent, Color.white, 0.5f);
953 Handles.DrawLine(origin, handlePosition);
955 Quaternion rotation = Quaternion.identity;
956 if (vector != Vector3.zero)
958 rotation = Quaternion.LookRotation(vector);
961 Vector3 newPosition = Handles.FreeMoveHandle(handlePosition, rotation, handleSize, Vector3.zero, Handles.DotHandleCap);
967 if (handlePosition != newPosition)
969 recordingUndo =
true;
970 Undo.RegisterCompleteObjectUndo(target, target.name);
971 vector = (newPosition - origin).normalized;
977 distanceToOrigin = Vector3.Distance(origin, newPosition) / handleLength;
980 distanceToOrigin = Mathf.Clamp01(distanceToOrigin);
982 vector *= distanceToOrigin;
988 protected Quaternion RotationHandle(Vector3 position, Quaternion rotation,
float handleSize = 0.2f,
bool autoSize =
true)
990 Handles.color = handleColorRotation;
993 handleSize = Mathf.Lerp(handleSize, HandleUtility.GetHandleSize(position) * handleSize, 0.75f);
997 Quaternion newRotation = Handles.FreeRotateHandle(rotation, position, handleSize * 2);
1003 Handles.color = Handles.zAxisColor;
1004 Handles.ArrowHandleCap(0, position, Quaternion.LookRotation(newRotation * Vector3.forward), handleSize * 2, EventType.Repaint);
1005 Handles.color = Handles.xAxisColor;
1006 Handles.ArrowHandleCap(0, position, Quaternion.LookRotation(newRotation * Vector3.right), handleSize * 2, EventType.Repaint);
1007 Handles.color = Handles.yAxisColor;
1008 Handles.ArrowHandleCap(0, position, Quaternion.LookRotation(newRotation * Vector3.up), handleSize * 2, EventType.Repaint);
1010 if (rotation != newRotation)
1012 recordingUndo =
true;
1013 Undo.RegisterCompleteObjectUndo(target, target.name);
1015 rotation = newRotation;
1021 #region editor prefs 1023 private static void SetEditorPref(
string key,
bool value)
1025 EditorPrefs.SetBool(Application.productName + key, value);
1028 private static bool GetEditorPref(
string key,
bool defaultValue)
1030 if (EditorPrefs.HasKey(Application.productName + key))
1032 return EditorPrefs.GetBool(Application.productName + key);
1035 EditorPrefs.SetBool(Application.productName + key, defaultValue);
1036 return defaultValue;