Difference between revisions of "Linkset Resizer 2"

From Second Life Wiki
Jump to navigation Jump to search
m (<lsl> tag to <source>)
 
(3 intermediate revisions by one other user not shown)
Line 30: Line 30:
== Resizer ==
== Resizer ==
<div style="padding: 0.5em">
<div style="padding: 0.5em">
<lsl>
<source lang="lsl2">
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Resizer
// Resizer
Line 48: Line 48:
// If using in a product with no other scripts, change START_ON_TOUCH below to TRUE
// If using in a product with no other scripts, change START_ON_TOUCH below to TRUE
// so user can initiate resizing by just touching the object.
// so user can initiate resizing by just touching the object.
 
integer START_ON_TOUCH = FALSE;
integer START_ON_TOUCH = FALSE;
 
// Display status messages in chat window (to owner only)
// Display status messages in chat window (to owner only)
 
integer SAY_STATUS = TRUE;
integer SAY_STATUS = TRUE;
 
// Channel to listen for commands on
// Channel to listen for commands on
 
integer CHAT_CHANNEL = 1;
integer CHAT_CHANNEL = 1;
 
// SL constraints
// SL constraints
 
float MIN_SIZE = .01;
float MIN_SIZE = .01;
float MAX_SIZE = 10;
float MAX_SIZE = 10;
float MAX_DISTANCE = 10;  
float MAX_DISTANCE = 10;  
float MIN_SCALE = .1;
float MIN_SCALE = .1;
 
integer MENU_CHANNEL = -1001;
integer MENU_CHANNEL = -1001;
   
   
list backupPrims = [];
list backupPrims = [];
integer backupStored = FALSE;
integer backupStored = FALSE;
 
float scale = 1.0;
float scale = 1.0;
 
init_menu_channel() {
init_menu_channel() {
     MENU_CHANNEL = ((integer)("0x" + llGetSubString((string)llGetKey(), -8, -1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
     MENU_CHANNEL = ((integer)("0x" + llGetSubString((string)llGetKey(), -8, -1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
}
}
 
say_status(string msg) {
say_status(string msg) {
     if (SAY_STATUS) llOwnerSay(msg);
     if (SAY_STATUS) llOwnerSay(msg);
}
}
 
backup() {
backup() {
     if (!backupStored) {
     if (!backupStored) {
Line 107: Line 107:
}
}
   
   
restore() {
    if (backupStored) {
        say_status("Restoring previously backed up positions and sizes.");
        integer p = llGetNumberOfPrims();
        integer i = 0;
        for (i = 1; i <= p; i++)
        {
            vector pos = llList2Vector(backupPrims, (i - 1) * 2);
            vector size = llList2Vector(backupPrims, ((i - 1) * 2) + 1);
            if (i == 1) {
                llSetLinkPrimitiveParamsFast(i, [PRIM_SIZE, size]);
            }
            else {
                llSetLinkPrimitiveParamsFast(i, [PRIM_POSITION, pos, PRIM_SIZE, size]);
            }
        }
        say_status("Previously backed up prim positions and sizes restored.");
    }
    scale = 1;
}
finish() {
    say_status("Deleting Resizer script.");
    llRemoveInventory(llGetScriptName());
}
float min(float a, float b) {
float min(float a, float b) {
     if (a < b) return a;
     if (a < b) return a;
     return b;
     return b;
}
}
 
float max(float a, float b) {
float max(float a, float b) {
     if (a > b) return a;
     if (a > b) return a;
     return b;
     return b;
}
}
 
float constrainMinMax(float value, float min, float max) {
float constrainMinMax(float value, float min, float max) {
     value = max(value, min);
     value = max(value, min);
Line 148: Line 122:
     return value;
     return value;
}
}
 
float constrainSize(float size) {
vector constrainSize(vector size) {
     return constrainMinMax(size, MIN_SIZE, MAX_SIZE);
     size.x = constrainMinMax(size.x, MIN_SIZE, MAX_SIZE);
    size.y = constrainMinMax(size.y, MIN_SIZE, MAX_SIZE);
    size.z = constrainMinMax(size.z, MIN_SIZE, MAX_SIZE);
    return size;
}
}
 
float constrainDistance(float distance) {
vector constrainDistance(vector delta) {
     return min(distance, MAX_DISTANCE);
     delta.x = min(delta.x, MAX_DISTANCE);
    delta.y = min(delta.y, MAX_DISTANCE);
    delta.z = min(delta.z, MAX_DISTANCE);
    return delta;
}
}
   
   
process() {
process(integer restore) {
     backup();
     backup();
 
     say_status("Resizing prims to " + (string)llRound(scale * 100) + "% of original size.");
     if (restore) {
        say_status("Restoring previously backed up positions and sizes.");
        scale = 1;
    }
    else {
        say_status("Resizing prims to " + (string)llRound(scale * 100) + "% of original size.");
    }
       
     integer p = llGetNumberOfPrims();
     integer p = llGetNumberOfPrims();
     integer i = 0;
     integer i = 0;
Line 168: Line 155:
         vector size = llList2Vector(backupPrims, ((i - 1) * 2) + 1);
         vector size = llList2Vector(backupPrims, ((i - 1) * 2) + 1);
   
   
         size.x = constrainSize(size.x * scale);
         if (!restore) size = constrainSize(size * scale);
        size.y = constrainSize(size.y * scale);
        size.z = constrainSize(size.z * scale);
 
         if (i == 1) {
         if (i == 1) {
             llSetLinkPrimitiveParamsFast(i, [PRIM_SIZE, size]);
             llSetLinkPrimitiveParamsFast(i, [PRIM_SIZE, size]);
         }
         }
         else {
         else {
             pos = pos * scale;
             if (!restore) pos = constrainDistance(pos * scale);
            pos.x = constrainDistance(pos.x);
            pos.y = constrainDistance(pos.y);
            pos.z = constrainDistance(pos.z);
             llSetLinkPrimitiveParamsFast(i, [PRIM_POSITION, pos, PRIM_SIZE, size]);
             llSetLinkPrimitiveParamsFast(i, [PRIM_POSITION, pos, PRIM_SIZE, size]);
         }
         }
     }
     }
     say_status("Prims resized.");
      
    if (restore) {
        say_status("Previously backed up prim positions and sizes restored.");
    }
    else {
        say_status("Prims resized.");
    }
}
finish() {
    say_status("Deleting Resizer script.");
    llRemoveInventory(llGetScriptName());  
}
}
 
menu() {
menu() {
     llDialog(llGetOwner(),
     llDialog(llGetOwner(),
Line 191: Line 184:
     ["Revert", "-", "Finish", "-1%", "-5%", "-10%", "+1%", "+5%", "+10%"], MENU_CHANNEL);
     ["Revert", "-", "Finish", "-1%", "-5%", "-10%", "+1%", "+5%", "+10%"], MENU_CHANNEL);
}
}
 
handle_message(integer channel, string name, key id, string message)  
handle_message(integer channel, string name, key id, string message)  
{
{
Line 205: Line 198:
                     scale = (((float)llGetSubString(scale_param, 0, -2)) / 100);
                     scale = (((float)llGetSubString(scale_param, 0, -2)) / 100);
                     scale = max(scale, MIN_SCALE);
                     scale = max(scale, MIN_SCALE);
                     process();
                     process(FALSE);
                 }
                 }
             }
             }
Line 212: Line 205:
     else if (channel == MENU_CHANNEL) {
     else if (channel == MENU_CHANNEL) {
         if (message == "Revert") {
         if (message == "Revert") {
             restore();
             process(TRUE);
             menu();
             menu();
         }
         }
Line 221: Line 214:
             scale = scale + (((float)llGetSubString(message, 0, -2)) / 100);
             scale = scale + (((float)llGetSubString(message, 0, -2)) / 100);
             scale = max(scale, MIN_SCALE);
             scale = max(scale, MIN_SCALE);
             process();
             process(FALSE);
             menu();
             menu();
         }
         }
     }
     }
 
}
}
 
default
default
{
{
Line 240: Line 233:
         else {
         else {
             llListen(CHAT_CHANNEL, "", llGetOwner(), "");
             llListen(CHAT_CHANNEL, "", llGetOwner(), "");
           
             init_menu_channel();
             init_menu_channel();
             llListen(MENU_CHANNEL, "", llGetOwner(), "");
             llListen(MENU_CHANNEL, "", llGetOwner(), "");
           
             llOwnerSay("Resizer Ready");
             llOwnerSay("Resizer Ready");
             llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
             llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
Line 259: Line 252:
     }
     }
}
}
 
state start_on_touch
state start_on_touch
{
{
Line 265: Line 258:
     {
     {
         llListen(CHAT_CHANNEL, "", llGetOwner(), "");
         llListen(CHAT_CHANNEL, "", llGetOwner(), "");
       
         init_menu_channel();
         init_menu_channel();
         llListen(MENU_CHANNEL, "", llGetOwner(), "");
         llListen(MENU_CHANNEL, "", llGetOwner(), "");
       
         llOwnerSay("Resizer Ready");
         llOwnerSay("Resizer Ready");
         llOwnerSay("Touch for resizer menu.");
         llOwnerSay("Touch for resizer menu.");
Line 282: Line 275:
         handle_message(channel, name, id, message);
         handle_message(channel, name, id, message);
     }
     }
   
     touch_start(integer num_detected)
     touch_start(integer num_detected)
     {
     {
         menu();
         menu();
     }
     }
 
}
}




 
</source>
</lsl>
</div></div>
</div></div>
{{#vardefine:sort|Fix Small Prims}}{{LSLC|Library}}
{{#vardefine:sort|Link Resizer 2}}{{LSLC|Library}}

Latest revision as of 22:30, 24 January 2015

About

Resizer by Emma Nowhere

Yet another object resizer script. Seeing as I was the person who originally opened the JIRA for LLGetLinkPrimitiveParams I thought I should put it to good use. I like it more than the other resizer scripts out there, but of course, I'm biased. In any case, it never hurts to have more code being shared.

How to use with menu:

  1. Install this script in the root prim of a linked set of prims (aka "linkset")
  2. Type /1resizer to show the menu
  3. Hit the appropriate buttons to scale up or down the linkset
  4. Hit the "Finish" button to remove the script and finalize prim sizes

Optionally, enter the percentage directly via chat by typing /1resizer x% where x is the percentage of the original size you want to resize to.

IMPORTANT: You should always make a backup copy of the object before using this script.

The script below is configured to be used as a drop-in script for a user or builder that wants to resize something for themselves. If putting into a product, you may want to set START_ON_TOUCH to be TRUE so that your customers can just touch the object to start resizing. You may also want to set SAY_STATUS to FALSE so that a bunch of text doesn't get sent to the chat window (only seen by the owner, but can still be annoying to the end-user).

Resizer

///////////////////////////////////////////////////////////////////////////////
// Resizer
// by Emma Nowhere
//
// Last modified: 6/1/2010
//
// How to use with menu:
// 1. Install this script in the root prim of a linked set of prims (aka "linkset")
// 2. Type /1resizer to show the menu
// 3. Hit the appropriate buttons to scale up or down the linkset
// 4. Hit the "Finish" button to remove the script and finalize prim sizes
//
// Optionally, enter the percentage directly via chat by typing /1resizer x%
// where x is the percentage of the original size you want to resize to.
//
// If using in a product with no other scripts, change START_ON_TOUCH below to TRUE
// so user can initiate resizing by just touching the object.
 
integer START_ON_TOUCH = FALSE;
 
// Display status messages in chat window (to owner only)
 
integer SAY_STATUS = TRUE;
 
// Channel to listen for commands on
 
integer CHAT_CHANNEL = 1;
 
// SL constraints
 
float MIN_SIZE = .01;
float MAX_SIZE = 10;
float MAX_DISTANCE = 10; 
float MIN_SCALE = .1;
 
integer MENU_CHANNEL = -1001;
 
list backupPrims = [];
integer backupStored = FALSE;
 
float scale = 1.0;
 
init_menu_channel() {
    MENU_CHANNEL = ((integer)("0x" + llGetSubString((string)llGetKey(), -8, -1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF;
}
 
say_status(string msg) {
    if (SAY_STATUS) llOwnerSay(msg);
}
 
backup() {
    if (!backupStored) {
        say_status("Backing up prim positions and sizes.");
        backupPrims = [];
        integer p = llGetNumberOfPrims();
        integer i = 0;
        vector root_pos = <0, 0, 0>;
        for (i = 1; i <= p; i++)
        {
            list params = llGetLinkPrimitiveParams(i, [PRIM_POSITION, PRIM_SIZE]);
            vector pos = llList2Vector(params, 0);
            vector size = llList2Vector(params, 1);
            if (i == 1)
            {
                root_pos = pos;
            }
            else {
                pos = pos - root_pos;
            }
            backupPrims = backupPrims + pos + size;
        }
        backupStored = TRUE;
        say_status("Prim positions and sizes backed up.");
    }
}
 
float min(float a, float b) {
    if (a < b) return a;
    return b;
}
 
float max(float a, float b) {
    if (a > b) return a;
    return b;
}
 
float constrainMinMax(float value, float min, float max) {
    value = max(value, min);
    value = min(value, max);
    return value;
}
 
vector constrainSize(vector size) {
    size.x = constrainMinMax(size.x, MIN_SIZE, MAX_SIZE);
    size.y = constrainMinMax(size.y, MIN_SIZE, MAX_SIZE);
    size.z = constrainMinMax(size.z, MIN_SIZE, MAX_SIZE);
    return size;
}
 
vector constrainDistance(vector delta) {
    delta.x = min(delta.x, MAX_DISTANCE);
    delta.y = min(delta.y, MAX_DISTANCE);
    delta.z = min(delta.z, MAX_DISTANCE);
    return delta;
}
 
process(integer restore) {
    backup();

    if (restore) {
        say_status("Restoring previously backed up positions and sizes.");
        scale = 1;
    }
    else {
        say_status("Resizing prims to " + (string)llRound(scale * 100) + "% of original size.");
    }
        
    integer p = llGetNumberOfPrims();
    integer i = 0;
    for (i = 1; i <= p; i++)
    {
        vector pos = llList2Vector(backupPrims, (i - 1) * 2);
        vector size = llList2Vector(backupPrims, ((i - 1) * 2) + 1);
 
        if (!restore) size = constrainSize(size * scale);
 
        if (i == 1) {
            llSetLinkPrimitiveParamsFast(i, [PRIM_SIZE, size]);
        }
        else {
            if (!restore) pos = constrainDistance(pos * scale);
            llSetLinkPrimitiveParamsFast(i, [PRIM_POSITION, pos, PRIM_SIZE, size]);
        }
    }
    
    if (restore) {
        say_status("Previously backed up prim positions and sizes restored.");
    }
    else {
        say_status("Prims resized.");
    }
}
 
finish() {
    say_status("Deleting Resizer script.");
    llRemoveInventory(llGetScriptName()); 
}
 
menu() {
    llDialog(llGetOwner(),
    "Resizer\n\nMake a backup of your object first.\n\nPlease choose an option:\n",
    ["Revert", "-", "Finish", "-1%", "-5%", "-10%", "+1%", "+5%", "+10%"], MENU_CHANNEL);
}
 
handle_message(integer channel, string name, key id, string message) 
{
    if (channel == CHAT_CHANNEL) {
        if (message == "resizer") {
            menu();
        }
        else if (llSubStringIndex(message, "resizer") == 0) {  
            list params = llParseString2List(message, [" "], [] );
            if (llGetListLength(params) == 2) {
                string scale_param = llList2String(params, 1);
                if (llGetSubString(scale_param, -1, -1) == "%") {
                    scale = (((float)llGetSubString(scale_param, 0, -2)) / 100);
                    scale = max(scale, MIN_SCALE);
                    process(FALSE);
                }
            }
        }
    }
    else if (channel == MENU_CHANNEL) {
        if (message == "Revert") {
            process(TRUE);
            menu();
        }
        else if (message == "Finish") {        
            finish();                    
        }
        else if (llGetSubString(message, -1, -1) == "%") {
            scale = scale + (((float)llGetSubString(message, 0, -2)) / 100);
            scale = max(scale, MIN_SCALE);
            process(FALSE);
            menu();
        }
    }
 
}
 
default
{
    state_entry() 
    {
        if (START_ON_TOUCH) {
            // we only want a touch_start handler if we're going to use it
            // so change state rather than just testing inside touch_start
            // for START_ON_TOUCH to be true.
            state start_on_touch;
        }
        else {
            llListen(CHAT_CHANNEL, "", llGetOwner(), "");
 
            init_menu_channel();
            llListen(MENU_CHANNEL, "", llGetOwner(), "");
 
            llOwnerSay("Resizer Ready");
            llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
        }
    }
 
    on_rez(integer start_param) {
        llOwnerSay("Resizer Installed");
        llOwnerSay("Type /" + (string)CHAT_CHANNEL + "resizer for menu.");
    }    
 
    listen(integer channel, string name, key id, string message) 
    {
        handle_message(channel, name, id, message);
    }
}
 
state start_on_touch
{
    state_entry() 
    {
        llListen(CHAT_CHANNEL, "", llGetOwner(), "");
 
        init_menu_channel();
        llListen(MENU_CHANNEL, "", llGetOwner(), "");
 
        llOwnerSay("Resizer Ready");
        llOwnerSay("Touch for resizer menu.");
    }
 
    on_rez(integer start_param) {
        llOwnerSay("Resizer Installed");
        llOwnerSay("Touch for resizer menu.");
    }    
 
    listen(integer channel, string name, key id, string message) 
    {
        handle_message(channel, name, id, message);
    }
 
    touch_start(integer num_detected)
    {
        menu();
    }
 
}