Grab Slide Lever

From Second Life Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Description

This sample script creates a slide lever which will move through a series of positions between two points as a user drags it about. This script is a part of Haravikk Mistral's Lever Library.

When dragged this lever will move in the direction it is dragged along its fixed axis until it reaches FORWARD_POINT, or BACKWARD_POINT. This will result in a lever which can be moved between these two limits simply by dragging it.

You should be wary when setting points when it comes to local and global co-ordinates. It is strongly recommended that you use only levers that are child-prims of something else, so that they may use local co-ordinates which are a lot easier to use. You can get the co-ordinates you require using the llGetLocalPos() function.

This script also contains other features, including the ability to have it reset after a period of time, and also have it contact other objects regarding changes, either using link-messages or by sending messages using whisper/say/shout/region-say. See the comments in the script below for COMMS_TYPE on how to enable these.

Script

<lsl>// ===================================================================== // Simple Touch Slide Lever by Haravikk Mistral // ===================================================================== // This script allows you to create a simple lever that when touched // will slide through a set of positions. It is best used when the lever // prim is a child of a root prim, as the slide is performed between two // points. // // This script can be used and modified freely, though I ask that you // give credit to myself where possible, and provide a link to my // wiki page at https://wiki.secondlife.com/wiki/User:Haravikk_Mistral // =====================================================================

// ===================================================================== // CONSTANTS // ===================================================================== // The following values can be used to quickly set-up a lever without // having to modify the script. Read the comments above each item to // get an idea of what to do.

// The number of lever positions from FORWARD_POINT to BACKWARD_POINT // (inclusive). Minimum POSITIONS is 2. integer POSITIONS = 3; // The starting position, positions are numbered from 1 to POSITIONS integer START_POSITION = 1; // The starting direction, TRUE will slide the lever forward from it's // starting position, FALSE will slide it backward first. When it // reaches it's limit it will change direction. integer START_DIRECTION = TRUE;

// The forward/end-point of the slide lever's movement vector FORWARD_POINT = <-0.15, 0.0, 0.0>; // The back/start-point of the slide lever's movement vector BACKWARD_POINT = <0.15, 0.0, 0.0>;

// This is the amount the lever must be dragged by before it will move // to the next position. float DRAG_SENSITIVITY = 0.5; // The axis on which to test drag-amount, only one should be set to 1.0, // the rest to 0.0, unless you know what you're doing. vector DRAG_AXIS = <-1.0, 0.0, 0.0>;

// A sound to play when moving the lever key SOUND = NULL_KEY; // The volume of the sound float SOUND_VOLUME = 1.0;

// This value determines how long the lever will wait before resetting // it's position back to START_POSITION and START_DIRECTION. Set this // to 0.0 if you never want to reset the lever. float RESET_TIME = 30.0;

// Determines what type of message this lever sends when its position // changes. The available types are: // -1 lever sends no communications (lever is a prop only) // 0 link-message (see LINK_* constants below to set-up) // 1 whisper (see CHANNEL constant) // 2 say (see CHANNEL constant) // 3 shout (see CHANNEL constant) // 4 region-say (see CHANNEL constant) // // Link messages will have the position number in their string parameter // and the key of the user who touched the lever in the key parameter. // All other message types will contain a message in the form: // <position>,<user> // That is; the position, and user-key are comma-separated. // NOTE: Any time the lever positions itself (reset) the key will be // NULL_KEY. integer COMMS_TYPE = -1;

// Determines what channel the lever whispers/says/shouts/region-says on integer CHANNEL = -1234567890;

// The link in a linked-set to send messages to upon changing position integer LINK_TARGET = LINK_ROOT; // The value to place in the integer parameter of a link-message for // easy filtering. integer LINK_FILTER = 8192;

// ===================================================================== // VARIABLES // ===================================================================== // Below here are variables, these are used by the script. integer position = 0; vector lastGrab = ZERO_VECTOR;

float positionsF = 0.0;

moveToPosition(integer newPosition, key id) {

   if (newPosition > POSITIONS) newPosition = POSITIONS;
   else if (newPosition < 1) newPosition = 1;

   integer steps = newPosition - position;
   if (!steps) return; // Already there

   integer change = 1;
   if (steps < 0) {
       change = -1;
       steps = -steps;
   }

   integer i = 0;
   vector diff = FORWARD_POINT - BACKWARD_POINT;

   do {
       position += change;
       llSetPos(BACKWARD_POINT + (
           diff * ((float)(position - 1) / positionsF))
       );
       
       if (SOUND) llPlaySound(SOUND, SOUND_VOLUME);
   } while ((++i) < steps);

   if (COMMS_TYPE >= 0) {
       if (COMMS_TYPE == 0)
           llMessageLinked(LINK_TARGET, LINK_FILTER, (string)position, id);
       else {
           string str = (string)position + "," + (string)id;

           if (COMMS_TYPE == 1) llWhisper(CHANNEL, str);
           else if (COMMS_TYPE == 2) llSay(CHANNEL, str);
           else if (COMMS_TYPE == 3) llShout(CHANNEL, str);
           else if (COMMS_TYPE == 4) llRegionSay(CHANNEL, str);
       }
   }

   if (RESET_TIME > 0.0) llSetTimerEvent(RESET_TIME);

}

default {

   state_entry() {
       positionsF = (float)(POSITIONS - 1);
       moveToPosition(START_POSITION, NULL_KEY);
   }

   touch(integer x) {
       vector grab = llDetectedGrab(0);
       vector diff = grab - lastGrab;
              diff.x *= DRAG_AXIS.x;
              diff.y *= DRAG_AXIS.y;
              diff.z *= DRAG_AXIS.z;
       float  drag = llVecMag(diff);

       if (drag > DRAG_SENSITIVITY) {
           integer sign = TRUE;
           if (diff.x < 0.0) sign = !sign;
           if (diff.y < 0.0) sign = !sign;
           if (diff.z < 0.0) sign = !sign;

           integer steps = llFloor(drag / DRAG_SENSITIVITY);
           if (steps <= 0) return;

           integer newPosition = position;
           if (sign) newPosition += steps;
           else newPosition -= steps;

           if (newPosition > POSITIONS) newPosition = POSITIONS;
           else if (newPosition < 1) newPosition = 1;

           moveToPosition(newPosition, llDetectedKey(0));
           lastGrab = grab;
       }
   }

   touch_start(integer x) {
       lastGrab = ZERO_VECTOR;
   }

   touch_end(integer x) {
       lastGrab = ZERO_VECTOR;
   }

   timer() {
       llSetTimerEvent(0.0);
       moveToPosition(START_POSITION, NULL_KEY);
   }

}</lsl>