//  StopWatch
//  Created by Water Rogers for IBM/Opensource
 
//  Purpose
//  --------------------------------------------------------------
//  This is a basic example of how you can create a stopwatch.
//  
 
//  Requirements
//  --------------------------------------------------------------
//  A single prim is all that is necessary for this example.
 
//  Usage
//  --------------------------------------------------------------
//  Touch the object to toggle the timer off/on
//  type "reset" to reset the timer.  Not case-sensitive.
 
//  GLOBAL VARIABLES
//  --------------------------------------------------------------
 
integer g_Seconds   = 0;        //  Globaly store the Seconds
integer g_Minutes   = 0;        //  Globaly store the Minutes
integer g_Hours     = 0;        //  Globaly store the Hours
integer g_Ticking   = FALSE;    //  Toggles the timer off/on
vector  g_TextColor = <1,1,1>;  //  Text color for the timer. <1,1,1> = White
 
//  FUNCTIONS
//  --------------------------------------------------------------
 
//  This is a simple function to zero pad the numbers 2 spaces to make
//  the timer look more authentic.  It takes an integer as an argument
//  and outputs a string.
string zero_pad(integer number)
{
    if(number < 10) return "0" + (string)number;
    return (string)number;
}
 
//  EVENTS
//  --------------------------------------------------------------
 
default
{
    state_entry()
    {
        //  ------------------------------------------------------
        //  This is the entry-point of the script.  After a script
        //  has been saved or reset, this event will fire off first
        //  ------------------------------------------------------
 
        //  We call llSetText() first to reset the text above the object
        //  back to 00:00:00 time.
        llSetText("00:00:00", g_TextColor, TRUE);
 
        //  Set up a listener so that we can reset the timer by typing
        //  "reset".  This particular listener will listen to any chat
        //  typed by anyone (or any object)
        llListen(0, "", "", "");
 
        //  Finally, we set up a timer that will repeat itself every
        //  g_Ticking seconds.  Since g_Ticking could only ever possibly
        //  equal 0 or 1, we can use this to our advantage in optimizing.
        //  This particular example is not necessary, but can have a
        //  dramatic impact on larger scripts.  Note that setting a timer
        //  to 0 (False) will indeed turn off the timer.
        llSetTimerEvent(g_Ticking);
    }
 
    touch_start(integer num_detected)
    {
        //  If someone touches the object, it will toggle the timer off/on
 
        //  We can avoid using if/else statements here because of the
        //  nature of our timer.  Using an exclamation in front of the
        //  variable "flips" the bits.  In this case, our variable is either
        //  only ever TRUE (1) or FALSE(0).  Since we need the timer to
        //  tick each second, this becomes a nice optimization method.
        g_Ticking = !g_Ticking;
        llSetTimerEvent(g_Ticking);
 
    }
 
    listen(integer channel, string name, key id, string message)
    {
        //  This event is fired off whenever anyone chats around the object
        //  and a proper listener is set up, such as in state_entry()
 
        //  We take the message and make it all lowercase so that the word
        //  "reset" is not case-sensitive
        message = llToLower(message);
        if(message == "reset")
        {
            //  The filter determined that the word "reset" was typed.  So
            //  we need to reset everything back to 0, and turn the timer off
            g_Ticking = FALSE;
            llSetTimerEvent(0);
            llSetText("00:00:00", g_TextColor, TRUE);
            g_Seconds = 0; g_Minutes = 0; g_Hours;
        }
    }
 
    timer()
    {
        //  This event fires off each second because the integer 1 is being
        //  passed as the argument for seconds in llSetTimerEvent(float seconds)
 
        //  Incriment the global Seconds variable by 1
        g_Seconds++;
 
        //  If seconds are at 60, then we've just made a minute
        if(g_Seconds >= 60)
        {
            //  So we increment the global minutes by 1, and reset the seconds.
            g_Minutes++;
            g_Seconds = 0;
 
            //  If the minutes are at 60, then we've just made an hour
            if(g_Minutes >= 60)
            {
                //  Increment the global hours by 1, and reset the minutes.
                g_Hours++;
                g_Minutes = 0;
            }
        }
 
        //  Display everything above the object.  Notice the use of the zero_pad()
        //  function that we created earlier to make the timer look better.
        llSetText(zero_pad(g_Hours) + ":" + zero_pad(g_Minutes) + ":" + zero_pad(g_Seconds), g_TextColor, TRUE);
    }
}