Difference between revisions of "State"

From Second Life Wiki
Jump to navigation Jump to search
m
(Replaced Rand Linden's comment with the latest test of the operation.)
 
(24 intermediate revisions by 12 users not shown)
Line 1: Line 1:
{{Multi-lang}}
{{LSL Header|ml=*}}
{{LSL Header}}
{{RightToc}}
<div style="float:right">__TOC__</div>
<div id="box">
<h2>Description</h2>
<div style="padding: 0.5em">
In LSL, most scripts sit idle until they receive some input, or detect some change in their environment. At any moment, the script is in some state, and will react to events or inputs according to some scheme defined by the programmer. However, a script can also contain two or more different states, and react differently to events or inputs depending on what state it is in.
In LSL, most scripts sit idle until they receive some input, or detect some change in their environment. At any moment, the script is in some state, and will react to events or inputs according to some scheme defined by the programmer. However, a script can also contain two or more different states, and react differently to events or inputs depending on what state it is in.


The main state is the default state. When a script is compiled, reset or loaded, this is the state it enters by default. After the default state definition can follow additional state definitions which the script may use to change how and which events are handled.
The main state is the '''default''' state. When a script is compiled, reset or loaded, this is the state it enters by default. A script will '''NOT''' automatically re-enter the default state state_entry event when the task is rezzed or attached (even by a new owner), nor if the task is moved to another SIM, nor on SIM restart.
{{#vardefine:name|state
 
}}{{#vardefine:p_jump_state_desc|name of a state to run
After the default state definition, additional state definitions may follow, which the script may use to change how and which events are handled.
}}{{#vardefine:p_label_state_desc|state name
</div>
}}{{#vardefine:p_events_desc|one or more {{LSLGC|Events|events}}
</div>
}}{{#vardefine:header_title|default { {{LSL Param|events}} }
{{#if:
}}{{#vardefine:header_text|{{{!}}
 
{{#vardefine:name|state}}
 
{{#vardefine:p_jump_state_desc|name of a state to run}}
{{#vardefine:p_label_state_desc|state name}}
{{#vardefine:p_events_desc|one or more {{LSLGC|Events|events}}}}
 
{{#vardefine:header_title|default { {{LSL Param|events}} } }}
{{#vardefine:header_text|{{{!}}
{{LSL DefineRow|event|events|{{#var:p_events_desc}}}}
{{LSL DefineRow|event|events|{{#var:p_events_desc}}}}
{{!}}}
{{!}}}
The default state definition.
The default state definition.
}}{{#vardefine:constants_nb|
}}
 
{{#vardefine:constants_nb|
<div id="box">
<div id="box">
<h2>state {{LSL Param|label_state|target}} { {{LSL Param|events}} }</h2>
<h2>state {{LSL Param|label_state|target}} { {{LSL Param|events}} }</h2>
Line 22: Line 34:
{{LSL DefineRow|event|events|{{#var:p_events_desc}}}}
{{LSL DefineRow|event|events|{{#var:p_events_desc}}}}
{{!}}}
{{!}}}
'''target''' state definition.
{{LSLP|target}} state definition.
</div>
</div>
</div>
</div>
{{!}}-
{{!}}
<div id="box">
<div id="box">
<h2>state {{LSL Param|jump_state|target}};</h2>
<h2>state {{LSL Param|jump_state|target}};</h2>
Line 40: Line 50:
</div>
</div>
</div>
</div>
}}{{#vardefine:examples|
}}
<pre>
 
{{#vardefine:examples|
<source lang="lsl2">
default
default
{
{
     touch_start(integer a)
     state_entry()
    {
        llSay(0,
            "You either just saved the script after editing it"
            + "\nand/or the script (re)entered the default state.");
 
        // white and opaque text
        llSetText("Click to change states", <1.0, 1.0, 1.0>, (float)TRUE);
    }
 
    touch_end(integer num_detected)
     {
     {
         state hello;
         // Note: NEVER do a state change from within a touch_start event -
        // - that can lead to the next touch_start on return to this state to be missed.
        // Here we do the state change safely, from within touch_end
        state two;
    }
 
    state_exit()
    {
        llSay(0, "The script leaves the default state.");
     }
     }
}
}


state hello
state two
{
{
     state_entry()
     state_entry()
     {
     {
         llOwnerSay("Hello");
         llSay(0, "The script entered state 'two'");
         state default;
         state default;
     }
     }
     state_exit()
     state_exit()
     {
     {
         llOwnerSay("Goodbye");
         llSay(0, "The script leaves state 'two'");
     }
     }
}
}
</pre>
</source>
}}{{#vardefine:notes|
* '''[http://www.youtube.com/watch?v=49vj9HEI2OY/Basic Tutorial on States, Events, and Functions]
}}{{#vardefine:caveats|*On state change:
}}
 
{{#vardefine:notes|{{#var:notes}}
* To avoid dumping previously queued events, consider moving the [[state]] ''target'' command to the [[timer]] event, and calling it with [[llSetTimerEvent]]( 0.01 ), then stopping the timer in [[state_entry]] of the new [[state]]. Do NOT use [[state_exit]] if this is a concern.
}}
 
{{#vardefine:caveats|*On state change:
**All [[listen]]s are released.
**All [[listen]]s are released.
**The event queue is cleared
**The event queue is cleared. (see [[#Notes|Notes]] for a partial workaround)
**[[llSensorRepeat|Repeating sensors]] are released.
**The [[llSetTimerEvent|timer event clock]] is '''not''' cleared.
**This means if the new state has a timer event, and the previous state has a timer set, the timer event in the new state will be triggered on the interval set in the previous state.
*The ''default'' state must be defined before all others.
*The ''default'' state must be defined before all others.
*States cannot have user functions or variables inside their immediate scope, only event definitions may be inside a states scope.
*States cannot have user functions or variables inside their immediate scope, only event definitions may be inside a states scope.
}}{{#vardefine:helpers|
*User-defined (global) functions cannot change a script's state. The compiler will throw the error 'ERROR: Global functions can't change state'.  However, a workaround can be used by putting the state change in the body of a simple 'if' statement; one which is without an 'else' clause (Ex: '''if (condition) state Two;''' rather than '''if (condition) state Two; else state default;'''). Rand Linden has previously stated that this workaround is no longer valid, so care should be taken in using it, and preparations made for the sudden removal of this bugfeature.
}}{{#vardefine:also_header|<h3>Keywords</h3>
}}
 
{{#vardefine:helpers|}}
 
{{#vardefine:also_header|<h3>Keywords</h3>
{{{!}}
{{{!}}
{{LSL DefineRow||[[jump]]|}}
{{LSL DefineRow||[[jump]]|}}
{{LSL DefineRow||[[return]]|}}
{{LSL DefineRow||[[return]]|}}
{{!}}}
{{!}}}
}}{{#vardefine:also_footer|
}}
}}{{#vardefine:also_functions|
 
}}{{#vardefine:also_events|
{{#vardefine:also_footer|}}
 
{{#vardefine:also_functions|}}
 
{{#vardefine:also_events|
{{LSL DefineRow||[[state_entry]]|}}
{{LSL DefineRow||[[state_entry]]|}}
{{LSL DefineRow||[[state_exit]]|}}
{{LSL DefineRow||[[state_exit]]|}}
}}{{#vardefine:also_articles|
}}
}}{{#vardefine:also_tests|
 
}}{{#vardefine:location|
{{#vardefine:also_articles|}}
}}{{LSL Generic}}{{LSLC|Flow Control|3={{#var:lang}}}}{{LSLC|Script|3={{#var:lang}}}}
 
{{#vardefine:also_tests|}}
 
{{#vardefine:location|}}
 
}}{{LSL Generic}}{{LSLC|Flow Control|3={{#var:lang}}}}{{LSLC|Script|3={{#var:lang}}}}{{LSLC|State|3={{#var:lang}}}}

Latest revision as of 11:57, 14 June 2020

Description

In LSL, most scripts sit idle until they receive some input, or detect some change in their environment. At any moment, the script is in some state, and will react to events or inputs according to some scheme defined by the programmer. However, a script can also contain two or more different states, and react differently to events or inputs depending on what state it is in.

The main state is the default state. When a script is compiled, reset or loaded, this is the state it enters by default. A script will NOT automatically re-enter the default state state_entry event when the task is rezzed or attached (even by a new owner), nor if the task is moved to another SIM, nor on SIM restart.

After the default state definition, additional state definitions may follow, which the script may use to change how and which events are handled.

The correct title of this article is state. The initial letter is shown capitalized due to technical restrictions.

default { events }

default { events }
• event events one or more events

The default state definition.

state target { events }

• label target state name
• event events one or more events

target state definition.

state target;

• label target name of a state to run

When a state target; is encountered at runtime, if the current state and the target state are different:

  1. Trigger state_exit in the current state if it exists and clear the event queue.
  2. Change state to target, any listens are unregistered.
  3. Trigger state_entry in the target state if it exists.

If target state is the same as the current state, no state change occurs nor do any of the side effects.

Caveats

  • On state change:
    • All listens are released.
    • The event queue is cleared. (see Notes for a partial workaround)
    • Repeating sensors are released.
    • The timer event clock is not cleared.
    • This means if the new state has a timer event, and the previous state has a timer set, the timer event in the new state will be triggered on the interval set in the previous state.
  • The default state must be defined before all others.
  • States cannot have user functions or variables inside their immediate scope, only event definitions may be inside a states scope.
  • User-defined (global) functions cannot change a script's state. The compiler will throw the error 'ERROR: Global functions can't change state'. However, a workaround can be used by putting the state change in the body of a simple 'if' statement; one which is without an 'else' clause (Ex: if (condition) state Two; rather than if (condition) state Two; else state default;). Rand Linden has previously stated that this workaround is no longer valid, so care should be taken in using it, and preparations made for the sudden removal of this bugfeature.

Examples

default
{
    state_entry()
    {
        llSay(0,
            "You either just saved the script after editing it"
            + "\nand/or the script (re)entered the default state.");

        // white and opaque text
        llSetText("Click to change states", <1.0, 1.0, 1.0>, (float)TRUE);
    }

    touch_end(integer num_detected)
    {
        // Note: NEVER do a state change from within a touch_start event -
        // - that can lead to the next touch_start on return to this state to be missed.
        // Here we do the state change safely, from within touch_end
        state two;
    }

    state_exit()
    {
        llSay(0, "The script leaves the default state.");
    }
}

state two
{
    state_entry()
    {
        llSay(0, "The script entered state 'two'");
        state default;
    }

    state_exit()
    {
        llSay(0, "The script leaves state 'two'");
    }
}

Notes

See Also

Keywords

•  jump
•  return

Events

•  state_entry
•  state_exit