Jump to content

Using touch to start AND stop a process


EclecticJohn Niven
 Share

You are about to reply to a thread that has been inactive for 4024 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I think I must be missing something simple.  I want to start a function with the first touch and stop it with a second touch.  I have tried using states, tried using touch_start to start and touch_end to stop, no matter how I code it the 2nd Touch event is not processed until the function is completed.  The script is complex, but my problem is simple.  The script below only sees a 2nd touch event when counting is done.

 

integer interupted = FALSE;
integer counter;
integer iscounting;

counting()
{
            do
            {
                llSay(0,(string) counter + " "   + (string) interupted);
                llSleep(1);
                counter = counter + 1;
            }
            while ((counter < 50) && (interupted == FALSE));
}   

default
{
    state_entry()
    {
        counter = 0;
    }

    touch_start(integer total_number)
    {
        llSay(0,"Touched");
        if (iscounting == FALSE)
        {
            iscounting = TRUE;           

            counting();
        }
        else
            interupted = TRUE;
       
    }
}

 

I have that feeling where you know the answer must be staring you in the face and you can't see it!  Any help will be MUCH appreciated, even if someone tells me that "you can't" and why.  John

Link to comment
Share on other sites

You've got two problems there, I think.   The first is that the loop is going to keep on running (or at least I think it is) until it completes before the script evaluates the second touch.   The second problem is that, if you touch the prim while the script is sleeping (that is, most of the time the loop is running), then the touch won't register anyway.

Try something like this (not tested but it should work)

integer counter;integer iscounting;default{	state_entry()	{		counter = 0;	}	touch_start(integer total_number)	{		iscounting=!iscounting;		if(iscounting){			counter=0;			llSetTimerEvent(1.0);		}		else{			llOwnerSay("Interrupted");			llSetTimerEvent(0.0);		}	}	timer()	{		if(counter< 50){			++counter;			llOwnerSay((string)counter);		}		else{			llSetTimerEvent(0.0);		}	}}

 ETA: using llSleep as quick substitute for a timer is usually not a good idea -- I only use llSleep very rarely and only  if I want to be sure something can't happen until another process has had time to complete.

Link to comment
Share on other sites

You are calling the function counting() from within the touch_start event state and an event cannot interrupt itself. So, the second touch is being queued until the function is finished.

 

Even taking that into account, it will not perform as you wish since you set the variable interrupted to TRUE but it never gets set back to FALSE, which is required for the function counting() to loop again.

 

Use Innula's example, which will do as you expect (though they are mistaken saying that the second touch would be missed while the script is sleeping. It will be queued and processed as soon as [Edited] after the script awakens. http://lslwiki.net/lslwiki/wakka.php?wakka=llSleep&show_comments=1#comments ,  ).

Link to comment
Share on other sites

Is the touch event queued and processed?

I have just tested  with this:

 

integer toggle;default{    state_entry()    {           llSetColor(<.0,0.0,1.0>,ALL_SIDES);     }    touch_start(integer total_number)    {       toggle=!toggle;       if(toggle){           llSetColor(<1.0,0.0,0.0>,ALL_SIDES);        }        else{             llSetColor(<.0,0.0,1.0>,ALL_SIDES);         }        llOwnerSay("Sleeping now");        llSetText("Sleeping",<1.0,1.0,1.0>,1.0);        llSleep(5.0);        llOwnerSay("Waking up");        llSetText("",<1.0,1.0,1.0>,1.0);    }}

 Touching it while it's sleeping has no effect at all -- it only changes colour for me if I touch it while it's awake.   I think that means it's ignoring the touch event.

Link to comment
Share on other sites

A LSL script is a single task process. There is NO multithreading.

Your loop runs 50 seconds and will block everything else for 50 seconds. Events are queued though and listens are cached by the sim and queued so your script will work them off after touch event finishes.

You need to use the timer event for scripts like that and think about it before you use llSleep since it will halt the script while it's active.  Using a 2nd script will work too.

Link to comment
Share on other sites


Innula Zenovka wrote:

Is the touch event queued and processed?

I have just tested  with this:

 
integer toggle;default{    state_entry()    {           llSetColor(<.0,0.0,1.0>,ALL_SIDES);     }    touch_start(integer total_number)    {       toggle=!toggle;       if(toggle){           llSetColor(<1.0,0.0,0.0>,ALL_SIDES);        }        else{             llSetColor(<.0,0.0,1.0>,ALL_SIDES);         }        llOwnerSay("Sleeping now");        llSetText("Sleeping",<1.0,1.0,1.0>,1.0);        llSleep(5.0);        llOwnerSay("Waking up");        llSetText("",<1.0,1.0,1.0>,1.0);    }}

 Touching it while it's sleeping has no effect at all -- it only changes colour for me if I touch it while it's awake.   I think that means it's ignoring the touch event.

That is because you are sleeping within your touch event. Remember- a touch event will not interrupt itself. Try this and see what is happening:

default {    state_entry() {            llOwnerSay ("Going to sleep.");            llSleep (10);            llOwnerSay ("I am awake now.");			llSetTimerEvent(5);    }        touch_end (integer total_number)    {        llOwnerSay ("Touch_end event");    }	    touch_start (integer total_number)    {        llOwnerSay ("Touch_start event");    } 	    touch (integer total_number)    {        llOwnerSay ("Touch event.");    }  	 timer()	 {		llResetScript();	 } }

 Edited code so it will loop without needing to be manually reset.

Link to comment
Share on other sites

I have read with real interest the discussions.  I am afraid I complicated things by trying to "simplify" the example.  This is a Function which I use for window blinds, stage curtains, garage doors and stuff like that.   It raises and lowers by resizing and repositioning.  With trivial changes it can work in the x or y planes.

 

blind_moving()
{
llLoopSound("Blind Moving",15.0);
if (isopen == FALSE)
{
isopen = TRUE;
for (counter = 0; counter < fullopen; ++counter)
{
psize.z = psize.z + startwidth; //psize local to object
pposition.z = pposition.z - (startwidth / 2); //pposition is global
llSetPrimitiveParams([PRIM_SIZE,psize,PRIM_POSITION,pposition]);
}
}
else
{
isopen = FALSE;
for (counter = 0; counter < fullopen; ++counter)
{
psize.z = psize.z - startwidth;
pposition.z = pposition.z + (startwidth / 2);
llSetPrimitiveParams([PRIM_SIZE,psize,PRIM_POSITION,pposition]);
}

}
llStopSound();
}

 

There is no sleep.  If I am reading what Nova said correctly,  once this function is  called, there is no way to interupt until is is finished?    Thanks all for the comments!

Link to comment
Share on other sites

An another way without timer could to be :

- not use touch_start and touch_end events ( or use them only for your loopsound and stopsound)

- use touch event to scale and move your object

- do one iteration of your loop inside the touch event , not the whole loop

- use a conditionnal  to know if you ahve reached the limits of your loop

 

So , while the user lets his mouse button clicked it opens/close the door  ( until a maximum/minimum)  of course.

 

 

Instance : ( with llSetLinkPrimitiveParamsFast , it should be smoother )

 

vector psize;vector pposition;integer counter;float startwidth = 0.25;integer isopen;integer fullopen = 10;integer finished;default{    state_entry()    {        psize = llGetScale();        pposition = llGetPos();            }    touch_start(integer total_number)    {        finished = FALSE;        llLoopSound("Blind Moving",15.0);    }    touch(integer n)    {        if ( ! finished )        {            if (isopen == FALSE)            {                if ( counter >= fullopen )                {                    isopen  = TRUE ;                    finished = TRUE;
counter = 0; } else { counter++; psize.z = psize.z + startwidth; //psize local to object pposition.z = pposition.z - (startwidth / 2); //pposition is global llSetPrimitiveParams([PRIM_SIZE,psize,PRIM_POSITION,pposition]); } } else { if ( counter >= fullopen ) { isopen = FALSE ; finished = TRUE;
counter = 0; } else { counter++; psize.z = psize.z - startwidth; pposition.z = pposition.z + (startwidth / 2); llSetPrimitiveParams([PRIM_SIZE,psize,PRIM_POSITION,pposition]); } } } } touch_end(integer total_number) { llStopSound(); } }

 

 

 

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4024 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...