// Script to present a dialog populated with a list of textures // either from the prims inventory or specified by UUID in a notecard. // // Notecard lines have the form: // Texture Name=UUID // // Note that only the first 24 characters of the texture names // are actually used - as only 24 chars can be placed in a dialog // button. This means that if two textures have the first 24 chars // the same, the second will be ignored ... // // Note however that usually, buttons don't display more than, say, // around 10 or so characters anyway!! // // There are two methods of setting textures - one (gSetTexture = TRUE) // allows you to use UUIDs, etc, but the other (gSetTexture = FALSE) // will allow you to specify the rotation and offset values. // // There is also an option to just use the values from the texture already // on the face (but this won't work for ALL_SIDES). // // Both allow you to set the face. // // Kimm Paulino // Feb 2012 // Controls how the script operates: integer gReshow = FALSE; integer gSetTexture = FALSE; // Use SetTexture method (needed for textures not in the prim inventory) integer gNotecards = TRUE; // Get textures to use from a notecard not inventory integer gPreserveTextures = FALSE; // Read offset/rotation values from existing texture // configures how textures appear integer gFace = 1; vector gRepeats = <1.0, 1.0, 1.0>; vector gOffsets = <1.0, 1.0, 1.0>; float gRotationInDegrees = 0.0; // Do not change anything below this line (unless you know what you are doing) integer gDebug = FALSE; integer gMenuPage; integer gNumTextures; list gTextures; list gTextureUUIDs; string gNotecardName; integer gNotecardLine = 0; key gQueryID; integer gListenChannel; integer gListenHandle; float gListenTimer; float LISTEN_TIMEOUT=300.0; string MENU_NEXT="Next>"; string MENU_TOP="Top"; string MENU_BACK="= num_pages) { // gMenuPage is an index starting at 0... // max is a 1... gMenuPage = num_pages-1; } // Max buttons on a dialog is 12, so if more than that, then need to // include special next/back button handling integer first_texture = 0; integer last_texture = gNumTextures-1; if (gNumTextures > 12) { // Note: This yields notecards counting as follows: // 0 to 8 = first page, // 9 to 17 = next page, etc first_texture = gMenuPage * 9; last_texture = first_texture + 9 - 1; if (last_texture >= gNumTextures) { // recall last_texture indexed from 0, but // gNumTextures is indexed from 1 last_texture = gNumTextures-1; } if (gMenuPage > 0) { buttons += [MENU_BACK]; } else { buttons += [MENU_SPACE]; } if (gMenuPage == 0) { buttons += [MENU_SPACE]; } else { buttons += [MENU_TOP]; } // If not on the last page, and there are more pages to come ... if (gNumTextures > 9 && gMenuPage < (num_pages-1)) { buttons += [MENU_NEXT]; } else { buttons += [MENU_SPACE]; } } integer i; for (i=first_texture; (i <= last_texture) && (i < gNumTextures); i++) { buttons += [llList2String (gTextures, i)]; } do_dialog (id, "\n\n(click \"Ignore\" when done)", buttons); } do_dialog (key id, string msg, list buttons) { llListenRemove (gListenHandle); gListenChannel = getRandomChannel(); gListenHandle = llListen (gListenChannel, "", id, ""); llSetTimerEvent (LISTEN_TIMEOUT); llDialog (id, msg, buttons, gListenChannel); } default { on_rez (integer start_param) { llResetScript(); } state_entry() { if (read_textures_from_inventory()) { // We have textures in the inventory and have read them gNotecards = FALSE; } else if (read_textures_from_notecards()) { // We have textures read in from a notecard by UUID // (or will have pretty soon) gNotecards = TRUE; } else { llOwnerSay ("Note: There are no textures or notecards in this prim ..."); } gMenuPage = 0; } touch_start(integer total_number) { // Start menu system again. Note that I don't do anything special // with several people trying to touch it at the same time - it will // always overlap the processing of gMenuPage, but all that will // happen is that peoples next/back might be a bit quirky for a while. // Eventually, they will sort themselves out! gMenuPage = 0; show_dialog (llDetectedKey(0)); } listen (integer channel, string name, key id, string msg) { if (channel == gListenChannel) { if (msg == MENU_BACK) { gMenuPage--; show_dialog (id); } else if (msg == MENU_TOP) { gMenuPage = 0; show_dialog (id); } else if (msg == MENU_NEXT) { gMenuPage++; show_dialog (id); } else { // should be something in the inventory to give out apply_texture (msg); // reshow the dialog if (gReshow) { show_dialog(id); } } } } timer () { // First see if we are timing out on a listen event if (gListenHandle != 0) { // Remove the old listen llListenRemove (gListenHandle); gListenHandle = 0; gListenChannel = 0; } } dataserver(key query_id, string line) { if (query_id == gQueryID) { if (line != EOF) { if (llSubStringIndex (line, "=") != 0) { list vals = llParseString2List (line, ["="], []); // Only store the first 24 characters of the name as this is all we can // show in a dialog anyway string texture = llList2String (vals, 0); string uuid = llList2Key (vals, 1); gTextures += [llGetSubString (texture, 0, 23)]; gTextureUUIDs += uuid; doDebug ("Adding: " + texture + " ("+uuid+")"); } // Now get the next line gNotecardLine++; gQueryID = llGetNotecardLine(gNotecardName, gNotecardLine); } else { gNumTextures = llGetListLength (gTextures); doDebug ("Found " + (string)gNumTextures + " textures."); } } } changed (integer change) { if (change & CHANGED_INVENTORY) { llResetScript(); } } }