Search Unity

  1. Unity 2019.1 beta is now available.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We're looking for insight from anyone who has experience with game testing to help us better Unity. Take our survey here. If chosen to participate you'll be entered into a sweepstake to win an Amazon gift card.
    Dismiss Notice
  4. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  5. Unity 2018.3 is now released.
    Dismiss Notice
  6. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Tools API

Discussion in '2019.1 Beta' started by Prodigga, Nov 24, 2018.

  1. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    627
    Any more information? Documentation? Feature breakdown? This sounds really cool.
     
    Peter77 likes this.
  2. kaarrrllll

    kaarrrllll

    Unity Technologies

    Joined:
    Aug 24, 2017
    Posts:
    106
    Hey, yes there is API documentation for this coming, but it looks like the online docs haven't caught up to the 2019.1 alpha yet.

    The gist is that you can now write tools that behave like the built-in transform tools, and are accessible from the top toolbar.



    To get you started, here are two examples. One is a CustomEditor tool that applies to any selection with a MeshFilter component, the other is a Global tool that can be used with any selection.

    Code (CSharp):
    1. // CustomEditor tool example.
    2. // Shows a billboard at each vertex position on a selected mesh.
    3.  
    4. using System.Collections.Generic;
    5. using System.Linq;
    6. using UnityEngine;
    7. using UnityEditor;
    8. using UnityEditor.EditorTools;
    9. using UnityEngine.Rendering;
    10.  
    11. // By passing `typeof(MeshFilter)` as the second argument, we register VertexTool as a CustomEditor tool to be presented
    12. // when the current selection contains a MeshFilter component.
    13. [EditorTool("Show Vertices", typeof(MeshFilter))]
    14. class VertexTool : EditorTool
    15. {
    16.     struct TransformAndPositions
    17.     {
    18.         public Transform transform;
    19.         public IList<Vector3> positions;
    20.     }
    21.  
    22.     IEnumerable<TransformAndPositions> m_Vertices;
    23.     GUIContent m_ToolbarIcon;
    24.  
    25.     public override GUIContent toolbarIcon
    26.     {
    27.         get
    28.         {
    29.             if (m_ToolbarIcon == null)
    30.             {
    31.                 // Usually you'll want to use an icon (19x18 px to match Unity's icons)
    32.                 var icon19x18 = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Examples/Icons/VertexTool.png");
    33.  
    34.                 if(icon19x18 != null)
    35.                     m_ToolbarIcon = new GUIContent(icon19x18, "Vertex Visualization Tool");
    36.                 else
    37.                     m_ToolbarIcon = new GUIContent("Vertex Tool", "Vertex Visualization Tool");
    38.             }
    39.  
    40.             return m_ToolbarIcon;
    41.         }
    42.     }
    43.  
    44.     // Called when an EditorTool is made the active tool.
    45.     public override void OnActivate()
    46.     {
    47.         Selection.selectionChanged += RebuildVertexPositions;
    48.         RebuildVertexPositions();
    49.     }
    50.  
    51.     // Called when the active tool is changed.
    52.     public override void OnDeactivate()
    53.     {
    54.         Selection.selectionChanged -= RebuildVertexPositions;
    55.     }
    56.  
    57.     void RebuildVertexPositions()
    58.     {
    59.         m_Vertices = targets.Select(x =>
    60.         {
    61.             return new TransformAndPositions()
    62.             {
    63.                 transform = ((MeshFilter)x).transform,
    64.                 positions = ((MeshFilter)x).sharedMesh.vertices
    65.             };
    66.         }).ToArray();
    67.     }
    68.  
    69.     // If you've implemented scene tools before, think of this like the `OnSceneGUI` method. This is where you put the
    70.     // implementation of your tool.
    71.     public override void OnToolGUI(EditorWindow window)
    72.     {
    73.         var evt = Event.current;
    74.  
    75.         var zTest = Handles.zTest;
    76.         Handles.zTest = CompareFunction.LessEqual;
    77.  
    78.         foreach (var entry in m_Vertices)
    79.         {
    80.             var size = HandleUtility.GetHandleSize(entry.transform.position) * .05f;
    81.             DrawHandleCaps(entry.transform.localToWorldMatrix, entry.positions, size);
    82.         }
    83.  
    84.         Handles.zTest = zTest;
    85.     }
    86.  
    87.     static void DrawHandleCaps(Matrix4x4 matrix, IList<Vector3> positions, float size)
    88.     {
    89.         if (Event.current.type != EventType.Repaint)
    90.             return;
    91.  
    92.         Vector3 sideways = (Camera.current == null ? Vector3.right : Camera.current.transform.right) * size;
    93.         Vector3 up = (Camera.current == null ? Vector3.up : Camera.current.transform.up) * size;
    94.         Color col = Handles.color * new Color(1, 1, 1, 0.99f);
    95.  
    96.         // After drawing the first dot cap, the handle material and matrix are set up, so there's no need to keep
    97.         // resetting the state.
    98.         Handles.DotHandleCap(0, matrix.MultiplyPoint(positions[0]), Quaternion.identity,
    99.             HandleUtility.GetHandleSize(matrix.MultiplyPoint(positions[0])) * .05f, EventType.Repaint);
    100.  
    101.         GL.Begin(GL.QUADS);
    102.  
    103.         for (int i = 1, c = positions.Count; i < c; i ++)
    104.         {
    105.             var position = matrix.MultiplyPoint(positions[i]);
    106.  
    107.             GL.Color(col);
    108.             GL.Vertex(position + sideways + up);
    109.             GL.Vertex(position + sideways - up);
    110.             GL.Vertex(position - sideways - up);
    111.             GL.Vertex(position - sideways + up);
    112.         }
    113.  
    114.         GL.End();
    115.     }
    116. }
    117.  
    Code (CSharp):
    1. // Example of a global tool.
    2. // This is a "super" transform handle that shows the position handles for all 6 directions, as well as a rotation
    3. // handle.
    4.  
    5. using UnityEditor;
    6. using UnityEditor.EditorTools;
    7. using UnityEngine;
    8.  
    9. [EditorTool("Super Transform Tool")]
    10. public class SimpleGlobalTool : EditorTool
    11. {
    12.     GUIContent m_ToolbarIcon;
    13.  
    14.     public override GUIContent toolbarIcon
    15.     {
    16.         get
    17.         {
    18.             if (m_ToolbarIcon == null)
    19.                 m_ToolbarIcon = new GUIContent(
    20.                     AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/Examples/Icons/SimpleIcon.png"),
    21.                     "Simple Global Tool");
    22.             return m_ToolbarIcon;
    23.         }
    24.     }
    25.  
    26.     public override void OnToolGUI(EditorWindow window)
    27.     {
    28.         var sceneView = window as SceneView;
    29.  
    30.         if (sceneView == null)
    31.             return;
    32.  
    33.         foreach (var trs in Selection.transforms)
    34.         {
    35.             EditorGUI.BeginChangeCheck();
    36.  
    37.             var rot = trs.rotation;
    38.             var pos = trs.position;
    39.  
    40.             Handles.color = Color.green;
    41.             pos = Handles.Slider(pos, trs.up);
    42.             pos = Handles.Slider(pos, -trs.up);
    43.  
    44.             Handles.color = Color.red;
    45.             pos = Handles.Slider(pos, trs.right);
    46.             pos = Handles.Slider(pos, -trs.right);
    47.  
    48.             Handles.color = Color.blue;
    49.             pos = Handles.Slider(pos, trs.forward);
    50.             pos = Handles.Slider(pos, -trs.forward);
    51.  
    52.             rot = Handles.RotationHandle(rot, pos);
    53.  
    54.             if (EditorGUI.EndChangeCheck())
    55.             {
    56.                 Undo.RecordObject(trs, "Simple Transform Tool");
    57.                 trs.position = pos;
    58.                 trs.rotation = rot;
    59.             }
    60.         }
    61.     }
    62. }
    63.  
     
  3. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    627
    Amazing response! Thanks for your time!
     
    kaarrrllll likes this.
  4. kaarrrllll

    kaarrrllll

    Unity Technologies

    Joined:
    Aug 24, 2017
    Posts:
    106
  5. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    627
    Sorry to dig this up but would you be able to provide an example that uses a window on the scene GUI too? (IE a mock vertex painting tool with brush settings in a GUI.window). I noticed the tool window and the camera preview windows automatically stack on top of one another, for example. When I was writing my tool, I naturally wanted to have a window for my tool in the scene view, too, but I don't know what the correct way to do it is. I'd want my tool window to fit in this stack of other windows.