Search Unity

2D slider

Discussion in 'Immediate Mode GUI (IMGUI)' started by soren, Feb 21, 2008.

  1. soren

    soren

    Joined:
    Feb 18, 2008
    Posts:
    123
    Hi Guys!

    As the new student/audio programmer at Unity I'm using my first days embarking upon the Unity GUI system. Needless to say its great!
    Anyway, I was (more or less) forced to share my first creation with you lads. So here goes: a 2D slider control. It works similar to the horizontal and vertical sliders, only using Vector2 values instead,


    Code (csharp):
    1.  
    2. public class Slider2D : MonoBehaviour {
    3.  
    4.     public GUISkin SliderSkin;
    5.     public GUIStyle BackStyle;
    6.     public GUIStyle ThumbStyle;
    7.    
    8.    
    9.     public Vector2 value;
    10.     public Vector2 maxvalue;
    11.     public Vector2 minvalue;
    12.        
    13.     static Vector2 offset;
    14.     static int slider2Dhash = "Slider2D".GetHashCode();
    15.    
    16.    
    17.        
    18.     // Use this for initialization
    19.     void Start () {
    20.          
    21.     }
    22.    
    23.     // Update is called once per frame
    24.     void Update () {
    25.    
    26.     }
    27.    
    28.     // OnGUI
    29.     void OnGUI()
    30.     {
    31.             GUI.skin = SliderSkin;
    32.            
    33.             value = SliderTWOD( new Rect(120,120,100,100),
    34.                       value,
    35.                       maxvalue,
    36.                       minvalue,                  
    37.                       "box",
    38.                       GUI.skin.horizontalSliderThumb );
    39.                                
    40.     }
    41.    
    42.     static void swap(ref float f1, ref float f2) { float tmp = f1; f1 = f2; f2 = tmp; }
    43.    
    44.     static Vector2 SliderTWOD(Rect rect, Vector2 value, Vector2 maxvalue, Vector2 minvalue, GUIStyle backStyle, GUIStyle thumbStyle)
    45.     {
    46.         if (backStyle == null)
    47.             return value;
    48.         if (thumbStyle == null)
    49.             return value;
    50.          
    51.         int id = GUIUtility.GetControlID (slider2Dhash, FocusType.Native);
    52.                
    53.         // test max and min
    54.         if (maxvalue.x < minvalue.x) // swap
    55.             swap(ref maxvalue.x,ref minvalue.x);       
    56.         if (maxvalue.y < minvalue.y)
    57.             swap(ref maxvalue.y,ref minvalue.y);       
    58.        
    59.                
    60.                  
    61.         // value to px ratio vector
    62.         Vector2 val2pxRatio =  new Vector2(
    63.             (rect.width - (backStyle.padding.right + backStyle.padding.left)) / (maxvalue.x - minvalue.x),
    64.             ( rect.height - (backStyle.padding.top + backStyle.padding.bottom)) / (maxvalue.y - minvalue.y));
    65.        
    66.         // thumb
    67.         float thumbHeight = thumbStyle.fixedHeight==0?thumbStyle.padding.vertical:thumbStyle.fixedHeight;
    68.         float thumbWidth = thumbStyle.fixedWidth==0?thumbStyle.padding.horizontal:thumbStyle.fixedWidth;       
    69.        
    70.         Rect thumbRect = new Rect(
    71.                     rect.x + (value.x* val2pxRatio.x) - (thumbWidth/2) + backStyle.padding.left - (minvalue.x * val2pxRatio.x),
    72.                     rect.y + (value.y* val2pxRatio.y) - (thumbHeight/2) + backStyle.padding.top - (minvalue.y * val2pxRatio.y),
    73.                     thumbWidth, thumbHeight);
    74.        
    75.         Event e = Event.current;
    76.        
    77.         switch(e.GetTypeForControl(id))
    78.         {          
    79.             case EventType.mouseDown:
    80.                 {                  
    81.                     if (rect.Contains(e.mousePosition)) // inside this control
    82.                     {
    83.                        
    84.                         GUIUtility.hotControl = id;                
    85.                         // did we hit the thumb?
    86.                         if (thumbRect.Contains(e.mousePosition))
    87.                         {
    88.                             // record offset
    89.                             offset = new Vector2(
    90.                                                 e.mousePosition.x - thumbRect.x,
    91.                                                 e.mousePosition.y - thumbRect.y
    92.                                               );
    93.                            
    94.                         }
    95.                         else // or just outside
    96.                         {
    97.                             offset = new Vector2(7,7);                     
    98.                             value.x = (((e.mousePosition.x - rect.x) - offset.x + (thumbWidth/2) - backStyle.padding.left) / val2pxRatio.x) + (minvalue.x) ;
    99.                             value.y = (((e.mousePosition.y - rect.y) - offset.y + (thumbHeight/2) - backStyle.padding.top) / val2pxRatio.y) + (minvalue.y);
    100.                        
    101.                         }
    102.                         Event.current.Use ();
    103.                     }
    104.                 }          
    105.                 break;
    106.             case EventType.mouseUp:
    107.                 if (GUIUtility.hotControl == id)
    108.                     GUIUtility.hotControl = 0;
    109.                 break;                 
    110.             case EventType.mouseDrag:
    111.                 {
    112.                     if (GUIUtility.hotControl != id)
    113.                         break;
    114.                     // move thumb to mouse position
    115.                     value.x = (((e.mousePosition.x - rect.x + (thumbWidth/2)) - offset.x - backStyle.padding.left) / val2pxRatio.x) + (minvalue.x) ;
    116.                     value.y = (((e.mousePosition.y - rect.y + (thumbHeight/2)) - offset.y - backStyle.padding.top) / val2pxRatio.y) + (minvalue.y);
    117.                    
    118.                     // clamp
    119.                     value.x = Mathf.Clamp (value.x, minvalue.x, maxvalue.x);
    120.                     value.y = Mathf.Clamp (value.y, minvalue.y, maxvalue.y);
    121.                 }
    122.                 break;
    123.             case EventType.repaint:
    124.             {              
    125.                 // background              
    126.                 backStyle.Draw(rect,GUIContent.none, id);
    127.                 // thumb
    128.                 thumbStyle.Draw(thumbRect,GUIContent.none, id);
    129.             }
    130.             break;
    131.         }                  
    132.         return value;          
    133.     }  
    134. }
    135.  
    136.  
    Cheers,
    Søren
     
  2. NicholasFrancis

    NicholasFrancis

    Joined:
    Apr 8, 2005
    Posts:
    1,587
    Hi guys...

    Just wanted to point out that if you really want to dig into how to extend UnityGUI with your own controls, this piece of code is VERY close to how all controls in UnityGUI are made.

    So if you want to learn, pull this piece of code apart and put it back together. I'll be here to answer your questions.
     
  3. Jonathan Czeck

    Jonathan Czeck

    Joined:
    Mar 17, 2005
    Posts:
    1,713
    Thanks Søren (and welcome!) and Nicholas... I had been wanting some code like this for a very long time.

    So are a lot of the widgets implemented in C# then? Is there some hidden API for the clipping that happens with scroll views?

    Cheers,
    -Jon

    p.s. Can't wait to see what kind of audio things you'll be up to, Søren. I want to implement procedural music similar to what they've done in Spore. :)
     
  4. ceteris

    ceteris

    Joined:
    Feb 9, 2008
    Posts:
    25
    oh man, I cant get it to work, and it looks so cool. just created an emply gameobj, and added that script... should I do something in addition?

    thanks!
     
  5. CK

    CK

    Joined:
    May 28, 2007
    Posts:
    7
    You also need to assign the Sliderskin a GUISkin asset ( by Assets->Create->GUI SKin, and drag the GameSkin from project pane to the inspector), and Maxvalue to something that's not zero.
     

    Attached Files:

  6. Brian-Kehrer

    Brian-Kehrer

    Joined:
    Nov 7, 2006
    Posts:
    411
    @ Jon
    you can do clipping with a series of groups

    I did a smoothed sub-pixel version with matrices, but you can shorten it and do it with groups.
    The key idea is to move a large content box inside a smaller clipping group that stays in place.

    Code (csharp):
    1.  
    2. GUI.BeginGroup(Rect(0,0,390,392));//clipping
    3.      GUI.Label(Rect(0,-actualScroll,390,totalScrollHeight),tmpJournal, "Copy");
    4. GUI.EndGroup();                
    5.  
    6.  
     
  7. BLSCLACobra

    BLSCLACobra

    Joined:
    Feb 3, 2010
    Posts:
    17
    Hey, I'm using Unity iPhone 1.5 and I really need like a HorizontalSlider but they ones that are in there don't work properly as the thumb can slide out of the slider bar. and bad adjustable.
    and is there any way to get the Rects position of the thumb??
     
  8. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Hi, welcome to the forum!

    Have you tried the GUI.HorizontalSlider function?
     
  9. BLSCLACobra

    BLSCLACobra

    Joined:
    Feb 3, 2010
    Posts:
    17
    yes thats what I'm using because the other one we wanted was way to complicated and Unity doesn't give you enough freedom to play with the HorizontalSlider properties
    EDIT:

    well I got it working decent now but I found eighter a bug I belive..

    it apears that I always need to double tap the HorizontalSlidar first befor you can use the slider... is there a way around this...
     
  10. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Can you post the OnGUI code you are using to manage the slider? It could well be a bug, but it's worth checking out first.
     
  11. BLSCLACobra

    BLSCLACobra

    Joined:
    Feb 3, 2010
    Posts:
    17
    Code (csharp):
    1.  
    2. void OnGUI()
    3.     {
    4.         //xPos = sliderright.pixelInset.x + 0.5f * Screen.width - sliderright.pixelInset.width - 40.0f;
    5.         xPos =  0.5f * Screen.width + sliderright.pixelInset.width ;
    6.         yPos = Screen.height - sliderright.pixelInset.y - 0.5f * Screen.height - 0.5f * sliderright.pixelInset.height - 8.0f;
    7.  
    8.         sliderValue = GUI.HorizontalSlider(new Rect( xPos, yPos, 100.0f, 10.0f ), sliderValue, 0.0f, 100.0f);
    9.         slidertext.text = sliderText + string.Format( "{0:00}", sliderValue ) + "%";
    10.     }
    the calculation is to make sure the HorizontalSlider apears on the exact spot we want it to apear.

    but you need to tab the HS everytime befor you can slide the thumb..
    in the mean time I'm creating my own slider (orders from above)
     
  12. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Yeah, it looks like a bug. Can you file a report for it?
     
  13. BLSCLACobra

    BLSCLACobra

    Joined:
    Feb 3, 2010
    Posts:
    17
    I could if I knew how :oops:
     
  14. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    There's an item called "Report a problem" at the bottom of Unity's Help menu.
     
  15. BLSCLACobra

    BLSCLACobra

    Joined:
    Feb 3, 2010
    Posts:
    17
    sorry for the late reply but I already sended in the report last week :)
     
  16. jpoffley

    jpoffley

    Joined:
    Oct 16, 2017
    Posts:
    1
    I know I reviving a very old thread, but I am trying to edit this script from OnGUI() to work with RectTransforms in a Canvas, as the current 1D Unity UI slider works for example. Would anyone know how feasible this is to do? I am a novice Unity developer and have never worked with the OnGUI system. Cheers