Search Unity

Slider that updates based on code unless touched?

Discussion in 'Immediate Mode GUI (IMGUI)' started by Jessy, Jul 28, 2008.

  1. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    I would like to make playheads using the GUI sliders and audio.time, but if that is possible, I can't figure it out. I need a way to override the value of a slider only if it is being clicked upon. Otherwise, I want it to update based on audio.time/audio.length.
     
  2. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    You can, never tried though..

    Just create your slider and update it with your audio.time

    After than check GUI.changed to know if your user has input some data and override your audio.time with that info

    .org
     
  3. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    You can't change the slider if it's being updated through other code, though, apparently.
     
  4. shaun

    shaun

    Joined:
    Mar 23, 2007
    Posts:
    728
    Why don't you check mousedown together with Rect.contains on the slider - if both are true, you write to the slider value based on the mouse offset from the left of the slider, otherwise just make it equal to whatever value you last had plus the elapsed time.
     
  5. Omar Rojo

    Omar Rojo

    Joined:
    Jan 4, 2007
    Posts:
    494
    ok i tested.. i think this is what you need


    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Slider : MonoBehaviour {
    5.  
    6.     private float mSlidertime;
    7.  
    8.     // Use this for initialization
    9.     void Start ()
    10.     {
    11.         mSlidertime = 0.0f;
    12.     }
    13.    
    14.     // Update is called once per frame
    15.     void Update ()
    16.     {
    17.         mSlidertime += Time.deltaTime;
    18.     }
    19.    
    20.    
    21.     void OnGUI ()
    22.     {
    23.         mSlidertime = GUI.HorizontalSlider (new Rect (10, 10, 200, 20), mSlidertime, 0.0f, 10.0f);
    24.        
    25.         if ( GUI.changed )
    26.         {
    27.             Debug.Log ("New audio.time=" + mSlidertime);
    28.         }
    29.     }
    30. }
    31.  
    Just modify it to suit your needs

    .org
     
  6. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Wow, I was just working on this (using your previous advice), and almost had a functional solution, but yours is less code and works better. Thanks a ton!
     
  7. soren

    soren

    Joined:
    Feb 18, 2008
    Posts:
    123
    This should work as well (js)
    Code (csharp):
    1. var oldTime = audio.time;
    2. var newTime = GUILayout.HorizontalSlider(oldTime, 0.0, audio.clip.length);
    3. if (oldTime != newTime) audio.time = newTime;
    4.  
     
  8. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Well, I spent a while searching for a solution to what I thought was a serious problem...

    No matter what I did, if I "paused" the audio, when I started it back up again at a different point, using the slider that this thread is about, a buffer of audio from when I paused would always play first. This was probably about a 1/8 sec. clip, which was just enough to be kind of annoying.

    I tried a few alternative solutions, because I thought it was a limitation of AudioSource.Pause(). But no. In the IDE, the problem is unavoidable. However, the built projects do not exhibit this behavior. Now that I know, it's not a big deal, but it would be nice if this worked better in the editor, so that no one else ever has to waste time trying to fix it like I did.

    My girlfriend is making the visual elements of my GUI presently. I'll put my jukebox the showcase asap. Thanks again for your help, guys.
     
  9. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    http://teamuv.net/jessy/music/

    As it is with the examples you guys gave, the playback starts up immediately after moving the slider. I would prefer for the playback to pause when dragging, and then play again when the thumb is released. I tried using GUIUtility.hotControl for this purpose, but I don't really know to work with GUI Events. The manual tells me that it will instruct me, but it lies:

    http://unity3d.com/support/documentation/Manual/Game Interface Elements.html

    http://unity3d.com/support/documentation/ScriptReference/GUIUtility.html

    Any ideas?
     
  10. shaun

    shaun

    Joined:
    Mar 23, 2007
    Posts:
    728
    This is what I was getting at with my example, however my explanation was rather bad.
    Here's the code. It's quick and dirty, but it operates exactly like iTunes.

    Code (csharp):
    1. public class NewBehaviourScript : MonoBehaviour
    2. {
    3.     public float sliderPos;
    4.     private Rect sliderRect = new Rect(10, 10, 300, 32);
    5.     private bool UpdateAudioTime = false;
    6.  
    7.     void OnGUI()
    8.     {
    9.         GUILayout.BeginArea(sliderRect);
    10.         if (Input.GetMouseButton(0))
    11.         {
    12.             sliderPos = GUILayout.HorizontalSlider(sliderPos, 0, audio.clip.length);
    13.             UpdateAudioTime = true;
    14.         }
    15.         else
    16.             GUILayout.HorizontalSlider(audio.time, 0, audio.clip.length);
    17.         GUILayout.EndArea();
    18.         if (UpdateAudioTime  Input.GetMouseButtonUp(0)) audio.time = sliderPos;
    19.     }
    20. }
    EDIT: Almost exactly, like iTunes. It still keeps playing when you drag, and jumps to the new time on mouseup. I tried pausing during the drag, but when I started playing again, it replayed what was left in the buffer and then jumped to the new time.
     
  11. Jessy

    Jessy

    Joined:
    Jun 7, 2007
    Posts:
    7,325
    Did you try building the project? This is behavior I always get in the editor. (See my second-to-last post.)

    Anyway, thanks for the nice, simple solution. I'll try to implement it asap!


    Later...
    I need this code to work only when dragging in the slider rectangle. This last example works if the slider is the only control. Otherwise, I need to figure out if I'm mousing over the correct control.