// Testing child prim rotations.
// This is a script that could be used with a non-path-cut linked door or windows
// and so on, with the correct rotation offsets and calculations to function.
//
// When the script is run for the first time, prim should be in the closed position.
//
// Kimm Paulino, August 2010
// Specify the rotation to apply, as a Euler vector in degrees
vector gNewRotation_e = <0.0, 0.0, 150.0>;
// Specify the details of the Centre of Rotation to use.
// Can either work it out from the prim parameters or put a hardcoded one in here
integer gCorAxis = 1; // 1=x, 2=y, 3=z, -1=-x, -2=-y, -3=-z, 0=gCor
vector gCor = 0><0.0,0.0,0.0>; // Relative to root prim, if gCorAxis = 0
// This test script will automatically return the prim to its start
// parameters after this time if gAutoClose is set to TRUE.
float RESET_TIME = 5.0;
integer gAutoClose = FALSE;
vector gInitialPosition;
rotation gInitialRotation;
integer CLOSED=0;
integer OPEN=1;
integer gState;
store_child ()
{
// llOwnerSay ("-----------------");
gInitialPosition = llGetLocalPos();
// llOwnerSay ("Initial Position: " + (string)gInitialPosition);
gInitialRotation = llGetLocalRot();
// llOwnerSay ("Initial Rotation: " + (string)r2v(gInitialRotation));
}
restore_child()
{
// Note: Use the PRIM_ROTATION workaround, as described in SVC-93
llSetPrimitiveParams ([ PRIM_POSITION, gInitialPosition,
PRIM_ROTATION, gInitialRotation / llGetRootRotation()]);
//llSetPos (gInitialPosition);
//llSetLocalRot (gInitialRotation);
}
vector calcCorAxis ()
{
// Note: If the prim is rotated, then we need to apply the
// same rotation to the size values to pick up the correct axis
vector prim_size = llGetScale() * llGetLocalRot();
if (gCorAxis == 1)
{
return <(prim_size.x/2.0), 0.0, 0.0>;
}
else if (gCorAxis == 2)
{
return <0.0, (prim_size.y/2.0), 0.0>;
}
else if (gCorAxis == 3)
{
return 0><0.0, 0.0, (prim_size.z/2.0)>;
}
else if (gCorAxis == -1)
{
return <(-prim_size.x/2.0), 0.0, 0.0>;
}
else if (gCorAxis == -2)
{
return <0.0, (-prim_size.y/2.0), 0.0>;
}
else if (gCorAxis == -3)
{
return 0><0.0, 0.0, (-prim_size.z/2.0)>;
}
else
{
return gCor;
}
}
vector r2v (rotation r)
{
return (RAD_TO_DEG * llRot2Euler (r));
}
// rot is a rotation to be applied to the prim
// cor is a relative position (to the root) for the centre of rotation
rotate_child (rotation rot, vector cor)
{
// Work in local coordinates
vector current_position = llGetLocalPos();
rotation current_orientation = llGetLocalRot();
//llOwnerSay ("Current position/rotation: " + (string)current_position + " / " + (string)r2v(current_orientation));
// Calculate the offset from the centre of the object
// to the centre of rotation. This effectively moves
// the object so that the cor can be thought off as the
// origin. Once we've done the calculations, we'll move it back.
vector normalised_position = current_position - cor;
//llOwnerSay ("Normalised position/COR: " + (string)normalised_position + " / " + (string)cor);
// Calculate the new position by applying the required
// rotation to the current position (i.e. rotate the
// vector origin-position to produce origin-newposition)
vector new_normalised_position = normalised_position * rot;
//llOwnerSay ("Rotated Normalised Position: " + (string)new_normalised_position);
vector new_position = cor + new_normalised_position;
//llOwnerSay ("New Actual Position: " + (string)new_position);
rotation new_orientation = current_orientation * rot;
//llOwnerSay ("New Orientation: " + (string)r2v(new_orientation));
// Set local position and rotation
// Note: There is no llSetLocalPos - llSetPos will do local coords for a child
//llSetPos (new_position);
//llSetLocalRot (new_orientation);
// However, use llSetPrimitiveParams to set both at same time, without
// incurring two 0.2s delays ... although note, have to use
// the PRIM_ROTATION workaround, as described in SVC-93
llSetPrimitiveParams ([ PRIM_POSITION, new_position,
PRIM_ROTATION, new_orientation / llGetRootRotation()]);
}
default
{
on_rez (integer start_param)
{
// As positions will be stored on entry,
// don't want to auto reset on rez, as it might
// be rezed in the closed position, which would screw
// things up!
// llResetScript();
}
state_entry ()
{
// store initial position/etc
gState = CLOSED;
store_child ();
}
touch_start (integer num_detected)
{
if (gState == CLOSED)
{
// Need to convert CoR to local coordinates relative to
// the root prim (not just relative to this prim).
vector cor = llGetLocalPos() + calcCorAxis();
rotate_child (llEuler2Rot (gNewRotation_e * DEG_TO_RAD), cor);
if (gAutoClose)
{
llSetTimerEvent (RESET_TIME);
}
gState = OPEN;
}
else
{
restore_child ();
gState = CLOSED;
}
}
timer ()
{
gState = CLOSED;
restore_child ();
llSetTimerEvent (0.0);
}
}0>>0>>0>