Search Unity

Feedback [Editor] Display global position of a child object in a prefab ?

Discussion in 'Editor Workflows' started by Quatum1000, Aug 14, 2021.

  1. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    Hi,

    is there a chance to display the global transform position of a child inside of a prefab?

    The transform component displays a local position only. But in some cases it important to know the world position of a child object as well.

    I thought about to click any and hold control key to display transform values in world space.
    Also when moving a group of objects there is no movement delta or global position at the center given.

    Thanks!
     
  2. Ruchir

    Ruchir

    Joined:
    May 26, 2015
    Posts:
    934
    This would indeed be pretty helpful :)
     
  3. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    889
    I wrote a new World Transform Editor.

    Create a project folder:
    WorldTransform/Editor/ and place script inside

    Click any child object and the WorldTransform will open.
    Position, Scale and Rotation can turn into very complex values if you use all at once.

    Untitled-1.jpg


    Code (CSharp):
    1. using System.Collections.Generic;
    2. using System.Linq;
    3. using System.Reflection;
    4. using UnityEditor;
    5. using UnityEngine;
    6.  
    7. // Roger Cabo 2020 V1.0. Transform component extension.
    8. // Display real world transform values for child objects automatically.
    9. // Reminds fold/unfold option
    10.  
    11. [CustomEditor(typeof(Transform)), CanEditMultipleObjects]
    12. public class WorldTransform : UIBaseAlignmentInspector {
    13.     bool unfold = false;
    14.     SerializedProperty p;
    15.     SerializedProperty r;
    16.     SerializedProperty s;
    17.     Transform t;
    18.  
    19.     public WorldTransform() : base("TransformInspector") { }
    20.  
    21.     void OnEnable() {
    22.         p = serializedObject.FindProperty("m_LocalPosition");
    23.         r = serializedObject.FindProperty("m_LocalRotation");
    24.         s = serializedObject.FindProperty("m_LocalScale");
    25.         t = target as Transform;
    26.         if (EditorPrefs.HasKey("CustomWordTransformUnfold"))
    27.             unfold = EditorPrefs.GetString("CustomWordTransformUnfold") == "True";
    28.     }
    29.  
    30.     public override void OnInspectorGUI() {
    31.         base.OnInspectorGUI();
    32.  
    33.         if (p.vector3Value != t.position  || s.vector3Value != t.transform.lossyScale) {
    34.             // || r.vector3Value != t.transform.rotation.eulerAngles
    35.             string originLabel = "Word Transform";
    36.             unfold = EditorGUILayout.Foldout(unfold, originLabel);
    37.             EditorPrefs.SetString("CustomWordTransformUnfold", unfold.ToString());
    38.             if (unfold) {
    39.                 EditorGUILayout.Vector3Field("Position", RoundTo5th(t.position));
    40.                 EditorGUILayout.Vector3Field("Rotation", t.rotation.eulerAngles);
    41.                 EditorGUILayout.Vector3Field("Scale", RoundTo5th(t.lossyScale));
    42.             }
    43.         }
    44.     }
    45.  
    46.     Vector3 RoundTo5th(Vector3 v3) {
    47.         return new Vector3((float)System.Math.Round(v3.x, 5), (float)System.Math.Round(v3.y, 5), (float)System.Math.Round(v3.z, 5));
    48.     }
    49. }
    50.  
    51. public abstract class UIBaseAlignmentInspector : Editor {
    52.     // Reflection Array
    53.     private static readonly object[] EMPTY_ARRAY = new object[0];
    54.  
    55.     #region Editor Fields
    56.  
    57.     /// <summary>
    58.     /// Type object for the internally used UIBaseAlignmentInspector editor.
    59.     /// </summary>
    60.     private System.Type AlignmentInspectorType;
    61.  
    62.     /// <summary>
    63.     /// Type object for the object that is edited by this editor.
    64.     /// </summary>
    65.     private System.Type editedObjectType;
    66.  
    67.     private Editor editorInstance;
    68.  
    69.     #endregion
    70.  
    71.     private static Dictionary<string, MethodInfo> decoratedMethods = new Dictionary<string, MethodInfo>();
    72.  
    73.     private static Assembly editorAssembly = Assembly.GetAssembly(typeof(Editor));
    74.  
    75.     protected Editor EditorInstance {
    76.         get {
    77.             if (editorInstance == null && targets != null && targets.Length > 0) {
    78.                 editorInstance = Editor.CreateEditor(targets, AlignmentInspectorType);
    79.             }
    80.             if (editorInstance == null) {
    81.                 Debug.LogError("Could not create editor !");
    82.             }
    83.             return editorInstance;
    84.         }
    85.     }
    86.  
    87.     public UIBaseAlignmentInspector(string editorTypeName) {
    88.         this.AlignmentInspectorType = editorAssembly.GetTypes().Where(t => t.Name == editorTypeName).FirstOrDefault();
    89.         Init();
    90.         var originalEditedType = GetCustomEditorType(AlignmentInspectorType);
    91.         if (originalEditedType != editedObjectType) {
    92.             throw new System.ArgumentException(
    93.                  string.Format("Type {0} does not match the editor {1} type {2}",
    94.                               editedObjectType, editorTypeName, originalEditedType));
    95.         }
    96.     }
    97.  
    98.     private System.Type GetCustomEditorType(System.Type type) {
    99.         var flags = BindingFlags.NonPublic | BindingFlags.Instance;
    100.         var attributes = type.GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[];
    101.         var field = attributes.Select(editor => editor.GetType().GetField("m_InspectedType", flags)).First();
    102.         return field.GetValue(attributes[0]) as System.Type;
    103.     }
    104.  
    105.     private void Init() {
    106.         var flags = BindingFlags.NonPublic | BindingFlags.Instance;
    107.         var attributes = this.GetType().GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[];
    108.         var field = attributes.Select(editor => editor.GetType().GetField("m_InspectedType", flags)).First();
    109.         editedObjectType = field.GetValue(attributes[0]) as System.Type;
    110.     }
    111.  
    112.     void OnDisable() {
    113.         if (editorInstance != null) {
    114.             DestroyImmediate(editorInstance);
    115.         }
    116.     }
    117.  
    118.     /// <summary>
    119.     /// Delegate by UIBaseAlignmentInspector instance
    120.     /// </summary>
    121.     protected void CallInspectorMethod(string methodName) {
    122.         MethodInfo method = null;
    123.         if (!decoratedMethods.ContainsKey(methodName)) {
    124.             var flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;
    125.             method = AlignmentInspectorType.GetMethod(methodName, flags);
    126.             if (method != null) {
    127.                 decoratedMethods[methodName] = method;
    128.             } else {
    129.                 Debug.LogError(string.Format("Could not find method {0}", methodName));
    130.             }
    131.         } else {
    132.             method = decoratedMethods[methodName];
    133.         }
    134.         if (method != null) {
    135.             method.Invoke(EditorInstance, EMPTY_ARRAY);
    136.         }
    137.     }
    138.  
    139.     protected override void OnHeaderGUI() {
    140.         CallInspectorMethod("OnHeaderGUI");
    141.     }
    142.  
    143.     public override void OnInspectorGUI() {
    144.         EditorInstance.OnInspectorGUI();
    145.     }
    146.  
    147.     public override void DrawPreview(Rect previewArea) {
    148.         EditorInstance.DrawPreview(previewArea);
    149.     }
    150.  
    151.     public override string GetInfoString() {
    152.         return EditorInstance.GetInfoString();
    153.     }
    154.  
    155.     public override GUIContent GetPreviewTitle() {
    156.         return EditorInstance.GetPreviewTitle();
    157.     }
    158.  
    159.     public override bool HasPreviewGUI() {
    160.         return EditorInstance.HasPreviewGUI();
    161.     }
    162.  
    163.     public override void OnInteractivePreviewGUI(Rect r, GUIStyle background) {
    164.         EditorInstance.OnInteractivePreviewGUI(r, background);
    165.     }
    166.  
    167.     public override void OnPreviewGUI(Rect r, GUIStyle background) {
    168.         EditorInstance.OnPreviewGUI(r, background);
    169.     }
    170.  
    171.     public override void OnPreviewSettings() {
    172.         EditorInstance.OnPreviewSettings();
    173.     }
    174.  
    175.     public override void ReloadPreviewInstances() {
    176.         EditorInstance.ReloadPreviewInstances();
    177.     }
    178.  
    179.     public override Texture2D RenderStaticPreview(string assetPath, Object[] subAssets, int width, int height) {
    180.         return EditorInstance.RenderStaticPreview(assetPath, subAssets, width, height);
    181.     }
    182.  
    183.     public override bool RequiresConstantRepaint() {
    184.         return EditorInstance.RequiresConstantRepaint();
    185.     }
    186.  
    187.     public override bool UseDefaultMargins() {
    188.         return EditorInstance.UseDefaultMargins();
    189.     }
    190. }
     
    Last edited: Aug 16, 2021