// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Texture offset jog menu // Not compiled or tested in-world // Setup: Set FACE on a spare classic diffuse-textured prim. Owner-touch; Restore restores the entire captured diffuse rule. // Stop / restore: Use the Restore or Home action described in setup before removing or resetting if you want the startup appearance. Menu listeners expire after 45 seconds. // Notes: Local owner-only control. Saved snapshots live in script memory and are lost on reset. Uses readable texture settings. Offsets are normalized/wrapped into the valid -1 to 1 range. Does not edit PBR-specific transforms. // License: see LICENSE in this distribution. // Original Incoprea. MIT. Not compiled or tested in-world. integer channel; integer handle; close() { if(handle)llListenRemove(handle); handle=0; llSetTimerEvent(0.0); } menu(string prompt,list buttons) { if(!handle) { channel=-1000-(integer)llFrand(1000000.0); handle=llListen(channel,"",llGetOwner(),""); } llDialog(llGetOwner(),prompt,buttons,channel); llSetTimerEvent(45.0); } integer FACE=0; list saved; init() { saved=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]); } show() { menu("Diffuse UV offset: 0.05 steps",["Left","Right","Up","Down","Center","Restore"]); } choose(string s) { if(s=="Restore") { llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+saved); show(); return; } list rule=llGetLinkPrimitiveParams(LINK_THIS,[PRIM_TEXTURE,FACE]); vector p=llList2Vector(rule,2); if(s=="Left")p.x-=0.05; else if(s=="Right")p.x+=0.05; else if(s=="Up")p.y+=0.05; else if(s=="Down")p.y-=0.05; else if(s=="Center")p=ZERO_VECTOR; else return; if(p.x>1.0)p.x-=2.0; if(p.x< -1.0)p.x+=2.0; if(p.y>1.0)p.y-=2.0; if(p.y< -1.0)p.y+=2.0; llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_TEXTURE,FACE]+llListReplaceList(rule,[p],2,2)); show(); } default { state_entry() { init(); } touch_start(integer n) { if(llDetectedKey(0)!=llGetOwner())return; close(); show(); } listen(integer ch,string name,key id,string message) { if(!handle||ch!=channel||id!=llGetOwner())return; choose(message); } timer() { close(); } changed(integer change) { if(change&CHANGED_OWNER)llResetScript(); } }