Linkset resizer with menu

From Second Life Wiki
Revision as of 12:38, 24 January 2015 by Lady Sumoku (talk | contribs) (Instead of <pre> generic formatting, used <source> for context highlighting to match the current (in progress) wiki updates)
Jump to navigation Jump to search

A single script that rescales every prim in a linkset

by Brilliant Scientist, 25th April 2010

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


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.00 (25.04.2010)
// by: Brilliant Scientist
// --
// This script resizes all prims in a linkset, the process is controlled via a menu.
// The script works on arbitrary linksets and requires no configuration.
// The number of prims of the linkset it can process is limited only by the script's memory.
// The script is based on "Linkset Resizer" script by Maestro Linden.
// http://wiki.secondlife.com/wiki/Linkset_resizer
// This script still doesn't check prim linkability rules, which are described in:
// http://wiki.secondlife.com/wiki/Linkability_Rules
// Special thanks to:
// Ann Otoole
 
float MIN_DIMENSION=0.01; // the minimum scale of a prim allowed, in any dimension
float MAX_DIMENSION=10.0; // the maximum scale of a prim allowed, in any dimension
 
float max_scale;
float min_scale;
 
float   cur_scale = 1.0;
integer handle;
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_positions = [];
 
makeMenu()
{
	llListenRemove(handle);
	menuChan = 50000 + (integer)llFrand(50000.00);
	handle = llListen(menuChan,"",llGetOwner(),"");
 
	//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","DELETE..."],menuChan);
}
 
integer scanLinkset()
{
	integer link_qty = llGetNumberOfPrims();
	integer link_idx;
	vector link_pos;
	vector link_scale;
 
	//script made specifically for linksets, not for single prims
	if (link_qty > 1)
	{
		//link numbering in linksets starts with 1
		for (link_idx=1; link_idx <= link_qty; ++link_idx)
		{
			link_pos=llList2Vector(llGetLinkPrimitiveParams(link_idx, [PRIM_POS_LOCAL]),0);
			link_scale=llList2Vector(llGetLinkPrimitiveParams(link_idx,[PRIM_SIZE]),0);
 
			// determine the minimum and maximum prim scales in the linkset,
			// so that rescaling doesn't fail due to prim scale limitations
			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];
			link_positions += [link_pos];
		}
	}
	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)
{
	integer link_qty = llGetNumberOfPrims();
	integer link_idx;
	vector new_size;
	vector new_pos;
 
	if (link_qty > 1)
	{
		//link numbering in linksets starts with 1
		for (link_idx=1; link_idx <= link_qty; link_idx++)
		{
			new_size   = scale * llList2Vector(link_scales, link_idx-1);
 
			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
			{
				new_pos    = scale * llList2Vector(link_positions, link_idx-1);
				llSetLinkPrimitiveParamsFast(link_idx, [PRIM_SIZE, new_size, PRIM_POSITION, new_pos]);
			}
		}
	}
}
 
default
{
	state_entry()
	{
		if (scanLinkset())
		{
			//llOwnerSay("resizer script ready");
		}
		else
		{
			llRemoveInventory(llGetScriptName());
		}
	}
 
	touch_start(integer total)
	{
		if (llDetectedKey(0) == llGetOwner()) makeMenu();
	}
 
	listen(integer channel, string name, key id, string msg)
	{
		//you can never be too secure
		if (id == llGetOwner())
		{
			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);
                           return;				
			}				
			else if (msg == "DELETE")
			{                
                           llOwnerSay("deleting resizer script...");
			   llRemoveInventory(llGetScriptName());				
			}			
			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);
		}
	}
}



Crunching and Inflating

I have been faced with the following problem: Stephen Xootfly handed me a representation of a caffeine molecule. I wanted to scale that molecule down so that I may create a necklace out of it. This is what the molecule looks like in comparison to my avatar:

Resize - Comparison.png

On the lower right, you can see the result after using the script above and using the minimal size option AND replacing the molecules and bindings with a set of nanoprims that I carry around. Here is a blow-up so you can see what it looks like after those operations:

Resize - BadCrunch.png

As you can see, the distances between the bindings and the atoms are relatively larger than in the original picture. This is NOT because the script above does not function correctly. The script above functions correctly however, by replacing the atoms and bindings with their equivalent nanoprim-sized sculpt shapes, I have thereby increased the "visible distance" artificially. In other words, the primitives are still the same size but by using nanoprims only a subpart of that is visible.

One way to solve this problem, would have been to roll-up my sleeves and start manually putting each molecule and binding in place. I went as far as doing one peripheral cluster and then I gave up. This would have wasted probably the rest of my day...

So, I took again at the script above and wondered how the script repositions the primitives after it has scaled them. The key is to be found in the script above, at this line:

<lsl> link_positions += [(link_pos-llGetRootPosition())/llGetRootRotation()]; </lsl>

which repositions the primitive relative to the root position.

Since I used n_20-size nanoprims for bindings between atoms, n_10-size nanoprims for small atoms and n_5-size nanoprims for large atoms, I figured that in fact, I am just inducing an error by a factor of 5.

To fix the problem, I used the script as it is to scale the molecule to its maximum size, after I had scaled it down and replaced the atoms and bindings with nanoprims. I then edited the script and alter it in order to take the factor out:

<lsl> link_positions += [(link_pos/5-llGetRootPosition())/llGetRootRotation()]; </lsl>

And then I clicked the gigantic molecule and selected "minimum size" to crunch it back into place, hoping to eliminate that factor of 5. This is the result:

Resize - GoodCrunch.png

As you see, the factor has been taken out and the molecule is now a perfect nano-replica of the original, scaled down to a n_20-size nano and respecting the relative distances between atoms and bindings.

This spared me a lot of time. Perhaps one could take this concept to the next level and write a script that would eliminate such a factor. It would be mightily useful for builders using nanoprims.