Holiday Lights and Tree Scripts

Creating scripts
Post Reply
User avatar
Kayaker Magic
Posts: 345
Joined: Sun Dec 01, 2013 8:40 am
Has thanked: 50 times
Been thanked: 365 times

Holiday Lights and Tree Scripts

Post by Kayaker Magic » Wed Nov 19, 2014 11:08 pm

Have a Lag-Free Holidays!

At OSCC I had a booth and (among other things) I had a “poster paper” about making blinking lights for the holidays without bogging down your SIM. Next to that was an example string of 100 lights that blink in patterns controlled by a single low-lag script. And a blinking holiday tree with a similar script for changing texture maps. I'm publishing the scripts here now as a holiday gift to the Open Simulator community in the hopes that it brightens your holiday SIMs!

That booth at OSCC will stay up for a while, so I will leave the lights on for you. And trees there for anyone to grab a full-perm copy for free. Hypergrid to http://cc.opensimulator.org:8002 and find your way to Expo Zone 4. I also have them available for the taking on the Kitely Grid, HG to [url]hop://grid.kitely.com:8002/Panthalassa/129/129/24[/url] . If you can grab copies of these, they have the full perm scripts in them and are made of sculpts designed to work well with the scripts. For the holiday tree, I started with a texture map I bought from Ro!Act Designs on the Kitely Marketplace (http://www.kitely.com/market?store=3080617). I stretched this to fit on the right surfaces of my sculpt and painted lights in different positions on 4 different versions of that texture map. Arianna Monaron gave me permission to give away these copies of this texture. For the lights on the tree I used a glitter brush from Obsidian Dawn (http://www.obbsidiondown.com).

December of 2013 I installed some of my toboggans on a friend's holiday SIM, only to discover that they only worked in spits and starts. I tracked down the problem to a free open source flashing light script. There were strings of holiday lights all over this SIM, with a copy of this script in every bulb. Thousands of copies of this script all running at once. The script had a timer event, but inside this event it was turning the light on, then llSleep'ing for a second, then turning the light off.

There is this dirty little secret of the Open Simulator LSL engine: When you call llSleep(), it stops the “thread” that is running your script for the delay time you asked for. A thread is like a separate processor that can run one script. By default, a SIM has 100 of these threads, so 100 scripts can be running at once. This may not sound like a lot, but most well-written scripts are “event driven”. This means that they spend most of their time doing nothing but waiting for a click, waiting for a timer, waiting for a message, waiting for a collision, etc. But the important thing is that while a script is waiting for an event, it frees up the thread. The threads are only used by scripts that are actually doing something. So thousands and thousands of scripts can all be “running” and ready to work, as long as only 100 or fewer are processing events at any one time.

But llSleep() is not the same thing as waiting for an event. It pauses the thread and HOLDS ONTO IT, preventing ANY OTHER SCRIPTS from using that thread until the delay time is over. So in the case of my friend's holiday SIM, after the first 100 blinking lights called llSleep, all 100 of the threads were paused and unable to work. No other scripts in the SIM were allowed to run, except once in a while when a thread was released for an instant. Nobody noticed that the lights were all blinking slower than they were supposed to. Only when I sat on a toboggan did I discover that something was very, very wrong.

Here is the holiday light script I wrote to solve that and several other problems:

Code: Select all

    //holiday lights
        //Written by Kayaker Magic and given away as open source with no restrictions.
        //I've seen some blinking light scripts that were very hard on the simulator
        //this is an attempt at a low-lag blinking light script.
        //It is completely event driven, running on a timer
        //One script can blink up to 256 lights
        //It uses llSetLinkPrimitiveParamsFast to avoid the script thread locking bug
        //It blinks the lights in an order that looks like they are shifting sequentially
        //You specify the light on/off pattern by putting a string of 1's and 0's 
        //in the root prim description
    //To use this:
        //Put this script in one light ONLY IN ONE LIGHT!
        //link it to as many lights as you want (well up to 256 lights total)
        //Name each of the light prims in an order that sorts in the order you want them to blink
        //In the root prim (or the one with the script) change the prim description to
        //a string of 1's and 0's to indicate the pattern of lights that are on.
        //The default (if no description) is "001" meaning two lights off and one on
        //repeats down your string of lights.
    //I have single-prim holiday light sculpt that looks like a bulb with a base. That
	// works well with this script. I made a black-and-white texture for that bulb so the
    	// base of the light is black, and the bulb white. You can change the color of the
    	// bulb and this script changes the brightness and glow. The black base is not
    	// effected by this and remains dark.
    
list lites;
string pattern;	//will contain the pattern of on/off lites
integer off;    //offset to the next character in the pattern

SortLites()		//sort the lights into the order they will blink
{
    lites=[];		//clear the list
    integer i;
    for (i=1;i<=llGetNumberOfPrims();i++)
        lites += [llGetLinkName(i),i];	//get every prim name and number
    lites = llListSort(lites,2,TRUE);	//sort them into name order
    	//also get the light order string from the description
    pattern=llGetDescription();
    if (llStringLength(pattern)==0)
    	pattern="001";		//default to two off, one on.
}

default
{
    state_entry()
    {
        SortLites();
        llSetTimerEvent(0.5);   //start the timer
    }
    on_rez(integer param)
    {
        SortLites();
    }
    changed(integer flags)
    {
        if (flags&CHANGED_LINK)
        {		//if a prim is added or removed,
            SortLites();	//better make a new sorted list
        }
    }
    timer()
    {
        integer i;
        for (i=1;i<=llGetNumberOfPrims();i++)
        {		//turn this light on if there is a "1" in the description
        	integer loff=(off+i)%llStringLength(pattern);	//advance through the pattern
        	integer brite = (llGetSubString(pattern,loff,loff)=="1");
            llSetLinkPrimitiveParamsFast(llList2Integer(lites,i*2-1),[
                PRIM_FULLBRIGHT,ALL_SIDES,brite,
                PRIM_GLOW,ALL_SIDES,(float)brite*0.5
            ]);
        }
        off = off+1)%llStringLength(pattern);	//advance the offset by one light
    }
}
And here is a related script for changing texture maps on a holiday tree:

Code: Select all

    //holiday tree
        //Written by Kayaker Magic and given away as open source with no restrictions.
        //I've seen some blinking texture scripts that were very hard on the viewers
        //this is an attempt at a low-lag blinking texture script.
        //It is completely event driven, running on a timer
        //This one script can blink up to 256 trees
        //It uses llSetLinkPrimitiveParamsFast to avoid the script thread locking bug
        //It blinks the textures randomly on each tree
    //To use this:
        //Put this script in one tree. ONLY IN ONE TREE!
        //Put a sequence of textures in the tree with the script. ONLY IN THE ONE TREE!
        //link it to as many trees as you want (well up to 256 trees total)
    //I have single-prim holiday tree sculpt made from 4 intersecting planes. That
	// works well with this script. I added a set of textures for this with lights
    	// painted in different locations. When the script changes textures, the lights
    	// appear to blink on and off.
    
default
{
    state_entry()
    {
        llSetTimerEvent(0.5);
    }
    timer()
    {
        integer tree;
        for (tree=1;tree<=llGetNumberOfPrims();tree++)
        {
            llSetLinkPrimitiveParamsFast(tree,[
                PRIM_TEXTURE,
                ALL_SIDES,
                llGetInventoryName(INVENTORY_TEXTURE,
                    (integer)llFrand(llGetInventoryNumber(INVENTORY_TEXTURE))),
                <8,1,0>,
                <0.5,0,0>,
                0.0
            ]);
        }
    }
}
Last edited by Kayaker Magic on Fri Nov 21, 2014 9:11 am, edited 2 times in total.
These users thanked the author Kayaker Magic for the post (total 6):
Constance PeregrineMarstol NitelyDot MatrixAda RadiusRobert StanleySerene Jewell
User avatar
Ada Radius
Posts: 267
Joined: Sun Dec 23, 2012 6:20 pm
Has thanked: 138 times
Been thanked: 164 times

Re: Holiday Lights and Tree Scripts

Post by Ada Radius » Thu Nov 20, 2014 8:23 pm

Thank you Kayaker! Very useful and helpful explanation as well for a non-programmer like me. I have a suggestion - put your name at the first // so those of us working with open source builds (such as the Aley ones I'm importing to Kitely) can make sure credit is there and that people will look for you when they need cool and elegant scripts. I'm trying very hard, on the SL side, to make sure that creator data carries from SL to OpenSim. EVERYTHING imports showing "created by Ada Radius" and OAR backup and restore isn't any better. When a scriptor has put creator information in the script itself, the information makes it in. Along with a request that subsequent script mods leave a trail as well, we have at least a shot at knowing where stuff came from.
Ada
User avatar
Kayaker Magic
Posts: 345
Joined: Sun Dec 01, 2013 8:40 am
Has thanked: 50 times
Been thanked: 365 times

Re: Holiday Lights and Tree Scripts

Post by Kayaker Magic » Fri Nov 21, 2014 9:06 am

Thanks for the suggestion Ada, I have added my name to the comments.
When I posted those to the OSCC14, I was rushed for time. I considered putting a reference to the Creative Commons License, or the GNU General Public License, but I didn't have time to go figure out what those really mean, and what the differences are. I'll get to that in my spare time!
User avatar
Constance Peregrine
Posts: 2325
Joined: Sun Dec 23, 2012 11:35 am
Has thanked: 2765 times
Been thanked: 1425 times

Re: Holiday Lights and Tree Scripts

Post by Constance Peregrine » Fri Nov 21, 2014 1:31 pm

got it @ your conference location...ty kind sir-))
These users thanked the author Constance Peregrine for the post:
Marstol Nitely
Laissez faire et laissez passer, le monde va de lui même!
My little sounds store https://www.kitely.com/market?store=2040306

Ephemeral wanderer...
User avatar
Marstol Nitely
Posts: 480
Joined: Mon Dec 24, 2012 1:42 am
Has thanked: 1015 times
Been thanked: 432 times

Re: Holiday Lights and Tree Scripts

Post by Marstol Nitely » Fri Nov 21, 2014 6:26 pm

I picked up the tree at the expo. Very cool display BTW. Grabbed the script here. I was happy to have the jump address because I had streaming for the conference which was fine, but I wanted jump over to the expo. So I guess I owe you a triple thank you! :D
User avatar
Robert Stanley
Posts: 84
Joined: Tue Aug 12, 2014 4:04 am
Has thanked: 260 times
Been thanked: 156 times

Re: Holiday Lights and Tree Scripts

Post by Robert Stanley » Fri Nov 21, 2014 6:55 pm

Thank you for the work you put into this and for sharing it with us. Also, thank you for the lesson in there about OpenSIm script limits.

Here's to a happy and less laggy VR Holiday season thanks to you. :)
Post Reply