Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  3. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Angle property drawer

Discussion in 'Scripting' started by FREEZX, Mar 25, 2014.

  1. FREEZX

    FREEZX

    Joined:
    Apr 2, 2013
    Posts:
    61
    Hi,
    From the unity blog i found this gem:
    http://blogs.unity3d.com/2012/09/07/property-drawers-in-unity-4/
    I would really want to integrate the Angle attribute in my custom scripts, but i cannot find it anywhere.
    In which namespace does it exist in unity, and if it's not included in unity, would it be possible to get the PropertyDrawer code for it?
    Thanks!
     
  2. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,577
    I don't think it exists within Unity. Sameway that "Compact" or "Multiline" doesn't exist.
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    7,302
    That's a pretty nice property drawer for angle. I like that.

    I might write something similar when I get some time to do it. If I do, I'll post it here.
     
  4. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,577
    Because I liked the idea and I had time...



    Code (csharp):
    1.  
    2.         private static Vector2 mousePosition;
    3.  
    4.         public static float FloatAngle(Rect rect, float value, bool showValue)
    5.         {
    6.             int id = GUIUtility.GetControlID(FocusType.Native, rect);
    7.  
    8.             Rect knobRect = new Rect(rect.x, rect.y, rect.height, rect.height);
    9.  
    10.             if (Event.current != null)
    11.             {
    12.                 if (Event.current.type == EventType.MouseDown  knobRect.Contains(Event.current.mousePosition))
    13.                 {
    14.                     GUIUtility.hotControl = id;
    15.                     mousePosition = Event.current.mousePosition;
    16.                 }
    17.                 else if (Event.current.type == EventType.MouseUp  GUIUtility.hotControl == id)
    18.                     GUIUtility.hotControl = -1;
    19.                 else if (Event.current.type == EventType.MouseDrag  GUIUtility.hotControl == id)
    20.                 {
    21.                     Vector2 move = mousePosition - Event.current.mousePosition;
    22.                     value += -move.x - move.y;
    23.                     mousePosition = Event.current.mousePosition;
    24.                     GUI.changed = true;
    25.                 }
    26.             }
    27.  
    28.             GUI.DrawTexture(knobRect, KnobBack);
    29.             Matrix4x4 matrix = GUI.matrix;
    30.             GUIUtility.RotateAroundPivot(value, knobRect.center);
    31.             GUI.DrawTexture(knobRect, Knob);
    32.             GUI.matrix = matrix;
    33.  
    34.             if (showValue)
    35.             {
    36.                 Rect label = new Rect(rect.x + rect.height, rect.y, rect.width, rect.height);
    37.                 GUI.Label(label, value.ToString());
    38.             }
    39.  
    40.             return value;
    41.         }
    42.  
    Will probably add some snap every X angle... or clamp the value between 0 and 360 (or better, value from the Angle attribute)
     
    Mehrdad995 and rakkarage like this.
  5. FREEZX

    FREEZX

    Joined:
    Apr 2, 2013
    Posts:
    61
    Awesome. I'll try it out :D
     
  6. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    7,302
    Awesome, save me having to do it tonight after work. Thanks dude.
     
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,577
    With snap and min/max range... If you want to do a volume that goes up to 11.
    Turned the label into a floatfield.
    Without min/max, the knob is 0 to 360.

    Code (csharp):
    1.  
    2.         private static Vector2 mousePosition;
    3.  
    4.         public static float FloatAngle(Rect rect, float value)
    5.         {
    6.             return FloatAngle(rect, value, -1, -1, -1);
    7.         }
    8.  
    9.         public static float FloatAngle(Rect rect, float value, float snap)
    10.         {
    11.             return FloatAngle(rect, value, snap, -1, -1);
    12.         }
    13.  
    14.         public static float FloatAngle(Rect rect, float value, float snap, float min, float max)
    15.         {
    16.             int id = GUIUtility.GetControlID(FocusType.Native, rect);
    17.  
    18.             Rect knobRect = new Rect(rect.x, rect.y, rect.height, rect.height);
    19.  
    20.             float delta;
    21.             if (min != max)
    22.                 delta = ((max - min) / 360);
    23.             else
    24.                 delta = 1;
    25.  
    26.             if (Event.current != null)
    27.             {
    28.                 if (Event.current.type == EventType.MouseDown  knobRect.Contains(Event.current.mousePosition))
    29.                 {
    30.                     GUIUtility.hotControl = id;
    31.                     mousePosition = Event.current.mousePosition;
    32.                 }
    33.                 else if (Event.current.type == EventType.MouseUp  GUIUtility.hotControl == id)
    34.                     GUIUtility.hotControl = -1;
    35.                 else if (Event.current.type == EventType.MouseDrag  GUIUtility.hotControl == id)
    36.                 {
    37.                     Vector2 move = mousePosition - Event.current.mousePosition;
    38.                     value += delta * (-move.x - move.y);
    39.  
    40.                     if (snap > 0)
    41.                     {
    42.                         float mod = value % snap;
    43.  
    44.                         if (mod < (delta * 3) || Mathf.Abs(mod - snap) < (delta * 3))
    45.                             value = Mathf.Round(value / snap) * snap;
    46.                     }
    47.  
    48.                     mousePosition = Event.current.mousePosition;
    49.                     GUI.changed = true;
    50.                 }
    51.             }
    52.  
    53.             GUI.DrawTexture(knobRect, KnobBack);
    54.             Matrix4x4 matrix = GUI.matrix;
    55.  
    56.             if (min != max)
    57.                 GUIUtility.RotateAroundPivot(value * (360 / (max - min)), knobRect.center);
    58.             else
    59.                 GUIUtility.RotateAroundPivot(value, knobRect.center);
    60.  
    61.             GUI.DrawTexture(knobRect, Knob);
    62.             GUI.matrix = matrix;
    63.  
    64.             Rect label = new Rect(rect.x + rect.height, rect.y + (rect.height / 2) - 9, rect.height, 18);
    65.             value = EditorGUI.FloatField(label, value);
    66.  
    67.             if (min != max)
    68.                 value = Mathf.Clamp(value, min, max);
    69.  
    70.             return value;
    71.         }
    72.  
     
    Last edited: Mar 25, 2014
    rakkarage likes this.
  8. FREEZX

    FREEZX

    Joined:
    Apr 2, 2013
    Posts:
    61


    Tried out both this and the previous version, had a strange bug where i couldn't change to any other tabs until i clicked something in the Project Window.
    Fixed it by removing
    Matrix4x4 matrix = GUI.matrix;

    and setting line 61 to
    GUI.matrix = Matrix4x4.identity;

    Also, at first i forgot to call Repaint whenever the value changed, so let this be a warning to anyone who attempts to use this control.

    Thanks for the component!
     
  9. FREEZX

    FREEZX

    Joined:
    Apr 2, 2013
    Posts:
    61
    Or actually, no, that doesn't quite fix it...
     
  10. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,577
    Hmm... Very strange. I admit I'm not within a standard scope here. My inspector is nothing be standard, so that could explain the repaint (which I call automatically whenever a value change).

    However, I don't understand how the matrix issue is solved. Flagging it "identity" would remove any previous transform. Maybe that's acceptable.

    EDIT: Yeah, I have that weird tab issue. Will look into it later, but it's most likely related to the HotControl part.

    REDIT: Yup! I'm a moron who should check the documentation; http://docs.unity3d.com/Documentation/ScriptReference/GUIUtility-hotControl.html

    Change the line #33;

    Code (csharp):
    1.  
    2. GUIUtility.hotControl = -1;
    3.  
    for

    Code (csharp):
    1.  
    2. GUIUtility.hotControl = 0;
    3.  
     
    Last edited: Mar 25, 2014
  11. FREEZX

    FREEZX

    Joined:
    Apr 2, 2013
    Posts:
    61
    Awesome, thanks!
     
  12. Glaskows

    Glaskows

    Joined:
    Mar 14, 2013
    Posts:
    9
    Sorry to intrude... but I am having a problem with GUI.DrawTexture() in general and used your code because it seemed to work, but the problem persist. Inside a PropertyDrawer the DrawTexture seems to flicker and go away after some time when the control looses focus. I came to this problem after searching why my Labels don't rotate inside a PropertyDrawer.
    Are you experience the same issue?
    Thanks!
     
  13. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,577
    I'm sorry... Since I'm not using PropertyDrawer, I can't say I experienced that issue. However, I'm a bit surprised, as with or without PropertyDrawer, the behaviour should be the same. GUI are usually fairly stable. Are you sure nothing else is try to draw at the same spot? Maybe a group with a style or another GUI.
     
  14. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    949
    There is a bug (Case 568929) in Unity where GUI.DrawTexture fails to work within custom property drawers for the default inspector implementation. It does work, however, for a custom `Editor`.
     
  15. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,577
    Nothing to raise my already low opinion of propertydrawers... :p
     
  16. Pal01

    Pal01

    Joined:
    Aug 14, 2014
    Posts:
    1
    Is it possible for someone to post an example of how to implement this into a custom inspector(or property drawer)?
    Which parts of this code need to go into OnGUI or OnInspectorGUI?
    From where are you getting your texture assets for the knobs?, selection,public variable, loaded from path ,etc...
    thanks for the help
     
  17. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,577
    From the bug reported here, it wouldn't work for PropertyDrawer. Don't know if the bug was fixed.

    As for custom inspector, you should just need to call the FloatAngle method from OnInspectorGUI. You should check existing tutorial about writing inspector editor.

    As for loading asset, there's many different ways to do it... However, I doubt I could help much, since I've came up with my own way; I load them from a DLL. I just hate having my editor texture floating around my assets.
     
  18. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    949
    For anyone interested, I came up with this little workaround:
    Code (csharp):
    1. public static class GUIHelper {
    2.  
    3.     private static GUIStyle s_TempStyle = new GUIStyle();
    4.  
    5.     public static void DrawTexture(Rect position, Texture2D texture) {
    6.         if (Event.current.type != EventType.Repaint)
    7.             return;
    8.  
    9.         s_TempStyle.normal.background = texture;
    10.  
    11.         s_TempStyle.Draw(position, GUIContent.none, false, false, false, false);
    12.     }
    13.  
    14. }
     
    hoekkii likes this.
  19. Jiraiyah

    Jiraiyah

    Joined:
    Mar 4, 2013
    Posts:
    175
    @LightStriker : I tried to add it not only on property drawer but also with combination of attribute drawer for it, first take a look :

    Code (CSharp):
    1. public class AngleAttribute : PropertyAttribute
    2.     {
    3.         public readonly float snap;
    4.         public readonly float min;
    5.         public readonly float max;
    6.  
    7.         public AngleAttribute()
    8.         {
    9.             snap = 1;
    10.             min = -360;
    11.             max = 360;
    12.         }
    13.  
    14.         public AngleAttribute(float snap)
    15.         {
    16.             this.snap = snap;
    17.             min = -360;
    18.             max = 360;
    19.         }
    20.  
    21.         public AngleAttribute(float snap, float min, float max)
    22.         {
    23.             this.snap = snap;
    24.             this.min = min;
    25.             this.max = max;
    26.         }
    27.     }
    Code (CSharp):
    1. [CustomPropertyDrawer(typeof(AngleAttribute))]
    2.     public class AngleDrawer : PropertyDrawer
    3.     {
    4.         private static Vector2 mousePosition;
    5.         private static Texture2D KnobBack = Resources.Load("Textures/Editor/KnobBack") as Texture2D;
    6.         private static Texture2D Knob  = Resources.Load("Textures/Editor/Knob") as Texture2D;
    7.         private static GUIStyle s_TempStyle = new GUIStyle();
    8.         private static float height = 75;
    9.  
    10.         private AngleAttribute angleAttribute
    11.         {
    12.             get { return (AngleAttribute) attribute; }
    13.         }
    14.  
    15.         public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    16.         {
    17.             property.floatValue = FloatAngle(position, property.floatValue, angleAttribute.snap, angleAttribute.min, angleAttribute.max);
    18.         }
    19.  
    20.         public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    21.         {
    22.             return height;
    23.         }
    24.  
    25.         public static float FloatAngle(Rect rect, float value)
    26.         {
    27.             return FloatAngle(rect, value, -1, -1, -1);
    28.         }
    29.  
    30.         public static float FloatAngle(Rect rect, float value, float snap)
    31.         {
    32.             return FloatAngle(rect, value, snap, -1, -1);
    33.         }
    34.  
    35.         public static float FloatAngle(Rect rect, float value, float snap, float min, float max)
    36.         {
    37.             int id = GUIUtility.GetControlID(FocusType.Native, rect);
    38.  
    39.             Rect knobRect = new Rect(rect.x, rect.y, rect.height, rect.height);
    40.  
    41.             float delta;
    42.             if (min != max)
    43.                 delta = ((max - min) / 360);
    44.             else
    45.                 delta = 1;
    46.  
    47.             if (Event.current != null)
    48.             {
    49.                 if (Event.current.type == EventType.MouseDown && knobRect.Contains(Event.current.mousePosition))
    50.                 {
    51.                     GUIUtility.hotControl = id;
    52.                     mousePosition = Event.current.mousePosition;
    53.                 }
    54.                 else if (Event.current.type == EventType.MouseUp && GUIUtility.hotControl == id)
    55.                     GUIUtility.hotControl = 0;
    56.                 else if (Event.current.type == EventType.MouseDrag && GUIUtility.hotControl == id)
    57.                 {
    58.                     Vector2 move = mousePosition - Event.current.mousePosition;
    59.                     value += delta * (-move.x - move.y);
    60.  
    61.                     if (snap > 0)
    62.                     {
    63.                         float mod = value % snap;
    64.  
    65.                         if (mod < (delta * 3) || Mathf.Abs(mod - snap) < (delta * 3))
    66.                             value = Mathf.Round(value / snap) * snap;
    67.                     }
    68.  
    69.                     mousePosition = Event.current.mousePosition;
    70.                     GUI.changed = true;
    71.                 }
    72.             }
    73.  
    74.             GUI.DrawTexture(knobRect, KnobBack);
    75.             Matrix4x4 matrix = GUI.matrix;
    76.  
    77.             if (min != max)
    78.                 GUIUtility.RotateAroundPivot(value * (360 / (max - min)), knobRect.center);
    79.             else
    80.                 GUIUtility.RotateAroundPivot(value, knobRect.center);
    81.  
    82.             GUI.DrawTexture(knobRect, Knob);
    83.             GUI.matrix = matrix;
    84.  
    85.             Rect label = new Rect(rect.x + rect.height, rect.y + (rect.height / 2) - 9, rect.height, 18);
    86.             value = EditorGUI.FloatField(label, value);
    87.  
    88.             if (min != max)
    89.                 value = Mathf.Clamp(value, min, max);
    90.  
    91.             return value;
    92.         }
    93.  
    94.         private static void DrawTexture(Rect position, Texture2D texture)
    95.         {
    96.             if (Event.current.type != EventType.Repaint)
    97.                 return;
    98.             s_TempStyle.normal.background = texture;
    99.             s_TempStyle.Draw(position, GUIContent.none, false, false, false, false);
    100.         }
    101.     }

    Ok, here is my problems :
    1- how to get rid of the constant float i am declering on top for the size of property?
    2- when i use GUI.DrawTexture, lots of time the images gets disappeared
    3- if i use the DrawTexture method numberCruncher mentioned, the texture stays and won't flicker out, but then when changing the value, the knob won't rotate at all
    4- would be nice if you would share those knob and it's back images, i tried my hand but the result was not as fancy and when it rotates it gives the feeling that the gear is not rotating at it's center :/

    Edit : one more question, when i make some property drawers and during when i tweak the drawing stuff in code and save it back, the inspector gets ruined until i click on it, is there anyway to force it to repaint itself like editor windows?

    Edit 2 : found a solution for the flickering, the property needs to be repainted, how to do it ?
    first, you need to change method definitions like this :

    Code (CSharp):
    1. public static float FloatAngle(Rect rect, float value, SerializedProperty property)
    2.  
    3. public static float FloatAngle(Rect rect, float value, float snap, SerializedProperty property)
    4.  
    5. public static float FloatAngle(Rect rect, float value, float snap, float min, float max, SerializedProperty property)
    as you see i am sending in the serialized property, now, at the end of the main method that is drawing the property, where you have the return value; before that add this :

    Code (CSharp):
    1. EditorUtility.SetDirty(property.serializedObject.targetObject);
    so the last lines on that method will look like this :

    Code (CSharp):
    1. if (min != max)
    2.                 value = Mathf.Clamp(value, min, max);
    3.             EditorUtility.SetDirty(property.serializedObject.targetObject);
    4.             return value;
    Now in the place you would call this method in the OnGUI method, change it to send the property as last param :

    Code (CSharp):
    1. public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    2.         {
    3.             property.floatValue = FloatAngle(position, property.floatValue, angleAttribute.snap, angleAttribute.min, angleAttribute.max, property);
    4.         }
    here is how i use that property attribute :

    Code (CSharp):
    1. [Angle(1f,0,100f)]
    2. [SerializeField]
    3. private float angleTest;
    if you don't specify anything, it will snap to 1, min to -360 and max to 360 :D

    and the property drawer behaves properly, now only if someone share the nice gui pictures? :/
     
    Last edited: Sep 8, 2015
    ZenMicro and DomDom like this.
  20. ZenMicro

    ZenMicro

    Joined:
    Aug 9, 2015
    Posts:
    206
    Hi @Jiraiyah, or perhaps @LightStriker might be able to help but i saw you don't like PropertyDrawers... anyway worth a shot!

    I've attempted to use this PropertyDrawer but am new to these and While i have the AngleAttribute and AngleDrawer scripts correctly updated and saved in appropriate folders i am not sure on how to use it, I am attempting to use it within an EditorWindow that has a scriptable object class that contains a list of another scriptable object class that contains a list of scriptable object class if that makes sense.

    In any case the 3 lines you state at the end of your post as to how you are using them has me stuck, or something else is missing i think? If i use angleTest in my Editor window nothing special happens. It appears as a plain float value which i have been using with EditorGUILayout.Slider. Do i need to create a wrapper class for it and then use that? Appreciate your help here :)

    And Here are some links to some Knob Icons, best double check the licence on them some are Free Creative Commons, some with Attribution, not real sure if you can make a product for profit with them all...
    http://vector4free.com/vector/volume-knob/
    https://greensock.com/draggable
    http://www.ifreepic.com/knob-223415.html
    http://icones.gratuites.web.free.fr/?c=Default Icon&img=media-knob.png
    hope they suit your needs!
     
    Last edited: Nov 2, 2015
  21. Jiraiyah

    Jiraiyah

    Joined:
    Mar 4, 2013
    Posts:
    175
    @ZenMicro Hi,
    If you want to use it in a custom editor window, i would suggest to take out those methods from the drawer into a custom static class as a helper method (float angle and draw texture ones), then feed it with the needed information like what we did in OnGUI, obviously you would need to tweak the code here and there to feed in the rect that it needs to draw it in the editor window but it should be fairly straight forward then.
     
    ZenMicro likes this.
  22. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    259
    Is there a clean version of the final code for this anywhere?
     
  23. Xelnath

    Xelnath

    Joined:
    Jan 31, 2015
    Posts:
    259
    Code (csharp):
    1.  
    2.  
    3. using UnityEditor;
    4. using UnityEngine;
    5. public class AngleAttribute : PropertyAttribute
    6. {
    7.     public readonly float snap;
    8.     public readonly float min;
    9.     public readonly float max;
    10.  
    11.     public AngleAttribute()
    12.     {
    13.         snap = 1;
    14.         min = -360;
    15.         max = 360;
    16.     }
    17.  
    18.     public AngleAttribute(float snap)
    19.     {
    20.         this.snap = snap;
    21.         min = -360;
    22.         max = 360;
    23.     }
    24.  
    25.     public AngleAttribute(float snap, float min, float max)
    26.     {
    27.         this.snap = snap;
    28.         this.min = min;
    29.         this.max = max;
    30.     }
    31. }
    32.  
    33. [CustomPropertyDrawer(typeof(AngleAttribute))]
    34. public class AngleDrawer : PropertyDrawer
    35. {
    36.     private static Vector2 mousePosition;
    37.     private static Texture2D KnobBack = Resources.Load("Editor Icons/Dial") as Texture2D;
    38.     private static Texture2D Knob  = Resources.Load("Editor Icons/DialButton") as Texture2D;
    39.     //private static GUIStyle s_TempStyle = new GUIStyle();
    40.     //private static float height = 75;
    41.  
    42.     public static float FloatAngle(Rect rect, float value)
    43.     {
    44.         return FloatAngle(rect, value, -1, -1, -1);
    45.     }
    46.  
    47.     public static float FloatAngle(Rect rect, float value, float snap)
    48.     {
    49.         return FloatAngle(rect, value, snap, -1, -1);
    50.     }
    51.  
    52.     public static float FloatAngle(Rect rect, float value, float snap, float min, float max)
    53.     {
    54.         return FloatAngle(rect, value, snap, min, max, Vector2.up);
    55.     }
    56.  
    57.     public static float FloatAngle(Rect rect, float value, float snap, float min, float max, Vector2 zeroVector)
    58.     {
    59.         int id = GUIUtility.GetControlID(FocusType.Passive, rect);
    60.         float originalValue = value;
    61.         Rect knobRect = new Rect(rect.x, rect.y, rect.height, rect.height);
    62.  
    63.         float delta;
    64.         if (min != max)
    65.             delta = ((max - min) / 360);
    66.         else
    67.             delta = 1;
    68.  
    69.         if (Event.current != null)
    70.         {
    71.             if (Event.current.type == EventType.MouseDown && knobRect.Contains(Event.current.mousePosition))
    72.             {
    73.                 GUIUtility.hotControl = id;
    74.                 mousePosition = Event.current.mousePosition;
    75.             }
    76.             else if (Event.current.type == EventType.MouseUp &&  GUIUtility.hotControl == id)
    77.             {
    78.                 GUIUtility.hotControl = 0;
    79.             }
    80.             else if (Event.current.type == EventType.MouseDrag &&  GUIUtility.hotControl == id)
    81.             {
    82.                 Vector2 move = mousePosition - Event.current.mousePosition;
    83.  
    84.                 //if ( knobRect.Contains(mousePosition)  )
    85.                 {
    86.                     Vector2 mouseStartDirection = (mousePosition - knobRect.center).normalized;
    87.                     float startAngle = CalculateAngle(Vector2.up, mouseStartDirection);
    88.  
    89.                     Vector2 mouseNewDirection = (Event.current.mousePosition - knobRect.center).normalized;
    90.                     float newAngle = CalculateAngle(Vector2.up, mouseNewDirection);
    91.  
    92.  
    93.                     float sign = Mathf.Sign(newAngle-startAngle);
    94.                     float delta2 = Mathf.Min( Mathf.Abs(newAngle - startAngle), Mathf.Abs(newAngle-startAngle+360f), Mathf.Abs(newAngle-startAngle-360f) );
    95.                     value -= delta2 * sign;
    96.                 }
    97.  
    98.                 if (snap > 0)
    99.                 {
    100.                     float mod = value % snap;
    101.  
    102.                     if (mod < (delta * 3) || Mathf.Abs(mod - snap) < (delta * 3))
    103.                         value = Mathf.Round(value / snap) * snap;
    104.                 }
    105.  
    106.                 if ( value != originalValue)
    107.                 {
    108.                     mousePosition = Event.current.mousePosition;
    109.                     GUI.changed = true;
    110.                 }
    111.             }
    112.         }
    113.  
    114.         float angleOffset =  (CalculateAngle(Vector2.up, zeroVector ) + 360f) % 360f;
    115.  
    116.         GUI.DrawTexture(knobRect, KnobBack);
    117.         Matrix4x4 matrix = GUI.matrix;
    118.  
    119.         if (min != max)
    120.             GUIUtility.RotateAroundPivot((angleOffset + value) * (360 / (max - min)), knobRect.center);
    121.         else
    122.             GUIUtility.RotateAroundPivot((angleOffset + value), knobRect.center);
    123.  
    124.         GUI.DrawTexture(knobRect, Knob);
    125.         GUI.matrix = matrix;
    126.  
    127.         Rect label = new Rect(rect.x + rect.height, rect.y + (rect.height / 2) - 9, rect.height, 18);
    128.         value = EditorGUI.FloatField(label, value);
    129.  
    130.         if (min != max)
    131.             value = Mathf.Clamp(value, min, max);
    132.  
    133.         return value;
    134.     }
    135.  
    136.     public static float CalculateAngle(Vector3 from, Vector3 to) {
    137.         Vector3 right = Vector3.right;
    138.         float angle = Vector3.Angle(from, to);
    139.         return (Vector3.Angle(right, to) > 90f) ? 360f - angle : angle;          
    140.  
    141.         //return Quaternion.FromToRotation(Vector3.up, to - from).eulerAngles.z;
    142.     }
    143. }
    144.  
    Here's a cleaned up version where you can click and drag on the knob to turn it.

    You will have to add this to your editor:

    Code (csharp):
    1.  
    2.  
    3.      void OnEnable() { EditorApplication.update += Update; }
    4.      void OnDisable() { EditorApplication.update -= Update; }
    5.  
    6.      void Update()
    7.      {
    8.         Repaint();
    9.      }
    10.  
    And textures:


    Dial.png DialButton.png

    Oh and I forgot, usage:

    Code (csharp):
    1.  
    2.         var rect = GUILayoutUtility.GetRect(64f, 64f);
    3.         float newValue = AngleDrawer.FloatAngle(rect, someValue, 5f, 0f, 360f, Vector2.down );
    4.  
     
    Last edited: Mar 29, 2017
    zvidrih, kodo91 and alexanderameye like this.
unityunity