User:Pazako Karu/LinksetResizerWithMenu
Jump to navigation
Jump to search
This script resizes a linkset in X,Y,Z as desired without any configuration.
On adding the script, it asks for a limit in case you don't want the true max.
I added this since the 'true max' of a small item would be hilariously large.
Code
// Linkset Resizer with Menu
// by: Pazako Karu
// This script resizes a linkset in X,Y,Z as desired without any configuration
float max_scale;
float min_scale;
vector scale = <1,1,1>;
list link_scales = [];
list link_positions = [];
integer X = TRUE;
integer Y = TRUE;
integer Z = TRUE;
integer SCANNED = FALSE;
//#include "dialog.lsl"
list DIALOG_DATA;
setDialog(key id, string caption, list buttons, integer context)
{ getDialog(id);
if (llList2Integer(DIALOG_DATA, -4) > llGetTime())
cleanDialogs();
else while (llGetListLength(DIALOG_DATA) >= 40)
{ llListenRemove(llList2Integer(DIALOG_DATA,2));
DIALOG_DATA = llList2List(DIALOG_DATA, 4, -1);
}
integer channel = -(integer)llFrand(DEBUG_CHANNEL);
DIALOG_DATA += [llGetTime()+60, id, llListen(channel, llKey2Name(id), id, ""), context];
llDialog(id, caption, buttons, channel);
}
integer getDialog(key id)
{ integer index = llListFindList(DIALOG_DATA, [id]);
integer context = llList2Integer(DIALOG_DATA,index+2);
if (~index)
{ llListenRemove(llList2Integer(DIALOG_DATA, index+1));
DIALOG_DATA = llDeleteSubList(DIALOG_DATA, index-1, index+2);
}
else context = 0;
return context;
}
cleanDialogs()
{
integer index;
for (index = 2; index < llGetListLength(DIALOG_DATA); index+=4)
llListenRemove(llList2Integer(DIALOG_DATA,index));
DIALOG_DATA=[];
}
makeMenu()
{
list options = ["-1%","-5%","-10%","+1%","+5%","+10%"];
if (X) options += ["[X]"]; else options += ["X"];
if (Y) options += ["[Y]"]; else options += ["Y"];
if (Z) options += ["[Z]"]; else options += ["Z"];
options += ["Max", "Min", "More..."];
setDialog(llGetOwner(), (string)[ "Max scale: ", max_scale, "\nMin scale: ", min_scale, "\n\nCurrent scale: ", scale], options, 1);
llSetTimerEvent(120);
}
scanLinkset()
{
integer links = llGetNumberOfPrims();
integer link;
integer offset = (links != 1); // add 1 if more than one prim (as linksets start numbering with 1)
list params;
for (link = 0; link < links; ++link)
{
params = llGetLinkPrimitiveParams(link + offset, [PRIM_POS_LOCAL, PRIM_SIZE]);
link_positions += llList2Vector(params, 0);
link_scales += llList2Vector(params, 1);
}
if (max_scale == 0)
max_scale = llGetMaxScaleFactor() * 0.999999;
min_scale = llGetMinScaleFactor() * 1.000001;
SCANNED = TRUE;
llOwnerSay("Ready to use! Max scale set to " + (string)max_scale + "m");
}
resizeObject(vector scale)
{
integer links = llGetNumberOfPrims();
integer link;
integer offset = (links != 1);
// scale the root
llSetLinkPrimitiveParamsFast(offset, [PRIM_SIZE, notDot(scale,llList2Vector(link_scales, 0))]);
// scale all but the root
for (link = 1; link < links; link++)
{
llSetLinkPrimitiveParamsFast(link + offset,
[PRIM_SIZE, notDot(scale, llList2Vector(link_scales, link)),
PRIM_POS_LOCAL, notDot(scale, llList2Vector(link_positions, link))]);
}
}
vector notDot(vector A, vector B)
{
return <A.x*B.x, A.y*B.y, A.z*B.z>;
}
float limit(float input)
{
if (input > max_scale) return max_scale;
if (input < min_scale) return min_scale;
return input;
}
default
{
state_entry()
{
setDialog(llGetOwner(), "Please define max scale, or leave blank to allow actual maximum, which may be very very large.", ["!!llTextBox!!"], 4);
}
touch_start(integer total)
{
if (llDetectedKey(0) == llGetOwner())
{
if (SCANNED == TRUE)
makeMenu();
else llResetScript();
}
}
timer()
{
cleanDialogs();
llSetTimerEvent(0);
}
listen(integer channel, string name, key id, string msg)
{
integer CONTEXT = getDialog(id);
if (CONTEXT == 4)
{
max_scale = llFabs((float)msg);
if (max_scale > llGetMaxScaleFactor() * 0.999999)
max_scale = llGetMaxScaleFactor() * 0.999999;
scanLinkset();
}
else if (SCANNED == TRUE)
{
if (CONTEXT == 1)
{
if (msg == "[X]") X = FALSE;
else if (msg == "[Y]") Y = FALSE;
else if (msg == "[Z]") Z = FALSE;
else if (msg == "X") X = TRUE;
else if (msg == "Y") Y = TRUE;
else if (msg == "Z") Z = TRUE;
else if (msg == "Max") scale = max_scale * <1,1,1>;
else if (msg == "Min") scale = min_scale * <1,1,1>;
else if (msg == "More...") setDialog(id, "\nBonus options:", ["Delete", "Restore", "Back"], CONTEXT=2);
else // Number chosen
{
float factor = (float)msg/100;
if (factor > 0)
{
factor += 1; // 1.05
if (X) scale = notDot(scale, <factor,1,1>);
if (Y) scale = notDot(scale, <1,factor,1>);
if (Z) scale = notDot(scale, <1,1,factor>);
}
else
{
factor = 1/(1-factor);
if (X) scale = notDot(scale, <factor,1,1>);
if (Y) scale = notDot(scale, <1,factor,1>);
if (Z) scale = notDot(scale, <1,1,factor>);
}
}
// Limit scale to bounds
scale = <limit(scale.x), limit(scale.y), limit(scale.z)>;
resizeObject(scale);
if (CONTEXT == 1)
makeMenu();
}
else if (CONTEXT == 2) // Bonus options
{ //"Delete", "Defaults", "Back"
if (msg == "Back") makeMenu();
else if (msg == "Delete") setDialog(id, "\nAre you sure you want to delete the resizer script?", ["Yes", "No"], 3);
else if (msg == "Restore")
{
scale = <1,1,1>;
resizeObject(scale);
makeMenu();
}
}
else if (CONTEXT == 3) // Delete confirm
{
if (msg == "Yes")
{
llRegionSayTo(id, 0, "Script deleted");
llRemoveInventory(llGetScriptName());
}
}
}
}
}
License
You may use, abuse, and distribute this object in any way, other than simply repacking for sale. You may include this object as part of a sellable object in any form, including full permission. This was made using some firestorm preprocessing commands and is not given with any promise of readability or assistance with modification.