Here is the good news: whatever problem is causing it to not work can be fixed by deleting the script inside the device and putting in a new script containing exactly the same script that is not now working. Since I "donated" this script to the community I haven't looked at it in more than a year, so it may carry ancient LSL hacks that are no longer needed.
If you have recently purchased one of these and it is not working for you, please send me a PM and I will refund your purchase price.
CODE
// image loop v2.0 - shows a continuous series of images on click or timer
// 18-oct-03 malachi petunia
// 23-oct-03 added touch control
// 11-nov-03 reordered texture preloading for actual preloading
// 24-dec-04 added config file and associated support, reset upon change of inventory
// need to implement image back command
// this script is released to the SL community for free use, derivative works are permitted
// provided you don't remove the comments from the top to here or claim you wrote it
integer activeSide = 2; // the +X face of a cube
integer hiddenSide = 3; // invisible face for texture caching
float swapInterval = 1200.0; // how long to pause between images
string configName = "CONFIG"; // name of a notecard in the object's inventory - format "name: value"
string startImage = "ab3d084f-78e3-e6f1-aa5d-49ccf271f0b6"; // display logo while resetting
string resetCmd = "image reset"; // command to restart
integer configLine = 0; // current config line number read
integer ownerOnly = FALSE; // restricts click advance to owner if true
integer imageLoop = TRUE; // TRUE cylces through images, FALSE runs once through
integer resetNeeded = FALSE; // holds pending auto-reset
integer listenHandle = -1; // idempotence for listener
integer num_textures = 0; // how many textures to shoe
integer currentTexture = -1; // initial list index;
list textureSet;
integer debug = FALSE; // verbose debug output
// debugMsg - syntax candy
//
debugMsg(string s) {
llSay(0, s);
}
// readConfig - initiate a read of the configName variable deeclarations if and only
// if it exists
//
readConfig() {
key configKey = llGetInventoryKey(configName);
// it is unduly hard to see if configName is a notecard so Ill just assume
// it is and let it throw a runtime errer
if(configKey != NULL_KEY) {
llGetNotecardLine(configName, configLine); // start the read, tail recurse thru dataserver
configLine++;
} else {
debugMsg("could not find " + configName + " in inventory, using defaults");
}
}
// parseConfig - interprets a single line from a notecard
// there are two kinds of lines: comments beginning with "#"
// and variable assignments of the form "name: value"
// known variables are assigned, all others rejected
//
parseConfig(string s) {
if(llGetSubString(s, 0, 0) == "#") // comment lines begin with #
return;
list args = llParseString2List(s, [":", " "], []);
if(llGetListLength(args) != 2) {
debugMsg("unparsable line in " + configName + "=" + s + "=");
return;
}
string id = llList2String(args, 0);
string val = llList2String(args, 1);
if(debug) debugMsg("parsed " + id + ": " + val);
if(id == "ownerOnly") {
ownerOnly = (integer) val;
if(debug) debugMsg("ownerOnly set to " + ((string) ownerOnly) + " from " + configName);
} else if(id == "swapInterval") {
swapInterval = (integer) val;
if(debug) debugMsg("swapInterval set to " + ((string) swapInterval) + " from " + configName);
llSetTimerEvent(swapInterval);
} else if(id == "imageLoop") {
imageLoop = (integer) val;
if(debug) debugMsg("imageLoop set to " + ((string) imageLoop) + " from " + configName);
} else {
debugMsg("unknown variable " + id + " in " + configName);
}
}
// nextImage - cycle to the next image, looping to first if needed
// preloads the next texture for instant availability
//
nextImage() {
integer a;
string preloadedImage;
string newImage;
currentTexture++;
preloadedImage = llGetTexture(hiddenSide);
// instantiate the new
llSetTexture(preloadedImage, activeSide);
if(debug) debugMsg("loaded " + preloadedImage + " onto side " + ((string) activeSide));
if((!imageLoop) && (currentTexture >= num_textures)) {
debugMsg("showing last image - say '" + resetCmd + "' to reset");
llSetTimerEvent(0);
return;
}
currentTexture %= num_textures;
newImage = llList2String(textureSet, currentTexture);
llSetTexture(newImage, hiddenSide); // preload the texture where it cannot be seen
if(debug) debugMsg("loaded " + newImage + " onto hidden side " + ((string) hiddenSide));
}
// fillTextureInventory - fills the textureInventory list with names of all textures in show
//
fillTextureInventory() {
integer i;
string texture_name;
num_textures = llGetInventoryNumber( INVENTORY_TEXTURE );
if (debug) debugMsg(((string) (num_textures)) + " textures in inventory:" );
textureSet = [];
for ( i = 0; i < num_textures; i++ ) {
texture_name = llGetInventoryName( INVENTORY_TEXTURE, i );
if (debug) debugMsg(texture_name);
textureSet += texture_name;
}
}
init() {
if(debug) debugMsg("initializing");
llSetTexture(startImage, activeSide);
llSetTexture(startImage, hiddenSide);
configLine = 0;
currentTexture = -1;
ownerOnly = FALSE;
swapInterval = 1200;
resetNeeded = FALSE;
readConfig();
fillTextureInventory();
nextImage();
llSetTimerEvent(swapInterval); // this may be changed by an asynchronous parseConfig
if(listenHandle == -1) {
listenHandle = llListen(0, "", llGetOwner(), resetCmd);
}
}
default {
state_entry() {
init();
}
on_rez(integer start) {
init();
}
touch_start(integer num_touxh) {
if(ownerOnly && (llDetectedKey(0) != llGetOwner()))
return;
nextImage();
llSetTimerEvent(swapInterval);
}
timer() {
if(resetNeeded) {
init();
} else {
nextImage();
}
}
dataserver(key query_id, string data) {
if (data != EOF) {
parseConfig(data);
llGetNotecardLine(configName, configLine);
configLine++;
}
}
listen(integer c, string n, key k, string m) {
// all listen prequalification done in the listener
init();
}
changed(integer c) {
if(debug) debugMsg("change of " + ((string) c));
if(c & CHANGED_INVENTORY) {
if(debug) debugMsg("inventory change - resetting in 30 seconds");
resetNeeded = TRUE;
llSetTimerEvent(30);
}
}
}