28 September 2008

Builds 18: Moving Doors

Was going nuts trying to figure out the best way to code rotation independent doors in Second Life. Then I discovered the Lindens helpfully created a function that takes the rotation and calculated vectors for you, so that no matter which way the door is facing you can move it, for instance, one meter to the left.

Anyway, here is my solution if anyone needs a robust door script. It assumes that the initial position for the door is along the Y-axis, set to slide north.

The script will either just slide the door or slide the door halfway and then do a little flip to fold the door against the wall. The second one makes for an elegant little effect.

// Creative Commons Attribute Share-Alike License
// Mootly Obviate 2008
// ==========
// This script controls doors that slide or slide or slide
// and rotate.  It is rotation independent and can be used
// when linked in single prim doors. Remember that prims
// pivot on their center.
// The point of this script is to make doors that slide
// partly out of the way and then rotate to fold away.

// defaults - no reason to touch
integer  on       = 1;        // set on flag to 1 (on)
integer  ont      = 0;        // set timer flag to 0 (off)
rotation delta    = <0,0,0,0>;
rotation rot      = <0,0,0,0>;
integer  thisstep = 0;

// Set this to determine delay before door autocloses.
float    time     = 30;       // close after x seconds

// Not really position, so much as length of movement.
// These should be set to how many meters you want the
// doors to move. Normally they should have the same value.
float    posi     = 1;        // position
float    dpos     = 1;        // default position

// Set whether the rotation and movement (x-axis) is
// positive or negative
integer  rotdir   = 1;        // set positive/negative rotation
integer  movdir   = 1;        // set positive/negative movement

// Set rotation action: number of steps and degrees per
// step. Remember a quarter turn is 90 degrees.
integer  steps    = 2;        // set steps in rotation
float    degper   = 45;       // set degrees per step

// Set flag (0/1) on whether to rotate after sliding.
integer  rot_tf   = 1;        // set true false on rotation

default
  {

  // state entry stuff
  state_entry()
    {
    llOwnerSay("Door Ready");
    }

  // auto close timer
  timer()
    {
    if (ont == 1) {
      if (rot_tf == 1)
        {
        rot = llGetLocalRot();
        delta = llEuler2Rot(<0,0,-(rotdir*degper*DEG_TO_RAD)>);
        thisstep = 0;
        for (; thisstep < steps; thisstep++)
          {
          rot = rot * delta;
          llSetLocalRot(rot);
          }
        }
      rot = llGetLocalRot();
      llSetPos(llGetLocalPos() - dpos*movdir*llRot2Left(rot));
      ont = 0;
      posi = dpos;
      }
    }

  // touch scripts: open, then close
  touch(integer touches)
    {
    if (on == 1)
      {
      if (posi == dpos) {
        rot = llGetLocalRot();
        llSetPos(llGetLocalPos() + dpos*movdir*llRot2Left(rot));
        posi = 0-dpos;
        ont = 1;
        if (rot_tf == 1)
          {
          delta = llEuler2Rot(<0,0,(rotdir*degper*DEG_TO_RAD)>);
          thisstep = 0;
          for (; thisstep < steps; thisstep++)
            {
            rot = rot * delta;
            llSetLocalRot(rot);
            }
          }
        llSetTimerEvent(time);
        }
      else
        {
        if (rot_tf == 1)
          {
          rot = llGetLocalRot();
          delta = llEuler2Rot(<0,0,-(rotdir*degper*DEG_TO_RAD)>);
          thisstep = 0;
          for (; thisstep < steps; thisstep++)
            {
            rot = rot * delta;
            llSetLocalRot(rot);
            }
          }
        rot = llGetLocalRot();
        llSetPos(llGetLocalPos() - dpos*movdir*llRot2Left(rot));
        posi = dpos;
        ont = 0;
        }
      }

    if (on == 0)
      {
      on = 1;
      }
    }
  }

// fin

No comments: