Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Event handling durint an endless while loop

TiGuy Goalpost
Registered User
Join date: 18 Nov 2006
Posts: 12
02-03-2008 18:18
Hi,

I'm new with scripting... so please forgive me if my question is stupid. The task is simple, I want to click on a prime and it starts rotating endlessly and if I click on it again it stops. I also programmed a "listen" so I can start or stop the rotation by a command on the chat ("/10000 Starts" or "/10000 Stop";). It works fine to start the rotation, but it doesn't work when I want to stop it. I use a "while(1)" loop, to fire the llSetRot() function and it looks like the events aren't captured during a while loop.

Here is the script:
The formating of the code is ugly here, because of the narrow text window, but if you cut and paste it into a text window with around 135 chars width, it will display correctly.
// ************************************************************************************************************************** //
// TiGuy's Flare Controler V1.1 //
// //
// Programmer : TiGuy GoalPost //
// Initial release: February 2008 //
// //
// The script is very simple. On startup, it forces the rotating part of the flare to a "stopped" state. On touch, it //
// will start rotating the light beams. //
// //
// Possible improvements: //
// - The rotation should stops on touch. It's supposed to stop rotating if we touch it again, but it just doesn't work //
// and I don't have a clue why. 8-( //
// - When the flare stops rotating, the yellow light beam should fade out and disapear, and the light bulb should be turned//
// white or a very light yellow. I suspect that the visual effect would be great. //
// - It could be useful to implement a "locked" state in which only the owner can control the flare. //
// //
// ************************************************************************************************************************** //

// Global variables definitions
string gScriptVersion = "Flare Controler V1.1";
integer gCommandChatChannel = 10000; // The chat channel that will be used to pass commands to the flare
string gStartCommand = "Start"; // The keyword to say on the command chat channel to start the flare
string gStopCommand = "Stop"; // The keyword to say on the command chat channel to stop the flare
integer gPublicChatChannel = 0;
integer gRotationIncrement = 10; // How many degre of rotation in each increment when rotating the light beam
integer gForever = TRUE; // Used to force endless loop



// ***************************************************************************************************************************//
// DEFAULT STATE //
// ************************************************************************************************************************** //
// This is the default state, this piece of code will be executed on the startup of the script
default
{
// The state_entry event code is executed once, when the default state starts
// By default when we rez the flare or reset the script, the flare is forced in the "Stopped" state
state_entry()
{
llSay(gPublicChatChannel,gScriptVersion + " is starting";);
state Stopped;
}


}



// ***************************************************************************************************************************//
// STATE RUNNING //
// ************************************************************************************************************************** //
state Running
{
// the state_entry code is executed when the state "Running" starts
state_entry()
{
// Start listening on the command chat channel. If something is said on that channel, the "listen" event
// will be executed.
integer ListenHandle = llListen(gCommandChatChannel, "", llGetOwner(), gStopCommand);
llOwnerSay("Say " + gStopCommand + " on channel " + (string)gCommandChatChannel + " to stop the flare.";);

llSetTouchText("Stop";); // Set the text for the "touch" item of the pie menu
vector DegreAngleOffset = <0,0,gRotationIncrement>; // Set the increment of the rotation
vector RadianAngleOffset = DegreAngleOffset*DEG_TO_RAD; // Convert the angle into radians
rotation RotationAngleOffset = llEuler2Rot(RadianAngleOffset); // Convert the angle into a quaternion (default SL rotation)

// rotate the light beam forever
while (gForever)
{
llSetRot(llGetRot()*RotationAngleOffset); // Rotate the light beam
llSleep(0.1);
}
}

// Usually this event should be triggered when an AVI touches the flare, and the script should jump to the "Stopped" state.
// For some reason it does't work.
touch_start(integer Number)
{
state Stopped;
}

// This event is triggered when the script receive a message on the command chat channel. We filter to receive
// only messages from the owner, and only if the message is the stop command. So if we get a message, we assume that
// we need to switch to the "Stopped" state.
listen(integer channel, string name, key id, string message )
{
state Stopped;
}

}



// ***************************************************************************************************************************//
// STATE STOPPED //
// ************************************************************************************************************************** //
state Stopped
{
state_entry()
{
// Start listening on the command chat channel. If something is said on that channel, the "listen" event
// will be executed.
integer ListenHandle = llListen(gCommandChatChannel, "", llGetOwner(), gStartCommand);
llOwnerSay("Say " + gStartCommand + " on channel " + (string)gCommandChatChannel + " to start the flare.";);
llSetTouchText("Start";); // Set the text for the "touch" item of the pie menu
}

// while in the "Stopped" state, if an AVI touch the light beam, the script jump to the "Running" state and starts
// rotating.
touch_start(integer Number)
{
state Running;
}

// This event is triggered when the script receive a message on the command chat channel. We filter to receive
// only messages from the owner, and only if the message is the start command. So if we get a message, we assume that
// we need to switch to the "Running" state.
listen(integer channel, string name, key id, string message )
{
state Running;
}
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
02-03-2008 18:24
That's correct. Each script is essentially single-threaded. One event handler cannot fire while another is still executing. Instead certain events queue up until the current handler is done. Better than a tight while loop would be a short-period timer event used to execute each "iteration". The complicated part is that you have to maintain state between iterations with global variables and other methods, rather than simple local stack-allocated variables. You'll probably want a timer period that is a little over the imposed script delay for llSetPos() or whatever combination of functions you are using. For llSetPos() and llSetPrimitiveParams() this is 0.2, so something like 'llSetTimerEvent(0.25);' would probably work well.
Destiny Niles
Registered User
Join date: 23 Aug 2006
Posts: 949
02-03-2008 18:36
You are not using the right function for what you want. What you want to use is the llTargetOmega function. This will rotate an object forever without the while function.
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-03-2008 19:11
assuming controlled rotation and a setup similar to hewees

CODE

vector gVecSpinDegrees = <0.0, 0.0, 6.0>;
rotation gRotSpin;

default{
state_entry(){
gRotSpin = llEuler2Rot( gVecSpinDegrees * DEG_TO_RAD );
}

touch_start( integer vIntNull ){
state sMoving;
}
}

state sMoving{
state_entry(){
llSetTimerEvent( 0.3 );
}

touch_start( integer vIntNull ){
llSetTimerEvent( 0.0 )
state default;
}

timer(){
llSetRot( gRotSpin * llGetRot );
}
}


I chose to do it in 2 states to prevent any extra firing of the timer event after the touch is processed, not really necessary in this case, but in iteration controlled timer loops it's one of three ideas that will prevent the loop possibly being qued an extra time (the other is a global boolean to control excution, to prevent extra processing, or checking the loop count, before processing, both of which might still queue but short circuit excuting the code)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Qie Niangao
Coin-operated
Join date: 24 May 2006
Posts: 7,138
02-03-2008 19:53
Just for completeness (and because by coincidence somebody asked me the same question in-world today), it is possible to interrupt an infinite loop by having another script call llResetOtherScript() on the looping script. (It doesn't interrupt a library call: if, for example, the loop has a big llSleep in it, the reset takes place after the sleep completes.) This is almost never what one wants to do, of course: the reset script loses all state information, so any that has to be preserved would have to be stored in another script and handed back at reset. And it's surely not appropriate for the problem in this thread, but of passing relevance to the subject.
TiGuy Goalpost
Registered User
Join date: 18 Nov 2006
Posts: 12
llTargetOmega is a very simple solution... But it's bugged
02-05-2008 19:11
First thank you all for your answers, very appreciated. I modified my code so it uses llTargetOmega() and it would work fine normally. But The function is bugged (see another recent thread about it). The script works fine, but llTargetOmega() won't start unless we edit the prim and close the edit window. Then it starts... this is a known bug, and we should have a fix at some point so I won't modify my script.

This is how I implemented it in my "Running" state. I do the same thing in the "Stopped" state, but I set a 0 spin/sec speed, which stops the rotation.

state Running
{
// the state_entry code is executed when the state "Running" starts
state_entry()
{
// Start listening on the command chat channel. If something is said on that channel, the "listen" event
// will be executed. We filter messages so we receive only if it's the stop command said by the owner.
integer ListenHandle = llListen(gCommandChatChannel, "", llGetOwner(), gStopCommand);


llOwnerSay("Say " + gStopCommand + " on channel " + (string)gCommandChatChannel + " to stop the flare.";);

// Set the text for the "touch" item of the pie menu
llSetTouchText("Stop";);

// Spin the assembly around the vertical axis at 0.1 rot/sec
llTargetOmega(<0,0,0.1>,TWO_PI,1.0);
}

// This event is triggered when an AVI touches the flare, if it's the owner
// the script jumps to the "Stopped" state.
touch_start(integer Number)
{
if (llGetOwner() == llDetectedKey(Number-1))
{
state Stopped;
}
}

// This event is triggered when the script receive a message on the command chat channel. We filter to receive
// only messages from the owner, and only if the message is the stop command. So if we get a message, we assume that
// we need to switch to the "Stopped" state.
listen(integer channel, string name, key id, string message )
{
state Stopped;
}

}
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-05-2008 20:09
please use php tags

I made some minor changes, safer testing of capitalization and extraneous spacing the listen, and a warning for typos, with an assumption that the stop command will be lowercased (allows it to ignore some user errors like extra spaces and capitalization)

CODE

state Running{
state_entry(){
llListen(gCommandChatChannel, "", llGetOwner(), "");

llOwnerSay("Say " + gStopCommand + " on channel " + (string)gCommandChatChannel + " to stop the flare.");

llSetTouchText("Stop");

llTargetOmega(<0,0,0.1>,TWO_PI,1.0);
}

touch_start(integer Number){
if (llGetOwner() == llDetectedKey( 0 )){
state Stopped;
}
}

listen(integer channel, string name, key id, string message ){
if (llToLower( llStringTrim( message, STRING_TRIM ) ) == gStopCommand){
state Stopped;
}else{ //-- troublshooting message
llOwnerSay( "Did not understand: " + message );
}
}
}


a changed event to detect new owners for the listen might not hurt, but the touch will still work regardless since it tests owner at the time of the touch.

I'll assume the stopped state has a call to target omega setting it to zero. ( I believe the effect persists accross states, if not, ignore that)

looks fine to me, although the last LL server update seems to have borked target omega, and it doesn't seem to always fire (selecting it in edit seems to work, changing the set text after the call may also kickstart it)

be careful in the touch_start event, detected*( 0 ) is the first touch, detected*( num -1 ) is the last, both apply if it's the only touch in the trigger time, but multiples can scew this, and while it's filtering only for the owner, and there's no code processing going on in this script, in other scripts it can be troublesome if you don't loop through all possible touches (especially if you're handling multiple users) see my linked post for details
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
02-05-2008 22:03
From: Void Singer
please use php tags

I've continued to use them, but I'm wondering if there is a point anymore. Links don't show up as links for me, nor does code show up as code. I don't seem to have a forum option for allowing this markup or anything. Is it promised back at some point, or am I missing something, or have I just gotten personally messed up somehow, or...?
Void Singer
Int vSelf = Sing(void);
Join date: 24 Sep 2005
Posts: 6,973
02-06-2008 03:49
From: Hewee Zetkin
I've continued to use them, but I'm wondering if there is a point anymore. Links don't show up as links for me, nor does code show up as code. I don't seem to have a forum option for allowing this markup or anything. Is it promised back at some point, or am I missing something, or have I just gotten personally messed up somehow, or...?

depends, what browser are you using?, there's a link and instructions available through my signature that will allow proper viewing of php tags, and links for firefox and opera users.

but you'll notice the link in my last post is also active, by a little trickery... instead of url tags, use img tags... the only caveat is that the url needs to include a question mark (search string).. if the url doesn't have it just toss one on the end, doesn't hurt anything. any link created this way will be active for anyone.

it aslo doesn't hurt to use the most basic text editing mode for posts, so that quoting them (and editing/previewing) doesn't get auto formated (keeps indents, tags, etc)
_____________________
|
| . "Cat-Like Typing Detected"
| . This post may contain errors in logic, spelling, and
| . grammar known to the SL populace to cause confusion
|
| - Please Use PHP tags when posting scripts/code, Thanks.
| - Can't See PHP or URL Tags Correctly? Check Out This Link...
| -
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
02-06-2008 04:15
Thanks for that hint, Void...

There's a plugin for Safari on Mac as well, called GreaseKit (one needs SIMBL to run this - google for both, you'll find it).

Although I was able to install GK and SIMBL and managed to install Strife's BBCode-Script... it doesn't work... :(

Seems like I have to use Firefox for the forums from now on...

[edit]

Strife's Code not working on Safari might have something to do with the chars-list at the beginning of the script. On a Mac, that reads: const chars = '&à áâãäåæçèéêëìà îïðñòóôõöøùúûüýþÿÀ�ÂÃÄÅÆÇÈÉÊËÌ�Î��ÑÒÓÔÕÖØÙÚÛÜ�Þ€\"ß<>¢£¤¥¦§¨©ª«¬ ®¯°±²³´µ¶·¸¹º»¼½¾€•'

Is this correct or do all the «Â»s mean something else?

P.S. sorry for hijacking this thread :)
Qie Niangao
Coin-operated
Join date: 24 May 2006
Posts: 7,138
02-06-2008 07:23
From: Hewee Zetkin
...nor does code show up as code. ... Is it promised back at some point...?
Even if one doesn't use the greasemonkey script, it can be helpful to have text tagged as code so that using the "Quote" button at least indents it correctly for legibility and cut-and-paste. As for the future... dunno 'bout "promise" but I'd venture that, once the Grand Unified Login thing is working, there will be some likelihood of the vBulletin software getting updated. Otherwise, some of the customization here would have to be redone first for the new version and then for the new authentication scheme. (One might well wonder why it's better to instead do it first for the authentication and then for the version upgrade. :p ) Of course, that's all predicated on the Forums surviving till then. See http://jira.secondlife.com/browse/WEB-448. We do what we can.