PolyLineEditor

From Unify Community Wiki
Revision as of 14:20, 10 October 2011 by Tofitouf (Talk | contribs)

Jump to: navigation, search

Description

Here is a an exemple of how to use the Unity Handles class and adding custom editing tools.

Exemple Polyline.jpg

This tool adds "inScene" controls to add, remove and align a set of points. those points could be used in any way you want (path, curve, animations ....)


I'd like to thank Dantus from EddelWeiss Interactive for 2 very useful trick :

  • a way to know which handle I'm currently using
  • a way to hide default handle



Usage

Add the following class in an Editor directory

C#

<csharp>

using UnityEditor; using UnityEngine; using System.Collections; using System; using System.Reflection;

// Thanks to Dantus from EddelWeiss Interactive for this trick public class DefaultHandles {

   public static bool Hidden
   {
       get
       {
           Type type = typeof(Tools);
           FieldInfo field = type.GetField("s_Hidden", BindingFlags.NonPublic | BindingFlags.Static);
           return ((bool)field.GetValue(null));
       }
       set
       {
           Type type = typeof(Tools);
           FieldInfo field = type.GetField("s_Hidden", BindingFlags.NonPublic | BindingFlags.Static);
           field.SetValue(null, value);
       }
   }

}

[CustomEditor(typeof(PolyLine))] public class PolyLineEditor : Editor {

   Vector3[] globalPos;
  // Event current;
   int curPointIndex = -1;
   bool hideDefaultHandle = true;
   void OnEnable()
   {
       DefaultHandles.Hidden = hideDefaultHandle;
   }
   void OnDisable()
   {
       DefaultHandles.Hidden = false;
   }
   void Delete(PolyLine polyLine, int index)
   {
       if (index < 0 || index >= polyLine.positions.Length)
           return;
       ArrayList list = new ArrayList(polyLine.positions);
       list.RemoveAt(index);
       polyLine.positions = (Vector3 []) list.ToArray(typeof(Vector3));
   }
   void insert(PolyLine polyLine, int position)
   {
       ArrayList list = new ArrayList(polyLine.positions);


       if (polyLine.positions.Length == 0)
       {
           list.Add(Vector3.zero);
       }
       else if (polyLine.positions.Length == 1)
       {
       
           if (position == 0)
           {
               list.Insert(0, Vector3.zero);      
           }
           else
           {
               list.Add(polyLine.positions[0] * 2);      
           }
          
       }
       else
       {
           Vector3[] newArray = new Vector3[polyLine.positions.Length+1];
           if (position == -1 ) // last
               position = polyLine.positions.Length ;
           if (position == 0)
               list.Insert(0, Vector3.zero);      
           else if ( position == polyLine.positions.Length)
               list.Add(2 * polyLine.positions[position - 1] - polyLine.positions[position - 2]);
           else
           {
               // between 2 points, use middle
               list.Insert(position, 0.5f * (polyLine.positions[position - 1] + polyLine.positions[position]));
           }    
       }
       polyLine.positions = (Vector3 []) list.ToArray(typeof(Vector3));
   }
   void insideSceneGUI(PolyLine polyLine)
   {
       Rect size = new Rect(0, 0, 300, 200);
       float sizeButton = 30;
       Handles.BeginGUI();
     //  Handles.BeginGUI(new Rect(Screen.width - size.width - 10, Screen.height - size.height - 10, size.width, size.height));
       GUI.BeginGroup(new Rect(Screen.width - size.width - 10, Screen.height - size.height - 50, size.width, size.height));
       GUI.Box(size, "PolyLine Tool Bar");


       Rect rc = new Rect(0, sizeButton, size.width, sizeButton);
       GUI.Label(rc, "Double Clic on Circles to select a point");
       rc.y += sizeButton;
       if (curPointIndex != -1)
       {
           GUI.Label(rc, "Current Point " + curPointIndex);
           rc.y += sizeButton;
           rc.width = size.width / 3;


           if (GUI.Button(rc, "Insert Before"))
           {
               insert(polyLine, curPointIndex);
           }
           rc.x += rc.width;
           if (GUI.Button(rc, "Delete"))
           {
               Delete(polyLine, curPointIndex);
           }
           rc.x += rc.width;
           if (GUI.Button(rc, "Insert After"))
           {
               insert(polyLine, curPointIndex + 1);
               curPointIndex++;
           }


       }
       else
       {
           if (polyLine.positions.Length == 0)
           {
               if (GUI.Button(rc, "Insert"))
               {
                   insert(polyLine, 0);
               }
               rc.y += sizeButton;
           }
           else
           {
               rc.width = size.width / 2;
               if (GUI.Button(rc, "Insert First"))
               {
                   insert(polyLine, 0);
                   curPointIndex = 0;
               }
               rc.x += rc.width;
               if (GUI.Button(rc, "Insert Last"))
               {
                   insert(polyLine, -1);
                   curPointIndex = polyLine.positions.Length - 1;
               }
               rc.y += sizeButton;
           }
       }
      
       if (polyLine.positions.Length > 0)
       {
           //rc.y += sizeButton;
           rc.width = size.width / 2;
           rc.x = 0;
           rc.y += sizeButton+10;
           if (GUI.Button(rc, "Clear All"))
           {
               polyLine.positions = new Vector3[0];
               curPointIndex = -1;
           }
           rc.x += rc.width;
           if (GUI.Button(rc, "Reset y"))
           {
               for (int i = 0; i < polyLine.positions.Length; i++)
               {
                   polyLine.positions[i].y = 0;
               }
           }
       }
       rc.y += sizeButton + 10;
       rc.x = 0;
       rc.width = size.width;
       if (hideDefaultHandle)
       {
           if (GUI.Button(rc, "Show Main Transform"))
           {
               hideDefaultHandle = false;
               DefaultHandles.Hidden = hideDefaultHandle;
           }
       }
       else
       {
           if (GUI.Button(rc, "Hide Main Transform"))
           {
               hideDefaultHandle = true;
               DefaultHandles.Hidden = hideDefaultHandle;
           }
       }
       
       GUI.EndGroup();
       Handles.EndGUI();
   }
   
   void OnSceneGUI () 
   {
       // Thank to Dantus from Edelweiss for this helper
       // You need them somewhere.
       Quaternion handleRotation = Quaternion.identity;
       int someHashCode = GetHashCode();


       PolyLine polyLine = (PolyLine) target;
       Transform tr = polyLine.transform;
       globalPos = new Vector3[polyLine.positions.Length];
       for (int i = 0; i < polyLine.positions.Length; i++)
       {   
           Vector3 pos = tr.TransformPoint(polyLine.positions[i]);
           Handles.Label(pos, "   " + i);
           float size = HandleUtility.GetHandleSize(pos);
           // Get the needed data before the handle
           int controlIDBeforeHandle = GUIUtility.GetControlID(someHashCode, FocusType.Passive);
           bool isEventUsedBeforeHandle = (Event.current.type == EventType.used);
           //
          // pos = Handles.PositionHandle(pos, Quaternion.identity);
           Handles.ScaleValueHandle(0, pos, Quaternion.identity, size, Handles.SphereCap, 0);
           if (curPointIndex == i)
           {
               pos = Handles.PositionHandle(pos, Quaternion.identity);
           }


           // Get the needed data after the handle
           int controlIDAfterHandle = GUIUtility.GetControlID(someHashCode, FocusType.Passive);
           bool isEventUsedByHandle = !isEventUsedBeforeHandle && (Event.current.type == EventType.used);
           if
            ((controlIDBeforeHandle < GUIUtility.hotControl &&
              GUIUtility.hotControl < controlIDAfterHandle) ||
              isEventUsedByHandle)
           {
               curPointIndex = i;
           }
           polyLine.positions[i] = tr.InverseTransformPoint(pos);
           globalPos[i] = pos;
       }
       insideSceneGUI(polyLine);
       Handles.DrawPolyLine(globalPos);
   }
   override public void  OnInspectorGUI()
   {
       base.OnInspectorGUI();
   }

}


</csharp>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox