Jump to content

Resize linkset script along a single axis?


Hada Sabra
 Share

You are about to reply to a thread that has been inactive for 4064 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

The Scripting forum is meant as a place for scripters to learn from each other. It's not really a place to look for scripts. If you are looking for someone to write a script for you, the best place to ask is in the Inworld Employment section of the Commerce Forums (http://community.secondlife.com/t5/Inworld-Employment/bd-p/InworldEmployment). If you are looking for a script that already exists, try Marketplace or the LSL Scripting Library (http://community.secondlife.com/t5/LSL-Scripting-Library/bd-p/LSLScriptingLibrary) or the Wanted section of the Commerce forums (http://community.secondlife.com/t5/Wanted/bd-p/Wanted). You will have much better luck.

If you are writing the script, though, take a look at llSetScale >> http://wiki.secondlife.com/wiki/LlSetScale .  All you need to do is pass it a vector that keeps two of the current dimensions fixed and changes the third one.

Link to comment
Share on other sites

it's possible to do, but in general it only works well if it's built to handle this... that pretty much means all the prims must be zero aligned, or facing a cardinal direction (but then requires extra work to determine)

the reason you don't see a general solution for this sort of thing is because it has too many requirements and too many limits. Mesh may be able to do this once it's in production.

Link to comment
Share on other sites

May we ask what you need it for?  As Void says, they only work under certain circumstances (and even then, in practice, I've always discovered drawbacks to using them that weren't immediately  appararent when I thought I needed one), and it may be that we can suggest an alternative method for whatever it is you want to do.

Link to comment
Share on other sites

To add to what the others have said about the difficulties of this, I was replying yesterday when the forums closed for maintenance.

Depending on the build(s) you will be using such a script can get very complicated.  For instance - you want to extend the object in the X-axis, but some of the prims are at 90-degrees so their x-axis isn't the one you need to change.  Phase 2 - you can cope with 90-degrees.  Then you hit a prim that is at a different rotation, around multiple axes.  So you need to check every single prim's rotation and calculate the proportion of your resize that should be assigned to each of its axes.  It's not impossible but it's a lot of work.  Then for curved shapes, especially, you find that the fit doesn't look right and so you end-up almost having to hard-code individual-prim values.

Been there, thought it would be easy, gave up.

Link to comment
Share on other sites

Hi,

All the prims we are using on this build are sculpties so they all will be will be zero aligned, the build is made to be worn by avis and I thought it could be helpful for the user to be able to adjust it depending on their own avi proportions.

This is my idea, using the http://wiki.secondlife.com/wiki/Linkset_resizer_with_menu as a template, but im lost on how to make the script aware when you change from different axis, the previous resizing get lost...

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++)
        {
            link_scale_a = llList2Vector(llGetLinkPrimitiveParams(link_idx,[PRIM_SIZE]),0);

            new_size   =  llList2Vector(link_scales, link_idx-1);
            new_pos    =  llList2Vector(link_positions, link_idx-1);            
            // new_size   = scale * llList2Vector(link_scales, link_idx-1);
            // new_pos    = scale * llList2Vector(link_positions, link_idx-1);
            
            if (axis == "x")
            {
                new_size.x = new_size.x * scale;
                new_pos.x  = new_pos.x * scale;
            }
            if (axis == "y")
            {
                new_size.y = new_size.y * scale;
                new_pos.y  = new_pos.y * scale;
            }
            if (axis == "z")
            {
                new_size.z = new_size.z * scale;
                new_pos.z  = new_pos.z * scale;
            }
            if (axis == "all")
            {
                new_size   = scale * llList2Vector(link_scales, link_idx-1);
                new_pos    = scale * llList2Vector(link_positions, 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
            {
                llSetLinkPrimitiveParamsFast(link_idx, [PRIM_SIZE, new_size, PRIM_POSITION, new_pos]);
            }
        }
    }
}

 

Link to comment
Share on other sites

Can't stay away from SL. (/me waves)  What happened to you lot while I was away?  Hadra specifies that her prims will all be aligned with the root, which keeps it simple.  So I wrote this:

 

// Resize Axis //// =========== //// Version 0.1// By Indeterminate Schism of Script Sisters group// Developed from earlier work by Void Singer, Brilliant Scientist, Ann Otoole, Maestro Linden// and probably others whose names have got lost in all the excitement// Resize single prims or linksets along specified axis/axes// NB: RESTRICTION - all prims must share the same rotation - this was developed for that specific situation as required by Hada Sabra// Independent selection of x, y, z axes for scaling// Includes menu-timeout to close listener// Not limited by script memory, uses hovertext to store original sizes and positions (removed when script deleted through menu)// Delete script menu option with confirm/cancel sub-menu// Revert to original sizes/positions option// Display of maxima, current and minima scaling for each axis// Accepts llMessageLinked() string "RESIZE:<scale>", eg; RESIZE:<1.5, 2.0, -0.5> (checked for maxima/minima bounds before processing)// Settings may be queried with string "RESIZEQUERY" - returns string consisting of <maxima>_<current>_<minima> vectors// Global Variables// ----------------vector Axes = ZERO_VECTOR;		// Axes along which object is being resizedinteger Delete = FALSE;		// Flag for script-delete menufloat MaxDim = 10.0;		// Constant - no dimension may be greater than thisvector Maxima = ZERO_VECTOR;	// Maximum dimensions in the object, read at state_entryinteger MenuListen;		// Handle to remove menu-listenfloat MinDim = 0.01;		// Constant - no dimension may be smaller than thisvector Minima = <10.0, 10.0, 10.0>;	// Minimum dimensions in the object, read at state_entryvector Scale = <1.0, 1.0, 1.0>;	// Amount by which to resize each axisCloseListen(){	// Stop the timer and listener and reset the handle	llSetTimerEvent(0.0);	if(MenuListen){		llListenRemove(MenuListen);		MenuListen = 0;	}}Menu(){	// 'Standard' menu buttons - 99% of the time these are the values that will be used	list MenuButtons = ["Restore", "Done", "Delete"];	string MenuMessage = "Scale:\nMax: " + (string) Maxima + "\nNow: " + (string) Scale + "\nMin: " + (string) Minima;	if(Delete){		// Delete-confirmation menu		MenuButtons = ["Confirm", "Cancel"];		MenuMessage = "Are you sure you want to delete this resize script?";	}else{		// Axes and scale buttons		if(Axes.x){MenuButtons += ["X •"];}else{MenuButtons += ["X"];}		if(Axes.y){MenuButtons += ["Y •"];}else{MenuButtons += ["Y"];}		if(Axes.z){MenuButtons += ["Z •"];}else{MenuButtons += ["Z"];}		MenuButtons += ["-0.05","-0.10","-0.25", "+0.05","+0.10","+0.25"];	}	// Show the menu	integer MenuChannel = -(integer) (llFrand(999999999.9) + 1);	MenuListen = llListen(MenuChannel, "", llGetOwner(), "");	llDialog(llGetOwner(), MenuMessage, MenuButtons, MenuChannel);	llSetTimerEvent(30.0);}Resize(){	// Check scaling is within maxima/minima bounds	if(Scale.x < Minima.x){Scale.x = Minima.x;}else if(Scale.x > Maxima.x){Scale.x = Maxima.x;}	if(Scale.y < Minima.y){Scale.y = Minima.y;}else if(Scale.y > Maxima.y){Scale.y = Maxima.y;}	if(Scale.z < Minima.z){Scale.z = Minima.z;}else if(Scale.z > Maxima.z){Scale.z = Maxima.z;}	// Resize and position everything	integer Counter = llGetNumberOfPrims();	if(1 == Counter){			list Originals = llParseString2List(llList2String(llGetLinkPrimitiveParams(0, [PRIM_TEXT]), 0), ["\n"], []);			vector NewSize = (vector) llList2String(Originals, 0);			NewSize.x *= Scale.x;			NewSize.y *= Scale.y;			NewSize.z *= Scale.z;			llSetLinkPrimitiveParamsFast(0, [PRIM_SIZE, NewSize]);	}else{		while(Counter){			list Originals = llParseString2List(llList2String(llGetLinkPrimitiveParams(Counter, [PRIM_TEXT]), 0), ["\n"], []);			vector NewSize = (vector) llList2String(Originals, 0);			NewSize.x *= Scale.x;			NewSize.y *= Scale.y;			NewSize.z *= Scale.z;			vector NewPos = (vector) llList2String(Originals, 1);			NewPos.x *= Scale.x;			NewPos.y *= Scale.y;			NewPos.z *= Scale.z;			if(1 == Counter){				// Just rescale the root				llSetLinkPrimitiveParamsFast(Counter--, [PRIM_SIZE, NewSize]);			}else{				// Rescale and reposition everything else				llSetLinkPrimitiveParamsFast(Counter--, [PRIM_SIZE, NewSize, PRIM_POSITION, NewPos]);			}		}	}	// Redisplay the menu for next command	Menu();}default{	link_message(integer FromPrim, integer Number, string Text, key UUID){		// Only the Text parameter is relevant		if("RESIZEQUERY" == Text){			// Return <maxima>_<current>_<minima> vectors			llMessageLinked(FromPrim, Number, (string) Maxima + "_" + (string) Scale + "_" + (string) Minima, UUID);		}else if("RESIZE:" == llGetSubString(Text, 0, 6)){			// Scale to given vector			Scale = (vector) llDeleteSubString(Text, 0, 6);			Resize();		}	}	listen(integer ChannelIn, string FromName, key FromID, string Message){		// Process menu selections		CloseListen();		if((float) Message){			// A numeric, therefore a scaling factor			if(Axes.x){Scale.x += (float) Message;}			if(Axes.y){Scale.y += (float) Message;}			if(Axes.z){Scale.z += (float) Message;}			Resize();		}else{			// Must be some other command			if("Cancel" == Message){				// Cancel script-deletion				Delete = FALSE;				Menu();			}else if("Confirm" == Message){				// Delete this script, but first remove all the prim text				integer Counter = llGetNumberOfPrims();				if(1 == Counter){					llSetLinkPrimitiveParamsFast(0, [PRIM_TEXT, "", ZERO_VECTOR, 0.0]);				}else{					while(Counter){						llSetLinkPrimitiveParamsFast(Counter--, [PRIM_TEXT, "", ZERO_VECTOR, 0.0]);					}				}				llRemoveInventory(llGetScriptName());				llOwnerSay("Script deleted");			}else if("Done" == Message){				// Do nothing			}else if("Delete" == Message){				// Show delete-confirmation menu				Delete = TRUE;				Menu();			}else if("Restore" == Message){				// Reset the sizes and positions to the original values				Scale = <1.0, 1.0, 1.0>;				Resize();			}else{				Message = llGetSubString(Message, 0, 0);				if("X" == Message){Axes.x = !(integer) Axes.x;}				else if("Y" == Message){Axes.y = !(integer) Axes.y;}				else if("Z" == Message){Axes.z = !(integer) Axes.z;}				Menu();			}		}	}    state_entry(){    	// Find the largest and smallest prim dimensions, store sizes and positions to prim text    	llOwnerSay("Initialising, please wait ...");    	integer Counter = llGetNumberOfPrims();    	if(1 == Counter){    		// I don't know why anyone would use this for a single prim, but it's here anyway    		Maxima = llList2Vector(llGetLinkPrimitiveParams(0, [PRIM_SIZE]), 0);    		Minima = Maxima;    		llSetLinkPrimitiveParamsFast(Counter, [PRIM_TEXT, (string) Maxima, ZERO_VECTOR, 0.0]);    	}else{	    	vector RootPos = llGetRootPosition();	    	rotation RootRot = llGetRootRotation();	    	while(Counter){	    		vector LinkScale = llList2Vector(llGetLinkPrimitiveParams(Counter, [PRIM_SIZE]), 0);	    		if(LinkScale.x < Minima.x){Minima.x = LinkScale.x;}else if(LinkScale.x > Maxima.x){Maxima.x = LinkScale.x;}	    		if(LinkScale.y < Minima.y){Minima.y = LinkScale.y;}else if(LinkScale.y > Maxima.y){Maxima.y = LinkScale.y;}	    		if(LinkScale.z < Minima.z){Minima.z = LinkScale.z;}else if(LinkScale.z > Maxima.z){Maxima.z = LinkScale.z;}	    		llSetLinkPrimitiveParamsFast(Counter, [PRIM_TEXT, (string) LinkScale + "\n" +	    			(string) ((llList2Vector(llGetLinkPrimitiveParams(Counter--, [PRIM_POSITION]), 0) - RootPos) / RootRot)	    			, ZERO_VECTOR, 0.0]);	    	}    	}    	// Convert those to valid scaling bounds    	Maxima.x = MaxDim / Maxima.x;    	Maxima.y = MaxDim / Maxima.y;    	Maxima.z = MaxDim / Maxima.z;    	Minima.x = MinDim / Minima.x;    	Minima.y = MinDim / Minima.y;    	Minima.z = MinDim / Minima.z;    	llOwnerSay("Ready - touch for menu");    }	timer(){		// Menu time-out		llOwnerSay("Menu timed-out.  Touch again to reactivate it");		Delete = FALSE;		CloseListen();	}	touch_start(integer HowMany){		// Show the menu to the owner		if(llDetectedKey(0) == llGetOwner()){			CloseListen();			Menu();		}	}}

 

It's not sufficiently tested to put in the library yet so comments/critique welcome.  I'm also concerned that that 'all prims must share the same rotation' is too big a restriction for this to have much more than academic interest.

What we need is a mathematician that can work out how to resize for an arbitary rotation.  That's way beyond me.

  • Like 2
Link to comment
Share on other sites

::sees her name in lights:: aww thanks IS =)

I personally don't see a general solution for anything other that axis aligned prims (cardinal directions) due to the way standard prims are built... there's a little room for some of the twist parameters to support a little more on certain axes, but there's no general solution, and even doing those few would likely take multiple scripts. we just don't have that kind of control. sculpts and meshes should be immune as long as they're axes aligned, although that may be a little difficult is the case of sculpts (lots of custom rotated ones for off angles)

Still, color me impressed that you decided to tackle it... you've more fortitude for it than me

Link to comment
Share on other sites


Void Singer wrote:

I personally don't see a general solution for anything other that axis aligned prims (cardinal directions)

Same here, I can feel my brain melting thinking of the complexity.  I hadn't even begun to consider the domplications involved in deforming prim-torture.  Still, it's nice to at least deal with this special case and see the OP get a solution

Link to comment
Share on other sites

I've made a few tweaks and tidies but nothing significant.  I'll put this in the library with a big warning at the top and suggested adjustments just for good measure.  (PRIM_DESC instead of PRIM_TEXT, that sort of thing)  Or not.  I want to at least handle cardinal-point rotations first, even if it isn't necessary in this special case.

@ Void, Dora - I really ought to avoid storing each prim's original size/position too, as you have.  This seemed to offer better protection against rounding errors but if you're happy just checking the root's current scaling I'll take your word for it.  Any other advice?

Link to comment
Share on other sites

my only suggestion is make sure your reference point is solid, that way any rounding erros are so smal as to be beyond the render limits.

I still plan to do a MONO version that does store sizes, but it will only do that once, and everything from there will be a reference. that should prevent all but the tiniest errors, since the dynamic setup is slightly unstable (still inside rendering tolerances, but there could be unique cases I didn't test for) largley due to the lack of a parameter like PRIM_POS_LOCAL.... if we ever get that, the dynamic will be a preferable solution size/memory wise, although it may be slightly slower

Link to comment
Share on other sites

  • 2 months later...

There are some cases in which "resize along the Z axis" actually means resize each prim along its own Z axis, regardless of its orientation with the rest of the link set.   Hair and certain other "organic" objects might benefit from a resize that ignores child prim rotation.  For this I use the "basic resizer" in the library, modified to use a vector instead of a scalar.  My version also saves the root rotation at the beginning and sets it to ZERO_ROTATION, then restores it at the end so the moves work right if the overall object is rotated.  I also modded it to allow me to make megaprims up to 64x64x64 now that we can do that.

 

Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 4064 days.

Please take a moment to consider if this thread is worth bumping.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...