Difference between revisions of "Linkset resizer with menu"

From Second Life Wiki
Jump to: navigation, search
(A menu-driven script that allows to resize arbitrary linksets. The script is based on Linkset resizer by Maestro Linden.)
 
(the trick explained no longer works, provide link)
 
(15 intermediate revisions by 5 users not shown)
Line 3: Line 3:
 
==== A single script that rescales every prim in a linkset====
 
==== A single script that rescales every prim in a linkset====
 
by [[User:Brilliant Scientist|Brilliant Scientist]], 25th April 2010
 
by [[User:Brilliant Scientist|Brilliant Scientist]], 25th April 2010
 +
 +
Updated and heavily modified by [[User:Sei Lisa|Sei Lisa]], 8th July 2015
  
 
This script uses the [[LlGetLinkPrimitiveParams|llGetLinkPrimitiveParams()]] and [[LlSetLinkPrimitiveParamsFast|llSetLinkPrimitiveParamsFast()]] functions introduced in server 1.38 to rescale every prim in an arbitrary linkset. Based on [[Linkset resizer]] script by [[User:Maestro Linden|Maestro Linden]].  
 
This script uses the [[LlGetLinkPrimitiveParams|llGetLinkPrimitiveParams()]] and [[LlSetLinkPrimitiveParamsFast|llSetLinkPrimitiveParamsFast()]] functions introduced in server 1.38 to rescale every prim in an arbitrary linkset. Based on [[Linkset resizer]] script by [[User:Maestro Linden|Maestro Linden]].  
  
The main differences are between the two scripts are:  
+
The main differences between the two scripts are:  
 +
 
 +
* this script is menu-controlled
 +
* the script's listen channel is generated dynamically
 +
* more comments in the code for beginner scripters
 +
* it's just less chatty
 +
 
 +
The main differences with the previous version are:
 +
 
 +
* modernized to use more recent features (it considers linkability rules now)
 +
* works with single-prim objects too now
 +
* closes the listener after a timeout
 +
* keeps the menu open until explicitly cancelled
 +
* MIN SIZE and MAX SIZE are commented out (but they can be enabled by removing the comment marks)
 +
* cancelling the DELETE option no longer resizes the linkset to the same size (it was a waste of resources)
 +
* no longer limited to 10m size per prim
  
<ul>
+
<br><b>Special thanks to:</b><br>
<li>this script is menu-controlled</li>
+
[[User:Ann Otoole|Ann Otoole]] for contributing with a script removal function. The source code on this wiki page has been modified to reflect this contribution.
<li>the script's listen channel is generated dynamically</li>
+
<br>
<li>more comments in the code for beginner scripters</li>
+
<li>it's just less chatty</li>
+
</ul>
+
  
 
==== Source Code ====
 
==== Source Code ====
  
<lsl>
+
<source lang="lsl2">
 
// Linkset Resizer with Menu
 
// Linkset Resizer with Menu
// version 1.00 (25.04.2010)
+
// version 1.50 (2015-07-08)
// by: Brilliant Scientist
+
// by: Brilliant Scientist and Sei Lisa
 +
// © Copyright 2015 Sei Lisa
 
// --
 
// --
// This script resizes all prims in a linkset, the process is controlled via a menu.
+
// This script resizes all prims in a linkset, or a single prim.
// The script works on arbitrary linksets and requires no configuration.
+
// The process is controlled via a menu.
// The number of prims of the linkset it can process is limited only by the script's memory.
+
// The script works on arbitrary objects and requires no configuration.
 
// The script is based on "Linkset Resizer" script by Maestro Linden.
 
// The script is based on "Linkset Resizer" script by Maestro Linden.
 
// http://wiki.secondlife.com/wiki/Linkset_resizer
 
// http://wiki.secondlife.com/wiki/Linkset_resizer
// This script still doesn't check prim linkability rules, which are described in:
+
// Special thanks to:
// http://wiki.secondlife.com/wiki/Linkability_Rules
+
// Ann Otoole
  
float MIN_DIMENSION=0.01; // the minimum cur_scale of a prim allowed, in any dimension
+
float DialogTimeout = 180; // how many seconds before removing the listener
float MAX_DIMENSION=10.0; // the maximum cur_scale of a prim allowed, in any dimension
+
  
 
float max_scale;
 
float max_scale;
Line 37: Line 51:
  
 
float  cur_scale = 1.0;
 
float  cur_scale = 1.0;
integer handle;
+
integer handle = 0;
 
integer menuChan;
 
integer menuChan;
 
float min_original_scale=10.0; // minimum x/y/z component of the scales in the linkset
 
float max_original_scale=0.0; // minimum x/y/z component of the scales in the linkset
 
  
 
list link_scales = [];
 
list link_scales = [];
Line 48: Line 59:
 
makeMenu()
 
makeMenu()
 
{
 
{
llListenRemove(handle);
+
    if (!handle)
menuChan = 50000 + (integer)llFrand(50000.00);
+
    {
handle = llListen(menuChan,"",llGetOwner(),"");
+
        menuChan = 500000 + (integer)llFrand(500000);
 +
        handle = llListen(menuChan, "", llGetOwner(), "");
 +
    }
 +
    llSetTimerEvent(DialogTimeout);
  
//the button values can be changed i.e. you can set a value like "-1.00" or "+2.00"
+
    //the button values can be changed i.e. you can set a value like "-1.00" or "+2.00"
//and it will work without changing anything else in the script
+
    //and it will work without changing anything else in the script
llDialog(llGetOwner(),"Max scale: "+(string)max_scale+"\nMin scale: "+(string)min_scale+"\n \nCurrent scale:"+
+
    llDialog(llGetOwner(), "Max scale: " + (string)max_scale + "\nMin scale: " + (string)min_scale
        (string)cur_scale,["-0.50","-0.25","-0.10","+0.05","0.00","-0.05","+0.10","+0.25","+0.50","MIN SIZE","RESTORE",
+
        + "\n\nCurrent scale: "+ (string)cur_scale,
        "MAX SIZE"],menuChan);
+
        ["-0.05", "-0.10", "-0.25", "+0.05", "+0.10", "+0.25", /*"MIN SIZE",*/ "RESTORE", /*"MAX SIZE",*/ "CLOSE", "DELETE..."],
 +
        menuChan);
 
}
 
}
  
integer scanLinkset()
+
scanLinkset()
 
{
 
{
integer link_qty = llGetNumberOfPrims();
+
    integer link_qty = llGetNumberOfPrims();
integer link_idx;
+
    integer link_idx;
vector link_pos;
+
    integer link_ofs = (link_qty != 1); // add 1 if more than one prim (as linksets start numbering with 1)
vector link_scale;
+
    list params;
  
//script made specifically for linksets, not for single prims
+
    for (link_idx = 0; link_idx < link_qty; ++link_idx)
if (link_qty > 1)
+
    {
{
+
        params = llGetLinkPrimitiveParams(link_idx + link_ofs, [PRIM_POS_LOCAL, PRIM_SIZE]);
//link numbering in linksets starts with 1
+
for (link_idx=1; link_idx <= link_qty; link_idx++)
+
{
+
link_pos=llList2Vector(llGetLinkPrimitiveParams(link_idx,[PRIM_POSITION]),0);
+
link_scale=llList2Vector(llGetLinkPrimitiveParams(link_idx,[PRIM_SIZE]),0);
+
  
// determine the minimum and maximum prim scales in the linkset,
+
        link_positions += llList2Vector(params, 0);
// so that rescaling doesn't fail due to prim cur_scale limitations
+
        link_scales    += llList2Vector(params, 1);
if(link_scale.x<min_original_scale) min_original_scale=link_scale.x;
+
    }
else if(link_scale.x>max_original_scale) max_original_scale=link_scale.x;
+
if(link_scale.y<min_original_scale) min_original_scale=link_scale.y;
+
else if(link_scale.y>max_original_scale) max_original_scale=link_scale.y;
+
if(link_scale.z<min_original_scale) min_original_scale=link_scale.z;
+
else if(link_scale.z>max_original_scale) max_original_scale=link_scale.z;
+
  
link_scales    += link_scale;
+
    max_scale = llGetMaxScaleFactor() * 0.999999;
link_positions +=[(link_pos-llGetRootPosition())/llGetRootRotation()];
+
    min_scale = llGetMinScaleFactor() * 1.000001;
}
+
}
+
else
+
{
+
llOwnerSay("error: this script doesn't work for non-linked objects");
+
return FALSE;
+
}
+
 
+
max_scale = MAX_DIMENSION/max_original_scale;
+
min_scale = MIN_DIMENSION/min_original_scale;
+
 
+
return TRUE;
+
 
}
 
}
  
 
resizeObject(float scale)
 
resizeObject(float scale)
 
{
 
{
integer link_qty = llGetNumberOfPrims();
+
    integer link_qty = llGetNumberOfPrims();
integer link_idx;
+
    integer link_idx;
vector new_size;
+
    integer link_ofs = (link_qty != 1);
vector new_pos;
+
  
if (link_qty > 1)
+
    // scale the root
{
+
    llSetLinkPrimitiveParamsFast(link_ofs, [PRIM_SIZE, scale * llList2Vector(link_scales, 0)]);
//link numbering in linksets starts with 1
+
    // scale all but the root
for (link_idx=1; link_idx <= link_qty; link_idx++)
+
    for (link_idx = 1; link_idx < link_qty; link_idx++)
{
+
    {
new_size  = scale * llList2Vector(link_scales, link_idx-1);
+
        llSetLinkPrimitiveParamsFast(link_idx + link_ofs,
new_pos    = scale * llList2Vector(link_positions, link_idx-1);
+
            [PRIM_SIZE,      scale * llList2Vector(link_scales, link_idx),
 
+
            PRIM_POS_LOCAL, scale * llList2Vector(link_positions, link_idx)]);
if (link_idx == 1)
+
    }
{
+
//because we don't really want to move the root prim as it moves the whole object
+
llSetLinkPrimitiveParamsFast(link_idx, [PRIM_SIZE, new_size]);
+
}
+
else
+
{
+
llSetLinkPrimitiveParamsFast(link_idx, [PRIM_SIZE, new_size, PRIM_POSITION, new_pos]);
+
}
+
}
+
}
+
 
}
 
}
  
 
default
 
default
 
{
 
{
state_entry()
+
    state_entry()
{
+
    {
if (scanLinkset())
+
        scanLinkset();
{
+
    }
//llOwnerSay("resizer script ready");
+
}
+
else
+
{
+
llRemoveInventory(llGetScriptName());
+
}
+
}
+
  
touch_start(integer total)
+
    touch_start(integer total)
{
+
    {
if (llDetectedKey(0) == llGetOwner()) makeMenu();
+
        if (llDetectedKey(0) == llGetOwner())
}
+
            makeMenu();
 +
    }
  
listen(integer channel, string name, key id, string msg)
+
    timer()
{
+
    {
//you can never be too secure
+
        llListenRemove(handle);
if (id == llGetOwner())
+
        handle = 0;
{
+
        llSetTimerEvent(0);
if (msg == "RESTORE")
+
    }
{
+
cur_scale = 1.0;
+
}
+
else if (msg == "MIN SIZE")
+
{
+
cur_scale = min_scale;
+
}
+
else if (msg == "MAX SIZE")
+
{
+
cur_scale = max_scale;
+
}
+
else
+
{
+
cur_scale += (float)msg;
+
}
+
  
//check that the scale doesn't go beyond the bounds
+
    listen(integer channel, string name, key id, string msg)
if (cur_scale > max_scale) { cur_scale = max_scale; }
+
    {
if (cur_scale < min_scale) { cur_scale = min_scale; }
+
        if (msg == "RESTORE")
 +
        {
 +
            cur_scale = 1.0;
 +
        }
 +
        else if (msg == "MIN SIZE")
 +
        {
 +
            cur_scale = min_scale;
 +
        }
 +
        else if (msg == "MAX SIZE")
 +
        {
 +
            cur_scale = max_scale;
 +
        }
 +
        else if (msg == "DELETE...")
 +
        {
 +
            llDialog(llGetOwner(),"Are you sure you want to delete the resizer script?",
 +
                ["DELETE","CANCEL"],menuChan);
 +
            llSetTimerEvent(DialogTimeout);
 +
            return;
 +
        }
 +
        else if (msg == "DELETE")
 +
        {
 +
            llOwnerSay("Deleting resizer script...");
 +
            llRemoveInventory(llGetScriptName());
 +
            return; // prevents the menu from showing - llRemoveInventory is not instant
 +
        }
 +
        else if (msg == "CANCEL")
 +
        {
 +
            // ignore but it will re-show the menu as it falls through
 +
        }
 +
        else if (msg == "CLOSE")
 +
        {
 +
            llListenRemove(handle);
 +
            handle = 0;
 +
            llSetTimerEvent(0);
 +
            return; // prevents the menu from showing
 +
        }
 +
        else
 +
        {
 +
            cur_scale += (float)msg;
 +
        }
  
resizeObject(cur_scale);
+
        //check that the scale doesn't go beyond the bounds
}
+
        if (cur_scale > max_scale) { cur_scale = max_scale; }
}
+
        if (cur_scale < min_scale) { cur_scale = min_scale; }
 +
 
 +
        resizeObject(cur_scale);
 +
        makeMenu();
 +
    }
 
}
 
}
</lsl>
+
</source>
 +
 
 +
 
 +
----
 +
 
 +
For information about using a resizer to handle nanoprims, check this older version: [http://wiki.secondlife.com/w/index.php?title=Linkset_resizer_with_menu&oldid=1194741#Crunching_and_Inflating]
 +
 
 
[[Category:LSL Examples]]
 
[[Category:LSL Examples]]

Latest revision as of 12:16, 9 July 2015

A single script that rescales every prim in a linkset

by Brilliant Scientist, 25th April 2010

Updated and heavily modified by Sei Lisa, 8th July 2015

This script uses the llGetLinkPrimitiveParams() and llSetLinkPrimitiveParamsFast() functions introduced in server 1.38 to rescale every prim in an arbitrary linkset. Based on Linkset resizer script by Maestro Linden.

The main differences between the two scripts are:

  • this script is menu-controlled
  • the script's listen channel is generated dynamically
  • more comments in the code for beginner scripters
  • it's just less chatty

The main differences with the previous version are:

  • modernized to use more recent features (it considers linkability rules now)
  • works with single-prim objects too now
  • closes the listener after a timeout
  • keeps the menu open until explicitly cancelled
  • MIN SIZE and MAX SIZE are commented out (but they can be enabled by removing the comment marks)
  • cancelling the DELETE option no longer resizes the linkset to the same size (it was a waste of resources)
  • no longer limited to 10m size per prim


Special thanks to:
Ann Otoole for contributing with a script removal function. The source code on this wiki page has been modified to reflect this contribution.

Source Code

// Linkset Resizer with Menu
// version 1.50 (2015-07-08)
// by: Brilliant Scientist and Sei Lisa
// © Copyright 2015 Sei Lisa
// --
// This script resizes all prims in a linkset, or a single prim.
// The process is controlled via a menu.
// The script works on arbitrary objects and requires no configuration.
// The script is based on "Linkset Resizer" script by Maestro Linden.
// http://wiki.secondlife.com/wiki/Linkset_resizer
// Special thanks to:
// Ann Otoole
 
float DialogTimeout = 180; // how many seconds before removing the listener
 
float max_scale;
float min_scale;
 
float   cur_scale = 1.0;
integer handle = 0;
integer menuChan;
 
list link_scales = [];
list link_positions = [];
 
makeMenu()
{
    if (!handle)
    {
        menuChan = 500000 + (integer)llFrand(500000);
        handle = llListen(menuChan, "", llGetOwner(), "");
    }
    llSetTimerEvent(DialogTimeout);
 
    //the button values can be changed i.e. you can set a value like "-1.00" or "+2.00"
    //and it will work without changing anything else in the script
    llDialog(llGetOwner(), "Max scale: " + (string)max_scale + "\nMin scale: " + (string)min_scale
        + "\n\nCurrent scale: "+ (string)cur_scale,
        ["-0.05", "-0.10", "-0.25", "+0.05", "+0.10", "+0.25", /*"MIN SIZE",*/ "RESTORE", /*"MAX SIZE",*/ "CLOSE", "DELETE..."],
        menuChan);
}
 
scanLinkset()
{
    integer link_qty = llGetNumberOfPrims();
    integer link_idx;
    integer link_ofs = (link_qty != 1); // add 1 if more than one prim (as linksets start numbering with 1)
    list params;
 
    for (link_idx = 0; link_idx < link_qty; ++link_idx)
    {
        params = llGetLinkPrimitiveParams(link_idx + link_ofs, [PRIM_POS_LOCAL, PRIM_SIZE]);
 
        link_positions += llList2Vector(params, 0);
        link_scales    += llList2Vector(params, 1);
    }
 
    max_scale = llGetMaxScaleFactor() * 0.999999;
    min_scale = llGetMinScaleFactor() * 1.000001;
}
 
resizeObject(float scale)
{
    integer link_qty = llGetNumberOfPrims();
    integer link_idx;
    integer link_ofs = (link_qty != 1);
 
    // scale the root
    llSetLinkPrimitiveParamsFast(link_ofs, [PRIM_SIZE, scale * llList2Vector(link_scales, 0)]);
    // scale all but the root
    for (link_idx = 1; link_idx < link_qty; link_idx++)
    {
        llSetLinkPrimitiveParamsFast(link_idx + link_ofs,
            [PRIM_SIZE,      scale * llList2Vector(link_scales, link_idx),
             PRIM_POS_LOCAL, scale * llList2Vector(link_positions, link_idx)]);
    }
}
 
default
{
    state_entry()
    {
        scanLinkset();
    }
 
    touch_start(integer total)
    {
        if (llDetectedKey(0) == llGetOwner())
            makeMenu();
    }
 
    timer()
    {
        llListenRemove(handle);
        handle = 0;
        llSetTimerEvent(0);
    }
 
    listen(integer channel, string name, key id, string msg)
    {
        if (msg == "RESTORE")
        {
            cur_scale = 1.0;
        }
        else if (msg == "MIN SIZE")
        {
            cur_scale = min_scale;
        }
        else if (msg == "MAX SIZE")
        {
            cur_scale = max_scale;
        }
        else if (msg == "DELETE...")
        {
            llDialog(llGetOwner(),"Are you sure you want to delete the resizer script?",
                ["DELETE","CANCEL"],menuChan);
            llSetTimerEvent(DialogTimeout);
            return;
        }
        else if (msg == "DELETE")
        {
            llOwnerSay("Deleting resizer script...");
            llRemoveInventory(llGetScriptName());
            return; // prevents the menu from showing - llRemoveInventory is not instant
        }
        else if (msg == "CANCEL")
        {
            // ignore but it will re-show the menu as it falls through
        }
        else if (msg == "CLOSE")
        {
            llListenRemove(handle);
            handle = 0;
            llSetTimerEvent(0);
            return; // prevents the menu from showing
        }
        else
        {
            cur_scale += (float)msg;
        }
 
        //check that the scale doesn't go beyond the bounds
        if (cur_scale > max_scale) { cur_scale = max_scale; }
        if (cur_scale < min_scale) { cur_scale = min_scale; }
 
        resizeObject(cur_scale);
        makeMenu();
    }
}



For information about using a resizer to handle nanoprims, check this older version: [1]