This item is a customizable banner with texture change support and with a matching holding animation.
The only requirements to change the textures is to drag and drop textures into the root primitive of the banner.
/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2021 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasMenuIndex = 0; list wasDialogMenu(list input, list actions, string direction) { integer cut = 11-wasListCountExclude(actions, [""]); if(direction == ">" && (wasMenuIndex+1)*cut+wasMenuIndex+1 < llGetListLength(input)) { ++wasMenuIndex; jump slice; } if(direction == "<" && wasMenuIndex-1 >= 0) { --wasMenuIndex; jump slice; } @slice; integer multiple = wasMenuIndex*cut; input = llList2List(input, multiple+wasMenuIndex, multiple+cut+wasMenuIndex); input = wasListMerge(input, actions, ""); return input; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// integer wasListCountExclude(list input, list exclude) { if(llGetListLength(input) == 0) return 0; if(llListFindList(exclude, (list)llList2String(input, 0)) == -1) return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude); return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// list wasListMerge(list l, list m, string merge) { if(llGetListLength(l) == 0 && llGetListLength(m) == 0) return []; string a = llList2String(m, 0); if(a != merge) return [ a ] + wasListMerge(l, llDeleteSubList(m, 0, 0), merge); return [ llList2String(l, 0) ] + wasListMerge(llDeleteSubList(l, 0, 0), llDeleteSubList(m, 0, 0), merge); } list textures = []; integer chan = 0; integer listenId = 0; default { state_entry() { integer i = llGetInventoryNumber(INVENTORY_TEXTURE) - 1; do { textures += llGetInventoryName(INVENTORY_TEXTURE, i); } while (--i > -1); state select; } changed(integer change) { llResetScript(); } on_rez(integer num) { llResetScript(); } } state select { state_entry() { chan = ((integer)("0x"+llGetSubString((string)llGetKey(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; } touch_start(integer num) { // Lock to owner. if(llDetectedKey(0) != llGetOwner()) { return; } listenId = llListen( chan, "", llGetOwner(), ""); llDialog( llGetOwner(), "Please choose the texture: ", wasDialogMenu(textures, ["⟵ Back", "", "Next ⟶"], ""), chan ); } listen(integer channel, string name, key id, string message) { if(message == "⟵ Back") { llDialog( id, "Please choose the texture: ", wasDialogMenu(textures, ["⟵ Back", "", "Next ⟶"], "<"), chan ); return; } if(message == "Next ⟶") { llDialog(id, "Please choose the texture: ", wasDialogMenu(textures, ["⟵ Back", "", "Next ⟶"], ">"), chan ); return; } integer i = llListFindList( textures, [ message ] ); string texture = llList2String(textures, i); llSetLinkPrimitiveParamsFast(3, [PRIM_TEXTURE, ALL_SIDES, texture, <-1, 1, 0>, <0, 0, 0>, PI_BY_TWO ]); llSetLinkPrimitiveParamsFast(5, [PRIM_TEXTURE, ALL_SIDES, texture, <-1, 1, 0>, <0, 0, 0>, PI_BY_TWO ]); llListenRemove(listenId); } changed(integer change) { llResetScript(); } on_rez(integer num) { llResetScript(); } }