When establishing the photo studio in one corner of Don’t Panic!, Danielle set up a backdrop prim with a number of different textures in it for picture backdrops. To switch between them, she came up with this little script:
integer number = llGetInventoryNumber(INVENTORY_TEXTURE);
float rand = llFrand(number);
integer choice = (integer)rand;
string name = llGetInventoryName(INVENTORY_TEXTURE,choice);
When touched, this script finds the number of textures the object contains in inventory, then picks a random number between 0 and that number minus 1. (As in most programming languages, casting from float to integer in LSL truncates everything after the decimal point.) Then it gets the name of the texture with that index and applies it to all sides. Simple enough.
Danielle wanted the script to say which texture was being displayed at touch time, so she asked me to take a look at the code and improve it. At the same time, I felt that random switching was not the way to go here; better yet would be sequential switching, to run through all the textures in order. Herewith my solution:
// Enhanced Texture Switcher
// Erbo Evans - 8/20/2006
list all_textures = ;
integer count = 0;
integer current = 0;
string s = llList2String(all_textures,ndx);
string p = (string)(ndx + 1);
llWhisper(0,"Now displaying texture: " + s + " (" + p + "/"
+ (string)count + ")");
count = llGetInventoryNumber(INVENTORY_TEXTURE);
for (i=0; i<count; i++)
string s = llGetInventoryName(INVENTORY_TEXTURE,i);
all_textures += [s];
llWhisper(0,"Texture switcher is ready.");
current = 0;
The code now loads the names of all textures into a list at state_entry() time, for faster access. Notice that, after we load the name of a texture into the string variable s, we turn that into a single-element list to concatenate it onto the all_textures list. We also save the number of textures in count, to avoid having to call llGetListLength() unnecessarily later.
Since setting textures now involves a few different operations, I moved the process into its own function, set_texture(), which takes as an argument the 0-based index of the texture to display. Note that, when the texture number is actually displayed via llWhisper(), it is displayed as a 1-based index, which is more “natural” for humans to deal with. (Unless they’re programmers…but let’s not go there.)
The first two lines of the touch_start() handler will be difficult to understand for anyone not already familiar with LSL, or familiar with one of the languages that inspired it (C, C++, Java). The expression adds one to the current variable, then, if that variable is equal to the count, resets it to 0. “++” in this context is used as a pre-increment operator, which increments the value of current before using it in the test for equality with count. If I had written “current++” rather than “++current”, the “++” would have been a post-increment operator, which means the value of current would have been incremented after its use in the comparison with count. This is sometimes useful, too…just not here. (Sometimes it doesn’t matter which you use, as in the third expression of the for loop in the state_entry() handler. In those contexts, I tend to use the post-increment form. Others will use the pre-increment form here. That’s just a stylistic difference.)
The main drawback of this code as compared to Danielle’s is that it won’t automatically adapt to the addition of new textures to the object; you have to reset the script manually. I could get around that by adding a changed() handler to listen for inventory changes, and call llResetScript() when they happen. In actual practice, though, we don’t add new textures to the backdrop often enough to worry about this.
This code also worked well for an automatic picture cycler that displays a number of pictures I took of Danielle. I simply changed the touch_start() handler into a timer() handler, and called llSetTimerEvent() at the end of the state_entry() handler, with an appropriate delay value.
Share and enjoy! 🙂