User:Void Singer/v7-D Zen Resizer

From Second Life Wiki
< User:Void Singer
Revision as of 09:36, 25 January 2015 by ObviousAltIsObvious Resident (talk | contribs) (<lsl> tag to <source> - last of llGetFoo yay)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

v7-D Zen Resizer

Builder Features:

  • Drag and Drop Design (minimal to no editing at all)
  • Clear Simple Instructions
  • Multiple configurations possible
  • Open source scripts let you modify directly in the script if desired
  • Multi Language Support
  • Allows end users to set and restore their own default (in the range you allow)
  • Allows end user to remove the resize script
  • Allows you to disable the the above user functions

Warning: Not fully compatible with other scripts that change the position/size of the links.

User Features:

  • Single LSO script, triggers after a two second touch/hold to avoid triggering when other touch scripts are present (and to override v2x dialogs)
  • Auto-language detection on ownership change (where reported, creator configurable to include any language code, default language set by creator)
  • Equivalent size adjustments (+10% then -10% results in the same starting size)
  • Size percentage reported on dialog in easy to understand 0.00 to 100.00 percentage format (representing size limits)
  • Preset Limits avoid broken objects (even on max resize). no guessing if a change will exceed min size or max link distance, because it won't.
  • Removable from no mod objects
  • User Settable Save and Restore
  • Auto-remenu (saves time editing) with "Done" cancel button.
  • Owner feedback on dialog commands provided.

Quickstart Instructions:

  1. Make a copy of your object for safety.
  2. Drop the v7-D Zen Resizer Prep script into your object, click it and follow the dialog instructions.
  3. Remove the previous script and drop the v7-D Zen Resizer (lite) script and v7-D Zen Resizer (lite): User Manual into your object.

Done!

Return to top

Detailed Instructions

Step 1

REQUIRED: Make a Copy of your object before Starting for safety!

Step 2

OPTIONAL: Drop a translated v7-D Zen Resizer Prep.cfg notecard into the root prim of your object Drop the v7-D Zen Resizer Prep script into the root prim of your object

Step 3

Click your object, and follow the instructions in the dialogs

NOTE: This step changes the size of your object; It will be reset to it's default size at the end of this step
NOTE: This step automatically sets the object description to set=< rotation > (it will also be printed to your chat history). You can add other information to the description without interfering with it, or if you prefer, you can remove it and add it to the notecard in [Step 5].

Step 4

Remove the v7-D Zen Resizer Prep script from your object (and any v7-D Zen Resizer Prep.cfg notecard)

Step 5

  • (5a) Edit the v7-D Zen Resizer (lite).cfg notecard for any custom changes
  • (5b) Drop the v7-D Zen Resizer (lite).cfg notecard into the root prim of your object
    • NOTE: Steps (5b) is REQUIRED if you removed the object description text above (and did not directly edit it into the script); otherwise it is OPTIONAL.
  • (5c) OPTIONAL: Translate the v7-D Zen Resizer (lite).cfg notecard into another language, and save as a new notecard, adding ".xx" (no quotes) to the end of its name (where "xx" is the language code, see the default v7-D Zen Resizer (lite).cfg notecard for details)

Step 6

Drop the v7-D Zen Resizer (lite) script into the root prim of your object

Step 7

OPTIONAL (but strongly suggested): Perform the following tests to confirm that Zen Resizer has been installed correctly:

  • (7a) make a copy of your current object (to avoid having to reset it)
  • (7b) Click on the Object, holding the mouse button down for two seconds to activate the menu
  • (7c) (via the dialog) Increase the objects size to 100.00%
  • (7d) (via the dialog) Save the current size
  • (7e) (via the dialog) Decrease the objects size to 0.00%
  • (7f) (via the dialog) Restore the saved size
  • (7g) if any test fails (and it shouldn't) go back to [Step 1] and use a smaller maximum size.

Step 8

OPTIONAL: Drop the v7-D Zen Resizer (lite): User Manual notecard into the root prim of your object

NOTE: If you made changes to the v7-D Zen Resizer (lite).cfg notecard, you will want to edit this notecard to reflect any command changes as well
NOTE: If you included translations for the menus, you may want to include translations of this notecard as well
NOTE: Optionally, You may, instead, copy the instructions to your own notecard included with the object.

Step 9

REQUIRED: Include a Plain Text (readable by the User) copy of the following three lines somewhere in or with your object

v7-D Zen Resizer
(C) 2010 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]
Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]
Return to top

Advanced Tips

  • Any Changes made in the default notecard can be directly edited into the script instead (all necessary variables are at the top)
  • Dialog can be triggered via link message so that you can tie the dialog into your own script with the following
llMessageLinked( LINK_ROOT, 0, "v7-D Zen Resizer (lite)", llGetOwner() );
You can replace llGetOwner() with the key of any avatar you want to receive the dialog
  • You can directly access the resize function via Link message from your own script with the following commands
llMessageLinked( LINK_ROOT, llRound( percentage * 10000 ), "v7-D Zen Resizer (lite)", "" ); //-- change object size
Replace percentage with a float in the range of 0.0 to 1.0
llMessageLinked( LINK_ROOT, -1, "v7-D Zen Resizer (lite)", "" ); //-- Reset the object to the last saved size
llMessageLinked( LINK_ROOT, -2, "v7-D Zen Resizer (lite)", "" ); //-- Saves the current Size
llMessageLinked( LINK_ROOT, -3, "v7-D Zen Resizer (lite)", "" ); //-- Removes the resize script
  • All direct access commands will report back with:
llMessageLinked( source_link_number, 1, "v7-D ZenResizer (lite)_", "" ); //-- Command Succeeded
llMessageLinked( source_link_number, 0, "v7-D ZenResizer (lite)_", "" ); //-- Command Failed
source_link_number = the link number of the script that sent the original command
  • The script name can be changed, notecards and link commands MUST be changed to match
  • This package is free; If you paid for it, you got screwed, probably by a copyright violator.
  • "set = " is set by notecard if present, by script if not, and by description field only if the other two are not present.
Return to top

Notecards and Scripts

v7-D Zen Resizer Prep.cfg

  1. Create a notecard and name it v7-D Zen Resizer Prep.cfg
  2. Copy and paste the contents of the box below into it and save
:: This is a comment, comments are good. anything starting with "::" and after is a comment
:: this notecard must be named the same as the script with ".cfg" (no quotes) added to the end
:: values may be translated, please include the "//" in txt0 for safety, line breaks wil be inserted for every instance of "\n" (no quotes)
txt0 = // You may paste the following line into your notecard:
txt1 = Resize the object (in edit, via a corner grab) to the DEFAULT size you want, then press "OK"\n\n(This size will automatically be restored when done)
txt2 = Resize the object (in edit, via a corner grab) to the SMALLEST size you want available, then press "OK"\n\n(This size must be SMALLER than the DEFAULT)
txt3 = Resize the object (in edit, via a corner grab) to the LARGEST size you want available, then press "OK"\n\n(this size must be LARGER than the DEFAULT)
txt4 = Done!\n\nThe set variable is saved to the object's description field, and has been sent to your chat history window. You may remove this script now.
Return to top

v7-D Zen Resizer Prep

  1. Create a script and name it v7-D Zen Resizer Prep
  2. Copy and paste the contents of the box below into it and save
/*//( v7-D Zen Resizer (lite) Prep v1.4 )//*/

//-- these variable may be translated here or in an optional notecard
list     gLstTxt = ["// You may paste the following line into your notecard:",
                    "Resize the object (in edit, via a corner grab) to the DEFAULT size you want, then press \"OK\"\n\n(This size will automatically be restored when done)",
                    "Resize the object (in edit, via a corner grab) to the SMALLEST size you want available, then press \"OK\"\n\n(This size must be SMALLER than the DEFAULT)",
                    "Resize the object (in edit, via a corner grab) to the LARGEST size you want available, then press \"OK\"\n\n(this size must be LARGER than the DEFAULT)",
                    "Done!\n\nThe Object Stats are saved to the objects description field, and have been sent to your chat window (you may include it in your notecard)"];
list     gLstVal;
integer  gIntCnt;
rotation gNfoSet = <0.0, 0.0, 0.0, 0.0>;

key    gKeyChk;
string gStrNCL;

 //-- Adjust Set Size
uAdjSiz( float vFltNew ){
     //-- clamp vFltNew to valid percentage [0.0, 1.0]
    vFltNew = (vFltNew * (vFltNew > 0.0) - 1.0) * (vFltNew < 1.0) + 1.0;
     //-- only run if previous percent greater or less than next percentage? (0 means the same)
    if ((vFltNew < gNfoSet.z) - (vFltNew > gNfoSet.z)){
         //-- get the current root size for comparison
        vector vSizOld = llGetScale();
         //-- save the new percentage to gNfoSet, and reuse gFltNew to save the relative change percentage
        vFltNew = (gNfoSet.x + gNfoSet.y * (gNfoSet.z = vFltNew)) / vSizOld.x;
        
         //-- intialize a temp list for holding child prims size/offset
        list vLstTmp;
         //-- get the number of prims for our loop + 1 (make loops cleaner later)
         //-- llGetObjectPrimCount doesn't count seated avs, but returns 0 for attachments
         //-- llGetNumberOfPrims works on attachments, but counts seated avs when detached
         //-- !!llGetAttached returns TRUE(1) if attached, or FALSE(0) if not, to cancel #ofPrims if unattached.
        integer  vIntCnt = ~-(llGetObjectPrimCount( llGetKey() ) +  llGetNumberOfPrims() * !!llGetAttached());
            //-- set the root prim separately since it's position will not change
        llSetLinkPrimitiveParamsFast( LINK_THIS, [PRIM_SIZE, vSizOld * vFltNew] );
        while (~-(--vIntCnt)){
            vLstTmp = llGetLinkPrimitiveParams( vIntCnt, [PRIM_SIZE, PRIM_POSITION] );
            llSetLinkPrimitiveParamsFast( vIntCnt,
                                          [PRIM_SIZE, llList2Vector( vLstTmp, 0 ) * vFltNew,
                                           PRIM_POS_LOCAL, llList2Vector( vLstTmp, 1 ) * vFltNew] );
        }
    }
}

default{
    state_entry(){
        gStrNCL = llGetScriptName() + ".cfg";
        if (~llGetInventoryType( gStrNCL )){
            gKeyChk = llGetNotecardLine( gStrNCL, gIntCnt );
        }else{
            state sRdy;
        }
    }
    
    dataserver( key vKeyQry, string vStrDta ){
        if (gKeyChk == vKeyQry){
            if (EOF == vStrDta){
                state sRdy;
            }else{
                if (vStrDta = llStringTrim( llList2String( llParseString2List( vStrDta, ["::"], [] ), 0 ), STRING_TRIM )){
                    if (!llSubStringIndex( llToLower( vStrDta ), "txt" )){
                        integer vIdxTxt = (integer)llGetSubString( vStrDta, 3, 0xFFFFFFFF );
                        vStrDta = (string)llList2List( llParseStringKeepNulls( vStrDta, ["="], [] ), 1, 0xFFFFFFFF );
                        gLstTxt = llListReplaceList( gLstTxt, (list)llDumpList2String( llParseStringKeepNulls( vStrDta, ["\\n"], [] ), "\n" ), vIdxTxt, vIdxTxt );
                    }
                }
                gKeyChk = llGetNotecardLine( gStrNCL, ++gIntCnt );
            }
        }
    }
}

state sRdy{
    state_entry(){
        gIntCnt = -4;
    }

    touch_end( integer vIntNul ){
        if (llGetOwner() == llDetectedKey( 0 )){
            state sRun;
        }
    }
    
    changed( integer vBitChg ){
        if (CHANGED_INVENTORY & vBitChg){
            if (~llGetInventoryType( gStrNCL )){
                llResetScript();
            }
        }
    }
}

state sRun{
    state_entry(){
        integer vIntChn = (integer)("0xF" + llGetSubString( llGetOwner(), 0, 6 ));
        llListen( vIntChn, "", llGetOwner(), "OK");
        llDialog( llGetOwner(), llList2String( gLstTxt, gIntCnt ), [], vIntChn );
    }
    
    listen( integer vIntChn, string vStrNul, key vKeyOwn, string vStrNull ){
        vector vSizTst = llGetScale();
        gLstVal += (list)vSizTst.x;
        if (~(++gIntCnt)){
            llDialog( vKeyOwn, llList2String( gLstTxt, gIntCnt ), [], vIntChn );
        }else{
             //-- calculate the info needed for the set.
            gNfoSet.x = llList2Float( gLstVal, 1 );
            gNfoSet.y = llList2Float( gLstVal, 2 ) - gNfoSet.x;
            gNfoSet.z = 1.0;
            gNfoSet.s = (llList2Float( gLstVal, 0 ) - gNfoSet.x) / gNfoSet.y;
            gLstVal = []; //-- clear the values list in case the user wants to do this again.
             //-- LSL has some weird rounding of rotations, but it's ignored if you diredctly print the elements
            llSetObjectDesc( "set=<" +
                             (string)gNfoSet.x + "," +
                             (string)gNfoSet.y + "," +
                             (string)gNfoSet.s + "," +
                             (string)gNfoSet.s + ">" );
             //-- avoid rounding errors in chat and pull the "set" variable from the description we just installed
            llOwnerSay( "\n" + llList2String( gLstTxt, 0) + "\n" + llGetObjectDesc() );

            uAdjSiz( gNfoSet.s );
            
            llDialog( llGetOwner(), llList2String( gLstTxt, -1 ), [], vIntChn );
            
            state sRdy;
        }
    }
}

/*//--                           License Text                           --//*/
/*//  Free to copy, use, modify, distribute, or sell, with attribution.   //*/
/*//    (C)2010 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]    //*/
/*//   Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  All usages must contain a plain text copy of the previous 2 lines.  //*/
/*//--                                                                  --//*/
Return to top

v7-D Zen Resizer (lite).cfg

  1. Create a notecard and name it v7-D Zen Resizer (lite).cfg
  2. Copy and paste the contents of the box below into it and save
// this is a comment, comments are good. anything begining with "//" will be ignored. so will blank lines.
txt0 = (v7-D Zen Resizer) Reading Notecard...
txt1 = (v7-D Zen Resizer) Notecard Read Failed; Retrying...
txt2 = (v7-D Zen Resizer) Ready.
txt3 = (v7-D Zen Resizer) Set Info Missing; Resize Aborted.
txt4 = (v7-D Zen Resizer) Resizing...
txt5 = (v7-D Zen Resizer) Resize Done.
txt6 = (v7-D Zen Resizer) Current Size Saved.
txt7 = (v7-D Zen Resizer) Dialog Timed Out.
txt8 = v7-D (v7-D Zen Resizer)  v1.3\n\nCurrent Size:
btn00 = +0.02%
btn01 = -0.02%
btn02 = Done
btn03 = +0.2%
btn04 = -0.2%
btn05 = Recall
btn06 = +2%
btn07 = -2%
btn08 = Save
btn09 = +20%
btn10 = -20%
btn11 = -Script
set = <0.0,0.0,0.0>
EOF

//-- Notecard must have the same name as the script plus ".cfg" added to the end (no quotes)
//-- You may have multiple notecards, each in a different language. to specify the
//--   language add the language code to the end of that. example: ".ja" for japanese
//-- Examples: "v7-D Zen Resizer.cfg.ja", or "v7-D Zen Resizer.cfg"
//--   the first would be used if the user had japanese as their SL client language
//--   the second would be used if no language could be found (or was not shared with object by the client)
//--     See [ http://wiki.secondlife.com/wiki/LlGetAgentLanguage ], for more details.

//-- text section explanation, replace with translated text, any missing line will use script defaults
//-- you may inlcude line breaks by using "\n" in these texts
//txt0 = <tell user we're reading the notecard> (this line should always be first in translations, and should ALWAYS be present)
//txt1 = <tell user we're going to reset reading the notecard because it timed out> (should always be the second line in translations)
//txt2 = <tell user: info missing, cannot resize>
//txt3 = <tell user: done reading notecard, ready to work>
//txt4 = <tell user: resizing the set> (in case the visual change isn't noticable)
//txt5 = <tell user: done resizing the set>
//txt6 = <tell user: saved current size>
//txt7 = <tell user: dialog timed out> (user took to long to make a choice, needs to reopen dialog to continue)
//txt8 = <Special: dialog box text to show user, the current percentage will be added to the end>

//-- button section explanation, replace with translated text, any missing line will use script defaults
//-- percentages must be from 0.01 to 100.00 (thoundands of whole percent)
//btn00 = <+/- percentage> (blank to disable)
//btn01 = <+/- percentage> (blank to disable)
//btn02 = <Closes Dialog>
//btn03 = <+/- percentage> (blank to disable)
//btn04 = <+/- percentage> (blank to disable)
//btn05 = <Reset to Saved Percentage>
//btn06 = <+/- percentage> (blank to disable)
//btn07 = <+/- percentage> (blank to disable)
//btn08 = <Save Current Percentage> (blank to disable)
//btn09 = <+/- percentage> (blank to disable)
//btn10 = <+/- percentage> (blank to disable)
//btn11 = <Remove Script> (blank to disable)

//-- Set value explanation: code from the prep script (remove this line to default to script or description field values)
//set = <0.0,0.0,0.0>

//-- "EOF" (no quotes) is a super comment, nothing after it will be read
Return to top

v7-D Zen Resizer (lite)

  1. Create a notecard and name it v7-D Zen Resizer (lite)
  2. Copy and paste the contents of the box below into it and save
/*//( v7-D Zen Resizer (lite) v1.4 )//*/

/*//-- Notes:
 Do Not Move/Rotate Object While It Is Resizing, it WILL break [LSL Limitation] (attached to moving av is safe)
 - a bad idea for physics objects, or objects with active move/rotation scripts, or object being edited
 (this limitation will be removed in the MONO Version I just haven't rewritten it yet)
 The gNfoSet Global, and uAdjSiz function can easily be reused in custom scripts
//*/

/*//-- Menu Variables --//*/
 //-- timeout for dialog listens and notecard reads
float    gFltTmt = 45.0;

 //-- Default Dialog Buttons
list     gLstBtn = ["+0.02%", "-0.02%", "Done",
                    "+0.2%", "-0.2%", "Recall",
                    "+2%", "-2%", "Save",
                    "+20%", "-20%", "-Script"];
 //-- Default User Text
list     gLstTxt = ["(v7-D Zen Resizer) Reading Notecard...",
                    "(v7-D Zen Resizer) Notecard Read Failed; Retrying...",
                    "(v7-D Zen Resizer) Ready.",
                    "(v7-D Zen Resizer) Set Info Missing; Resize Aborted.",
                    "(v7-D Zen Resizer) Resizing...",
                    "(v7-D Zen Resizer) Resize Done.",
                    "(v7-D Zen Resizer) Current Size Saved.",
                    "(v7-D Zen Resizer) Dialog Timed Out.",
                    "v7-D Zen Resizer v1.3\n\nCurrent Size:"];


/*//-- The Centerpiece Global, stores the  --//*/
rotation gNfoSet = <0.0, 0.0, 0.0, 0.0>;


/*//-- do not modify these variables. --//*/
 //-- key of the user given the resize dialog (also used to store the notecard request id)
key      gKeyMnu; 
 //-- channel the dialog will use (calculated per user) (also used to store the current notecard line)
integer  gIntChn;
 //-- stores the calculated name of the notecard (including translation if available)
string   gStrNCL;


 //-- Adjust Set Size
uAdjSiz( float vFltNew ){
     //-- clamp vFltNew to valid percentage [0.0, 1.0]
    vFltNew = (vFltNew * (vFltNew > 0.0) - 1.0) * (vFltNew < 1.0) + 1.0;
     //-- only run if previous percent greater or less than next percentage? (0 means the same)
    if ((vFltNew < gNfoSet.z) - (vFltNew > gNfoSet.z)){
         //-- get the current root size for comparison
        vector vSizOld = llGetScale();
         //-- save the new percentage to gNfoSet, and reuse gFltNew to save the relative change percentage
        vFltNew = (gNfoSet.x + gNfoSet.y * (gNfoSet.z = vFltNew)) / vSizOld.x;
        
         //-- intialize a temp list for holding child prims size/offset
        list vLstTmp;
         //-- get the number of prims for our loop + 1 (make loops cleaner later)
         //-- llGetObjectPrimCount doesn't count seated avs, but returns 0 for attachments
         //-- llGetNumberOfPrims works on attachments, but counts seated avs when detached
         //-- !!llGetAttached returns TRUE(1) if attached, or FALSE(0) if not, to cancel #ofPrims if unattached.
        integer  vIntCnt = ~-(llGetObjectPrimCount( llGetKey() ) +  llGetNumberOfPrims() * !!llGetAttached());
            //-- set the root prim separately since it's position will not change
        llSetLinkPrimitiveParamsFast( LINK_THIS, [PRIM_SIZE, vSizOld * vFltNew] );
        while (~-(--vIntCnt)){
            vLstTmp = llGetLinkPrimitiveParams( vIntCnt, [PRIM_SIZE, PRIM_POSITION] );
            llSetLinkPrimitiveParamsFast( vIntCnt,
                                          [PRIM_SIZE, llList2Vector( vLstTmp, 0 ) * vFltNew,
                                           PRIM_POS_LOCAL, llList2Vector( vLstTmp, 1 ) * vFltNew] );
        }
    }
}
    
 //-- Menu
uDialog(){
     //-- Format the Current Size Percentage to thousandths of percent
    string vStrPct = (string)llRound( gNfoSet.z * 10000.0 );
    if (llStringLength( vStrPct ) < 3){
        vStrPct = llGetSubString( "00" + vStrPct, -3 , -1 );
    }
     //-- Pop the dialog
    llDialog( gKeyMnu, llList2String( gLstTxt, 8 ) + llInsertString( vStrPct, llStringLength( vStrPct ) - 2, "." ) + "%", gLstBtn, gIntChn );
     //-- set a timeout to capture dialog cancelation and close the listen
    llSetTimerEvent( gFltTmt );
}

uChkNfo(){
     //-- are we missing linkset information?
    if (0.0 == gNfoSet.y){
         //-- set it from the description if it's available
        string vStrTmp = llGetObjectDesc();
        integer vIdxTmp = llSubStringIndex( vStrTmp, "set=" );
        if (~vIdxTmp){
            gNfoSet = (rotation)llGetSubString( vStrTmp, vIdxTmp + 4, 0xFFFFFFFF );
        }
    }
     //-- if we have a valid info set, make sure to set an accurate current percentage.
    if (gNfoSet.y){
        vector vSizTmp = llGetScale();
        gNfoSet.z = (vSizTmp.x - gNfoSet.x) / gNfoSet.y;
    }
}


default{
    state_entry(){
         //-- Check for language specific notecard
        if (~llGetInventoryType( gStrNCL = llGetScriptName() + ".cfg." + llGetAgentLanguage( llGetOwner() ) )){
         //-- check for default notecard
        }else if (~llGetInventoryType( gStrNCL = llGetScriptName() + ".cfg")){
        }else{
             //-- no notecard available
            gStrNCL = "";
        }
         //-- if there is a notecard, start reading it
        if (gStrNCL){
             //-- pre-use the av global to verify notecard reads
            gKeyMnu = llGetNotecardLine( gStrNCL, gIntChn );
             //-- set a timeout for notecard reads
            llSetTimerEvent( gFltTmt );
        }else{
             //-- make sure we have good information for the set
            uChkNfo();
             //-- fast timeout to avoid dumping changed events
            llSetTimerEvent( 0.01 );
        }
    }
    
    dataserver( key vKeyQry, string vStrDta ){
         //-- make sure this event was triggered by our script
        if (gKeyMnu == vKeyQry){
             //-- are we done reading the notecard?
            if (EOF == vStrDta || "EOF" == vStrDta){
                 //-- make sure we have good information for the set
                uChkNfo();
                 //-- clear key to signal that the notecard reads are done
                gKeyMnu = "";
                 //-- fast timeout to avoid dumping changed events
                llSetTimerEvent( 0.01 );
            }else{ //-- we have not reached the end of the notecard
                 //-- Strip comments and extra spaces, and see if there's anything left for us
                if (vStrDta = llStringTrim( llList2String( llParseStringKeepNulls( vStrDta, ["//"], [] ), 0 ), STRING_TRIM ) ){
                     //-- check if we have variable data to parse
                    integer vIdxTyp = llListFindList( ["set", "btn", "txt"], (list)llToLower( llGetSubString( vStrDta, 0, 2 ) ) );
                    if (~vIdxTyp){
                         //-- remove header and extra spaces
                        integer vIdxVar = (integer)llGetSubString( vStrDta, 3, ~-llSubStringIndex( vStrDta, "=" ) );
                        vStrDta = llStringTrim( llDeleteSubString( vStrDta, 0, llSubStringIndex( vStrDta, "=" ) ), STRING_TRIM );
                        if (2 & vIdxTyp){ //-- text
                             //-- replace default text with notecard text (line breaks corrected)
                            gLstTxt = llListReplaceList( gLstTxt, (list)llDumpList2String( llParseStringKeepNulls( vStrDta, ["\\n"], [] ), "\n" ), vIdxVar, vIdxVar );
                            if (!vIdxVar){
                                 //-- if we get the "reading notecard" translation, tell user immediately. (that's why that line goes first and is always included)
                                llOwnerSay( llList2String( gLstTxt, 0 ) );
                            }
                        }else if (1 & vIdxTyp){ //-- buttons
                             //-- replace default buton label with notecard button label
                            gLstBtn = llListReplaceList( gLstBtn, (list)vStrDta, vIdxVar, vIdxVar );
                        }else{ //-- set info
                             //-- replace default set info with notecard set info (this overrides the description field info)
                            gNfoSet = (rotation)vStrDta;
                        }
                    }
                }
                 //-- call the next line of the notecard
                gKeyMnu = llGetNotecardLine( gStrNCL, ++gIntChn );
                 //-- reset the notecard timeout
                llSetTimerEvent( gFltTmt );
            }
        }
    }
    
    timer(){
         //-- are we still trying to read a notecard?
        if (gKeyMnu){
            llOwnerSay( llList2String( gLstTxt, 1 ) );
            gKeyMnu = llGetNotecardLine( gStrNCL, gIntChn = 0 );
        }else{ //-- we are done with this state
             //-- tell the user we're ready
            llOwnerSay( llList2String( gLstTxt, 2 ) );
             //-- go to the ready state
            state sRdy;
        }
    }
    
    //-- if we change users, reset the script to detect language
    changed( integer vBitChg ){
        if (CHANGED_OWNER & vBitChg){
            llResetScript();
        }
    }
}

state sRdy{
    state_entry(){
         //-- clear timers set by other states
        llSetTimerEvent( 0.0 );
    }
    
     //-- oh look, outside script triggering =P
    link_message( integer vIntSrc, integer vIntAmt, string vStrCmd, key vKeyAvt ){
         //-- link messages to us must have string = script name
        if (llGetScriptName() == vStrCmd){
            if (vKeyAvt){
                 //-- if a key was sent open the dialog for that av
                gKeyMnu = vKeyAvt;
                state sRun;
            }else{
                 //-- much cooler, lets you build your own menu method, and trigger
                 //--  the resize by sending an integer in hundredths of percent
                 //-- -1 resets to default, <-1 saves the current percentage as default
                if (vIntAmt >> 31){ // neg value, it's a command
                    vIntAmt += 4; //-- reset range to positive, makes parse easier
                    if (vIntAmt > 0xFFFFFFFF){ //-- discard original values under -3
                        if (2 & vIntAmt){//-- CMD = recall
                            if (gNfoSet.y){ //-- check for prep values
                                uAdjSiz( gNfoSet.s );
                            }else{
                                //-- set failure flag
                                vIntAmt = 0xFFFFFFFF;
                            }
                        }else if (1 & vIntAmt){ //-- CMD = Save
                            gNfoSet.s = gNfoSet.z;
                        }else{
                             //-- CMD = remove script
                            llRemoveInventory( llGetScriptName() );
                            llMessageLinked( vIntSrc, 1, llGetScriptName() + "_", "" );
                        }
                    }
                }else{ //-- positive value, CMD = set custom percentage
                    if (gNfoSet.y){ //-- check for prep values
                        uAdjSiz( vIntAmt / 10000.0 );
                    }else{
                        //-- set Failure Flag
                        vIntAmt = 0xFFFFFFFF;
                    }
                }
                llMessageLinked( vIntSrc, !(vIntAmt >> 31), llGetScriptName() + "_", "" );
            }
        }
    }
    
     //-- or lame old hold for 2sec trigger for the owner
    touch_start( integer vIntNul ){
        llResetTime();
    }
    
    touch_end( integer vIntNul ){
         //-- test to see if touch lasted longer than 1 second
        if ((integer)llGetTime()){
             //-- was it the owner?
            if ((gKeyMnu = llGetOwner()) == llDetectedKey( 0 )){
                 //-- send em to the dialog state
                state sRun;
            }
        }
    }
    
     //-- if owner changes, jump back to default to retry language detection
    changed( integer vBitChg ){
        if (CHANGED_OWNER & vBitChg){
            state default;
        }
    }
}

 //-- this state is a pointless exercise in a generic menuing
 //-- system. you could replace it with just about any menu style
state sRun{
    state_entry(){
         //-- set up a semi-unique channel based on the av we're serving
        gIntChn = (integer)("0xF" + llGetSubString( gKeyMnu, 0, 6 ));
         //-- open a listen on that channel to that av
        llListen( gIntChn, "", gKeyMnu, "" );
         //-- send them a dialg
        uDialog();
    }
    
    listen( integer vIntNul, string vStrNul, key vKeyNul, string vStrCmd ){
         //-- which dialog button was pressed
        integer vIdxCmd = llListFindList( gLstBtn, (list)vStrCmd );
         //-- do we have a valid command
        if (~vIdxCmd){
             //-- only process non-blank buttons
            if (vStrCmd){
                 //-- is it in the right hand column
                if (vIdxCmd % 3 == 2){
                     //-- get smaller indexes so we can parse faster
                    vIdxCmd /= 3;
                    if (2 & vIdxCmd){ if (1 & vIdxCmd){
                         //-- original index = 11: remove script
                        llRemoveInventory( llGetScriptName() );
                         //-- inventory removal may fire slow, avoid triggering a new dialog
                        return;
                    }else{
                         //-- original index = 8: save default
                        gNfoSet.s = gNfoSet.z;
                         //-- tell the user
                        llOwnerSay( llList2String( gLstTxt, 6 ) );
                    } }else if (1 & vIdxCmd){
                          //-- original index = 5: restore default size
                         if (gNfoSet.y){ //-- make sure we have valid information
                             //-- tell user we started resizing
                            llOwnerSay( llList2String( gLstTxt, 4 ) );
                            uAdjSiz( gNfoSet.s );
                             //-- tell user we're done resizing
                            llOwnerSay( llList2String( gLstTxt, 5 ) ); 
                        }else{
                             //-- prep variable missing, abort
                            llOwnerSay( llList2String( gLstTxt, 3 ) );
                        }
                    }else{
                         //-- original index = 2: exit menu
                        state sRdy;
                    }
                 //-- must be a resize amount, apply it if we have good prep
                }else if (gNfoSet.y){
                     //-- tell user we started resizing
                    llOwnerSay( llList2String( gLstTxt, 4 ) );
                    uAdjSiz( (float)vStrCmd / 100.0 + gNfoSet.z );
                     //-- tell user we're done resizing
                    llOwnerSay( llList2String( gLstTxt, 5 ) );
                }else{
                     //-- prep variable missing, abort
                    llOwnerSay( llList2String( gLstTxt, 3 ) );
                }
            }
             //-- retrigger the dialog
            uDialog();
        }
    }
    
    timer(){
         //-- tell the user they took too long to respond
        llOwnerSay( llList2String( gLstTxt, 7 ) );
         //-- go back to waiting
        state sRdy;
    }
    
     //-- if owner changes, jump back to default to retry language detection
    changed( integer vBitChg ){
        if (CHANGED_OWNER & vBitChg){
            state default;
        }
    }
}

/*//--                           License Text                           --//*/
/*//  Free to copy, use, modify, distribute, or sell, with attribution.   //*/
/*//    (C)2010 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]    //*/
/*//   Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  All usages must contain a plain text copy of the previous 2 lines.  //*/
/*//--                                                                  --//*/
Return to top

v7-D Zen Resizer: User Manual

  1. Create a notecard and name it v7-D Zen Resizer: User Manual
  2. Copy and paste the contents of the box below into it and save
To Open the v7-D Zen Resizer Menu, click on your product, hold for 2 seconds then release.

If you recieve a Message in chat that the dialog Timed out, repeat the above step to continue

Click on a dialog button to use the function listed
- "Save" will save the current size as default
- "-Script" will remove the "v7-D Zen Resizer" script from your object permanently
- "Recall" will reset the objects size to the last saved size
- "Done" will cancel the dialog
- All other dialog buttons will modify the size of your object by the listed amount to a minimum of 0.00% and a maximum of 100.00%


v7-D Zen Resizer
(C)2010 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]
Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]
Return to top

Questions or Comments?

Feel free to leave me a note on my User Talk page.