Jump to content

Hiding and showing prims and glow (Part II)


Sion Pearl
 Share

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

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

Recommended Posts

Darkie Minotaur, in this previous thread, helped me out no end and I got an amazing script that, with no lag or anything, makes stuff proper vanish when you touch the object, and do it well and efficiently, which is important, given that there are popular clothes makers (naming no names) who still insist on scripting stuff so that you have like thirty prims, all listening on maybe /1 with scripts running in every single one!

But I thought, I have four items now (visor, collar, bracelets), and they've all got similar glowy bits that I might want to turn on and off and while I love that I can touch them and they go zap and vanish, having the four items listening on say, /9, and typing /9 show or /9 hide and having them all go at once would be awesome; likewise, being able to turn on or off one at at a time is also great.

So, here is my very first attempt at proper script construction, made by colliding Darkie Minotaur's script with rules gleaned from an exemplar I found on an online repository.

 

 

//This is a collision of lines from some online library and Darkie Minotaur's awesome script. Please tell me if it's going to work!  

integer giVisible = 1;

switchVisible(vector col, float glow, float alpha) {
    integer i;
    for(i = 1; i <= llGetNumberOfPrims(); ++i) {
        if (llSubStringIndex(llList2String(llGetLinkPrimitiveParams(i, [PRIM_NAME]), 0), "glow") > -1) {
            llSetLinkPrimitiveParams(i, [PRIM_GLOW, -1, glow, PRIM_COLOR, -1,col, alpha]);
            
        }
        
    }
}

default
{
state_entry(){
        llListen(9, "","", "" );
}
     listen(integer channel, string name, key id, string text)
    {
        if(text=="hide"){
            switchVisible(<1, 1, 1>, .15, 0.4);
                         }
        if(text=="show"){
            switchVisible(<1, 1, 1>, 0, 0.0);
         }     
         giVisible = !giVisible;
    }
touch_end(integer num_detected) {
         if(giVisible == 0) {
             switchVisible(<1, 1, 1>, .15, 0.4);    
         } else {
             switchVisible(<1, 1, 1>, 0, 0.0);    
         }
         giVisible = !giVisible;
    }
    
    attach(key id) {
        switchVisible(<0, 0, 0>, 1.0, 1.0);
        giVisible = 1;
    }
}

 

 

By the way, just so you know it's not all theoretical, these are the items I am talking about, as modelled by my avie: the visor is invisible, but you can still see the head gems that are also part of the attachment. Likewise the shiny metal collar and wristbands stay when the glowy bits vanish.

gravesmashup

And here's the visor when it's on:

avie.jpg

  • Like 1
Link to comment
Share on other sites

Welcome back :-) Glad I'm not too late this time.  A few of things:

Optional: llListen(9, "", "", ""); lets anyone command your attachments to toggle on/off.  If this is not what you want then llListen(9, "", llGetOwnerKey(), ""); will restrict it to just you.

Important-ish: in the listen() event-handler you set giVisible = !giVisible; whatever the command.  If this is "hide" you should use giVisible = 1; and if "show" use giVisible = 0; otherwise the touch-toggle will get out of step with the chatted commands.  You could, for instance, get the command "hide" twice in a row which will work but shouldn't toggle the global variable, just set it.

Bit I just don't understand: Why are the settings in the attach() event-handler different to the show/hide ones?  I take it there's a reason, but it's not obvious just from the script.

ETA: Oops - I forgot.  You may want other people to be able to touch your attachments to toggle them but if not wrap all the touch_start() stuff inside a if(llDetectedKey(0) == llGetOwner()){ ... } block.  Does the same thing as changing the listen

@ Darkie - ok, you beat delivered first this time but I want 75% of that L$0 because you only provided a short answer.  PS: read the comment line at the top of Sion's script :smileytongue:

  • Like 1
Link to comment
Share on other sites

Thanks, guys! ;


PeterCanessa Oh wrote:Bit I just don't understand: Why are the settings in the attach() event-handler different to the show/hide ones?  I take it there's a reason, but it's not obvious just from the script.

This is because I do not know what I am doing. So the settings should be the same, right?

I am not one who relly knows how these scripts work beyond the most general theory. Not a newb to building, compleat newb to scripting.

 

Link to comment
Share on other sites


Sion Pearl wrote:

So the settings should be the same, right?

 

You've worked out your different 'show' and 'hide' settings and put them in your listen and touch event-handlers.  That's fine.  I would have thought you would want either of those settings in your attach() too, that's all.  As you have it the visible-glowy things will look completely different when you first wear them (that's when the attach event is raised).

It's not terribly important though - they'll only look different until you chat /9 show or hide.  Don't sweat it, one step at a time is the way to work it all out.

Link to comment
Share on other sites

D'oh! Of course!

So. How does this look?

 

//This is a collision of lines from some online library and Darkie Minotaur's awesome script. Please tell me if it's going to work!  

integer giVisible = 1;

switchVisible(vector col, float glow, float alpha) {
integer i;
for(i = 1; i <= llGetNumberOfPrims(); ++i) {
if (llSubStringIndex(llList2String(llGetLinkPrimitiveParams(i, [PRIM_NAME]), 0), "glow") > -1) {
llSetLinkPrimitiveParams(i, [PRIM_GLOW, -1, glow, PRIM_COLOR, -1,col, alpha]);

}

}
}

default
{
state_entry(){
llListen(9, "",llGetOwner(), "" );
}
listen(integer channel, string name, key id, string text)
{
if(text=="hide"){
switchVisible(<1, 1, 1>, .15, 0.4);
}
 giVisible = 1;
if(text=="show"){
switchVisible(<1, 1, 1>, 0, 0.0);
}
giVisible = 0;
}
if(llDetectedKey(0) == llGetOwner())
{
touch_end(integer num_detected) {
if(giVisible == 0) {
switchVisible(<1, 1, 1>, 0.15, 0.4);
} else {
switchVisible(<1, 1, 1>, 0.0, 0.0);
}
giVisible = !giVisible;
}

attach(key id) {
switchVisible(<1, 1, 1>, 0.0, 0.0);
giVisible = 1;
}
}
}

 

 

Link to comment
Share on other sites

I sorted some brackets, set a few things straight and added a few comments, so you can see what I did and why - I hope this works as you want it

 

//This is a collision of lines from some online library and Darkie Minotaur's awesome script. Please tell me if it's going to work!  

integer giVisible = 1;

switchVisible(vector col, float glow, float alpha) {
    integer i;
    for(i = 1; i <= llGetNumberOfPrims(); ++i) {
        if (llSubStringIndex(llList2String(llGetLinkPrimitiveParams(i, [PRIM_NAME]), 0), "glow") > -1) {
            llSetLinkPrimitiveParams(i, [PRIM_GLOW, -1, glow, PRIM_COLOR, -1,col, alpha]);
            
        }
        
    }
}

default
{
    state_entry(){  
        llListen(9, "",llGetOwner(), "" );
    }
    
    listen(integer channel, string name, key id, string text) {
        if(text=="hide"){
            switchVisible(<1, 1, 1>, .15, 0.4);
            giVisible = 1; //it's ok - but you could have done the same as in the touch event: giVisible = !giVisible
        }
        if(text=="show"){
            switchVisible(<1, 1, 1>, 0, 0.0);
            giVisible = 0;
        }              
    }

    touch_end(integer num_detected) {
        if(llDetectedKey(0) == llGetOwner()) { //the if has to go insider the touch event
            if(giVisible == 0) {
                switchVisible(<1, 1, 1>, 0.15, 0.4);
            } else {
                switchVisible(<1, 1, 1>, 0.0, 0.0);
            }
            giVisible = !giVisible;
        }
    }
    
    attach(key id) {
        switchVisible(<1, 1, 1>, 0.0, 0.0); //if you set the gear invisible on attach, giVisible should be 0, not 1; if you want it visible,
                                            //the function call should be switchVisible(<1, 1, 1>, 0.15, 0.4);
        giVisible = 0;
    }
}

 

 

  • Like 1
Link to comment
Share on other sites

and now since it looks like you three are done (I hope) here's the same script with optimizations and simplifications, to take it a step or two further in the learning process (if it makes no sense, ask, if it it still makes no sense, that's ok, because it's meant to be a bit more advanced)

//-- Void's Edit

integer giVisible; //-- default off

switchVisible(){
giVisible = !giVisible;
integer i = llGetNumberOfPrims();
//-- use a count down loop instead of a 1 to X loop to save a variable
do{
//-- PRIM_NAME is ok, but why not PRIM_DESC ? it would let you name the parts AND still glow individual parts
//-- (~llSubStringIndex()) same effect as (llSubStringIndex() > -1)
//-- (string)llGetLinkPrimitiveParams( i, [PRIM_NAME] ) == llList2String( llGetLinkPrimitiveParams( i, [PRIM_NAME] ), 0 )
//-- testing if the string is anywhere in the text is kinda dangerous, cause it could be... anywhere
//-- instead, you might want to test if it starts with the string, or if it's in a certain spot, but I've left it alone here

if (~llSubStringIndex( (string)llGetLinkPrimitiveParams( i, [PRIM_NAME] ), "glow" )){
//-- we stuck all the variables in here since the same ones are used every time, and then multiply them by the hide/show value
llSetLinkPrimitiveParams( i, [PRIM_GLOW, ALL_SIDES, 0.25 * giVisible, PRIM_COLOR, ALL_SIDES, <1.0, 1.0, 1.0>, 0.4 * giVisible ]);
}
}while (--i);
//-- considered using a list of prim numbers, built in the changed event, but changing the name of a prim does not fire a changed event
}

default{
state_entry(){
llListen( 9, "", llGetOwner(), "" );
}

listen( integer channel, string name, key id, string text ){
//-- reuse channel for a test integer and check to make sure we got a valid command
//-- make sure to strip extra spaces and lowercase the text in case the user added a space, or capitalized
//-- (~channel) == (channel != -1)... if we get a command that we don't know, it will be -1
//-- other wise we get FALSE/TRUE to test against our current cisibility and only change if it's different

if (~channel = llListFindList( ["hide", "show"], [llToLower( llStringTrim( text, STRING_TRIM ) )] )){
if (channel != giVisible){
switchVisible();
}
}
}

touch_end( integer num_detected ) {
if (llDetectedKey(0) == llGetOwner()){
//-- this should really have an if that checks the name of the touched part,
//-- and if it's a certain part THEN switch visibility.

switchVisible();
}
}

attach( key id ){
//-- this is actually kinda sloppy since it will fire on detach AND attach
//-- but it lets it start going invisible before it gets attached, so
//-- the speed is a bonus

if (giVisible){
switchVisible();
}
//-- however, the on_rez event might be a better choice, if you use
//-- !!llGetAttached(), so that you can make everything visible if
//-- the object is rezzed to the ground (as people often do for editing)

}
}

 

the idea here isn't to show anyone up (I'm pretty sure everyone helping was keeping things simple), but to demonstrate for the people who are at the simpler level what improvements can or might be made =)

  • Like 1
Link to comment
Share on other sites

according to some folks that type of parameter reuse is actually a violation of good practice. (and a step towards the REAL violation of good practice that Strife and I cooked up for those unsigned integer functions a while back)

reason? because it doesn't let you just drop in other code that might look for the channel (for instance to send information back on the same channel), so it violates the expectation of what data is in that variable.

technically the same is true if you use the
do{ --num_detected; }while (num_detected);
loop structure to process detection events, since it destroys your ability to know how many detections there were...

 

to which I say, if you needed that you should have either A) processed that first (applies to both), or B) processed them inside the loop (applies to the seond only)

Link to comment
Share on other sites

those rules are designed for environments where the line count is much larger, and multiple programmers are looking at the same code, or there's a chance that the person who wrote it isn't going to be the same as the person who has to port it to a different language.... the idea is to make it as generic and easily modifiable as possible in those environments, to save time for other people so they don't have to back track the usage of a (supposedly) well understood variable before using it.

those things can happen in LSL but are exceedingly unlikely compared to other languages, due to factors like size, ownership, and specificity.

Link to comment
Share on other sites

@ Darkie - "giVisible = 1; //it's ok - but you could have done the same as in the touch event: giVisible = !giVisible" - that's a change I recommended Sion make as otherwise the touch() and listen() event-handlers could get out of step.  Touch() is always toggling things on/off but listen() is responding to a specific command, which may not be a change at all if, for instance, things are currently hidden and then "hide" is chatted.

@Void - nice as always :-) Yes, I didn't want to suggest more than necessary changes but the "right" version is always good to see.  I quite frequently re-use variables, partly to save memory and partly so SL doesn't have to initialise another one.  This is the temptation you earlier resisted, I take it? :-) I also appreciate your nPose joke now and apologise that I missed it completely first time :-)

Link to comment
Share on other sites

 


PeterCanessa Oh wrote:

@Void -

[...]

This is the temptation you earlier resisted, I take it? :-)

[...]

yup.... I had a feeling that it might go farther, and that it would be kept simple for OP (good things), so I didn't want to rush in before there was something to solid to build on. (I did that recently to Rolig, and I feel kinda bad about it, because it might leave the impression that I was trying to "one up" her)

 

Link to comment
Share on other sites

 


Void Singer wrote:

 yup.... I had a feeling that it might go farther, and that it would be kept simple for OP (good things), so I didn't want to rush in before there was something to solid to build on. (I did that recently to Rolig, and I feel kinda bad about it, because it might leave the impression that I was trying to "one up" her)

 

 

Nah.  Don't give that a second thought, Void. I can have a thin skin sometimes, but not when I get a good constructive comment and certainly not when there's something cool to learn. I don't know whether it shows to anyone else, but my scripting feels like it's a lot tighter and cleaner as I have paid attention to your feedback and good examples.  Keep 'em coming. 

(I hope nobody else ever feels that I'm trying to "one up" them either, BTW. I just love getting into the mix when we can get several solutions going for the same problem. )

Link to comment
Share on other sites

 


Sion Pearl wrote:

I tried it, and it doesn't work - SL tells me there's a syntax error in the line that goes:

 
    }while (--1);

 Yeah. 
Get rid of the curly bracket at the start of the line.  It duplicates the one on the previous line.  :smileywink:

ETA:  Ooops.  Never mind.  Misread the brackets. The error is here >>>  it should be
while (--i);

 

  • Like 1
Link to comment
Share on other sites

good catch... the "1" should have been an "i" (I must have done that while I was adding all the color codes), I also double checked and caught a miscapitalized function call. but all are corrected and test now.

(one day I'll learn to paste code into the viewer for a quick compile double check....)

but good on you that you pulled the the line that error was on (I know we all wish more people that post would do that and/or understand what that means)

PS the brackets are fine... do{ }while (); is an underused, but very useful loop construct (seems everyone like "for" better)

Link to comment
Share on other sites

I noticed that - I'd never seen a do... while loop before. In simple terms, what's the advantage?

Although I can see that your script is a bit shorter (which must mean it's more efficient right there. But is a shorter script a faster one? I don't actually know this stuff).

(I'm at work now, so I can't check on this until lunchtime, but I'll totally have a go at sticking it in now it's fixed.)

Oh, and I started on HTML and CSS for my job years and years ago and while I never really got beyond basic javascript, I learned to appreciate that identifying the point where it breaks makes all the difference, even if you don't actually understand why it breaks there. :robothappy:

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4768 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...