Grab Slide Lever
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>