// 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>; // 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, (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, (-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); } }