Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Stretching Prims via Scripting

Ahndou Zauberflote
Registered User
Join date: 9 Nov 2006
Posts: 30
06-08-2007 11:02
Can somebody tell me how to do this? I have a project in the works where a prim is supposed to get stretched horizontally little by little over time, and although I know that it is possible I do not know how to go about doing it. Thanks.
RJ Source
Green Sky Labs
Join date: 10 Jan 2007
Posts: 272
06-08-2007 11:04
Check out llSetScale
Ahndou Zauberflote
Registered User
Join date: 9 Nov 2006
Posts: 30
06-08-2007 19:20
Ah, update time! I have succeeded in getting a prim to stretch via scripting, however it doesn't script exactly how I want it to. I will show you the code:

integer counter;
integer second;
vector startScale;

default
{
state_entry()
{
counter = 0;
startScale = llGetScale();
}

touch_start(integer total_number)
{
counter = counter + 1;

llSetTimerEvent( .5 );
}

timer()
{
second++;

float X_scale = llFrand( 0.0 );
float Y_scale = llFrand( 0.0 );
float Z_scale = llFrand( 0.1 );

vector increment = < X_scale, Y_scale, Z_scale>;
vector newScale = startScale + increment;
llSetScale( newScale );

if ( second > 19 )
{
while ( llVecDist( llGetScale(), startScale ) > 0.001)
{
llSetScale( startScale );
}

llResetScript();
}
}
}

In gist, what this script does is stretch the prim random distances between 0 and .5 on the z-axis a number of times for a few seconds and then reverts back to it's original size.

A few changes that I want to make, but don't know how to do:

1. I want the prim to only be stretched by one side of the z-axis. During the run of this script the prim was stretched by both sides, like it was center-centric. I want one side to not stretch with the other side to do the stretching, if this makes any sense.

2. I do not want the prim to be stretched by random distances; I kind of want it to be increment-based, with it being stretched a certain constant distance (say, .1 per second) per second lapsed.

3. I need for the stretching part of this script to be initiated by another script in an object (say, if the avatar gets on an object and the object initiates the stretching script in another object; the script would also stop when the avatar gets off of the object).

4. The reversion portion of the script should probably be independent of the rest of the script, allowing the user to revert the object back into it's original size by command (chat command would be best).

Thanks everyone, any help would be greatly appreciated.
RJ Source
Green Sky Labs
Join date: 10 Jan 2007
Posts: 272
06-08-2007 19:45
Some thoughts:

1. Though I don't know if you can do just one direction, you could scale it, move the prim back to ground level, scale again, move again, etc. That way it will look like its shrinking from the top side. (Or just hide the bottom side thats shrinking below ground.)

2. Then your timer would be at 1 second intervals, and each timer event would shrink .1 (or .05 if you count both sides). Or some multiple (if .5 second intervals, than .1/2, etc).

3. Look at llMessageLinked

4. After shrinking, maybe change to a new state, that has a listen waiting for the user command, and then reverts to the original size. (So remember to save the original size in some variables at the start).
Ahndou Zauberflote
Registered User
Join date: 9 Nov 2006
Posts: 30
06-08-2007 20:35
From: RJ Source
Some thoughts:

1. Though I don't know if you can do just one direction, you could scale it, move the prim back to ground level, scale again, move again, etc. That way it will look like its shrinking from the top side. (Or just hide the bottom side thats shrinking below ground.)

2. Then your timer would be at 1 second intervals, and each timer event would shrink .1 (or .05 if you count both sides). Or some multiple (if .5 second intervals, than .1/2, etc).

3. Look at llMessageLinked

4. After shrinking, maybe change to a new state, that has a listen waiting for the user command, and then reverts to the original size. (So remember to save the original size in some variables at the start).


#1 won't do, there's got to be some other way. #2 seems feasable, although I don't know what you mean by "shrinking"; I want it to increase in size by the z-axis. #3 should be fine; I will look into that. #4 doesn't seem feasible, since the code itself reverts it just fine; I simply want it to be separately commanded. Thanks, hopefully others will help me out as well.
Lazink Maeterlinck
Registered User
Join date: 8 Nov 2005
Posts: 332
06-08-2007 23:00
RJ's suggestion of shrinking/expanding the prim then moving is the only way to do it, since you can't stretch a prim via a script on one side like you can in the edit window. Just use llSetPrimitivePararms() to make it look like it moves seamlessly.
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
06-09-2007 07:05
Scaling/Rotation/Positioning is always centered on the prim's center. If you're really set on not moving the prim, there is another alternative. It is possible to cut a prim so that it's only half there, that way it will only scale on one side. (This is the trick that one-prim doors use to rotate on their centers yet turn on one edge.) For example lf the prim is a Box, you could set the Path Cuts to 0.375 and 0.875, and then change the script to scale on the Y side instead. Note that this limits the max size to 5m instead of 10m.

For a circle, change the cuts to 0.25 and 0.75 and scale on Y.

For a cylinder, it's a bit trickier, you have to change it to a sphere, with cuts 0 and 1, then change the Dimple to 0.5 and 1.0, then change it back to Cylinder and scale on Z. (This is known as a "tortured prim" where you change something on the sphere and it affects the cylinder's shape.)

For the other prims you can experiment with combinations of Profile Cut (which is the same as a sphere's Dimple) and Path Cut to find the shape you want, then pick the appropriate direction to scale. I think you get the idea.

=-=-=-=-=-=-=-=-=

Otherwise, for scaling only one side of a WHOLE prim, here's a version of your code that moves only in on one side (the positive direction) of each axis (yes it will work for more than one, and anchor one corner instead of one side).

I made a few other changes too... I have moved the lines which save the original scale/pos to inside the start function, in case the object moves after the script is reset. I also removed the while loop on resetting the scale/pos because one call should do it. It wasn't even necessary for scaling (only setpos can fail) and in this case we'll never move so far that we're beyond the 10m setpos limit. Finally, I changed it to scale larger over time instead of using a random amount, and to start/reset on a channel listen event. This takes care of all four items on your list.

CODE

integer counter;
vector startScale;
vector startPos;

// Note: this represents the direction (1 or -1)
// divided by 2 because we only want
// to move half of the scale amount to keep
// one side in place. (we're just pre-calculating this)
float scaleFrac = -0.5; // which way to scale, 0.5 or -0.5

float tick = 0.25; // time for each change, must be > 0.2

integer channel = 2468; // channel to listen for start/reset

start()
{
if (counter != 0) // b ail if already running
return;

startScale = llGetScale();
startPos = llGetLocalPos();

counter = 0;
llSetTimerEvent( tick );
}

reset()
{
llSay(channel, "reset");
// restore only if script was triggered
if (startScale != ZERO_VECTOR && startPos != ZERO_VECTOR)
llSetPrimitiveParams( [PRIM_SIZE, startScale,
PRIM_POSITION, startPos] );
llResetScript();
}


default
{

state_entry()
{
counter = 0;
llListen(channel, "", "", "start");
llListen(channel + 1, "", "", "reset");
}

touch_start(integer total_number)
{
start();
}

listen(integer chan, string name, key id, string msg)
{
if (chan == channel)
start();

if (chan == channel + 1)
reset();
}

timer()
{
counter = counter + 1;
float seconds = tick * counter;

if ( seconds > 10 )
reset(); // restores and resets the script

vector scalevec = <0.0, 0.0, 0.1>; // direction of scaling
scalevec = scalevec * seconds;

vector newScale = startScale + scalevec;

rotation rot = llGetLocalRot();
vector newPos = startPos + ( scalevec * scaleFrac * rot );

llSetPrimitiveParams( [PRIM_SIZE, newScale,
PRIM_POSITION, newPos] );

}
}


Note that I also factored in the prim's rotation just in case it's not 0,0,0. I used llGetLocalPos() and llGetLocalRot() instead of llGetPos() and llGetRot() to allow this to work in a linked prim as well.

Also note that the scaling will NOT work if the object is physical, but the movement will. You'll have to disable physics momentarily if you need to scale while physical.

~Boss
Ahndou Zauberflote
Registered User
Join date: 9 Nov 2006
Posts: 30
06-09-2007 17:58
Thanks Boss. The code that you provided didn't solve the moving/stretching problem, but it does give a satisfactory steady increase in the z-axis size of the object. The object was a cylinder and I did what you suggested in order to half it's size, but it didn't really help.

Funny thing, though, is that when I altered the code a little bit by taking all of the variables of position out of it that the object behaved much the same way as it did when they were still there. Odd, isn't it? I don't know much about scripting though, so maybe you would know better about what is happening that I would.

Perhaps I could show you my project in SL and we could talk about it there? Or maybe you could post more code here? Either way is fine, you seem to be very talented.

Well, thanks!
Boss Spectre
Registered User
Join date: 5 Sep 2005
Posts: 229
06-09-2007 20:52
This code was intended to be used with an uncut prim, if you cut the prim you can simply scale the prim and it will scale from the prim's center, which is now one side due to the cut.
Ahndou Zauberflote
Registered User
Join date: 9 Nov 2006
Posts: 30
06-10-2007 12:35
Update time! It seems that the code will work just fine with the tortured cylinder prim that I had constructed with your advice, but in order for my project to be completely effective I'm going to have to somehow enable physics and the flexibility path in the tortured prim without having the prim revert back to being a normal cylinder. Is this possible through scripting? Any advice/guidance would be very much appreciated.