Difference between revisions of "Smooth Sliding Door"
(Created page with '{{LSL Header}} Smooth Sliding Door Script ==Introduction== It really annoys me that there are so many bad looking doors out there that jerk around. While you can use llSetPos f...') |
m (<lsl> tag to <source>) |
||
(12 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
{{LSL Header}} | {{LSL Header}} | ||
Smooth Sliding Door Script | =Smooth Sliding Door Script= | ||
==Introduction== | ==Introduction== | ||
It really annoys me that there are so many bad looking doors out there that jerk around. While you can use llSetPos for a sliding door you have no control at what speed it moves. This sliding door script i created because i wanted to time my sliding door movements with the door sounds i had. It uses llMoveToTarget to move the door, with the door temporally turning phantom as it moves. | It really annoys me that there are so many bad looking doors out there that jerk around. While you can use llSetPos for a sliding door you have no control at what speed it moves. This sliding door script i created because i wanted to time my sliding door movements with the door sounds i had. It uses llMoveToTarget to move the door, with the door temporally turning phantom as it moves. | ||
In laggy sims it will behave a little bit funky .. the door | In laggy sims it will behave a little bit funky .. the door sometimes seeming to zoom off to the side before popping into the correct final position as the door becomes a physical object. However, even with that defect it still looks much better IMHO | ||
===For a script with fewer problems, see "Alternative Script" at the end of this page.=== | |||
==The Script== | ==The Script== | ||
< | <source lang="lsl2"> | ||
// ******************************************************************** | // ******************************************************************** | ||
// | // | ||
Line 15: | Line 18: | ||
// by SimonT Quinnell | // by SimonT Quinnell | ||
// 11/07/2009 | // 11/07/2009 | ||
// | // | ||
// NOTE: If you are going to reposition the door, do it while the door is closed. | // NOTE: If you are going to reposition the door, do it while the door is closed. | ||
Line 23: | Line 24: | ||
// Licensed under the "OpenCollar License" | // Licensed under the "OpenCollar License" | ||
// Ie. Licensed under the GPLv2, with the additional requirement that these scripts remain "full perms" in Second Life. | // Ie. Licensed under the GPLv2, with the additional requirement that these scripts remain "full perms" in Second Life. | ||
// | |||
// Edit: Simplified the script to be just a basic move script .. removed the sound triggers (5/1/2010) | |||
// | // | ||
// ******************************************************************** | // ******************************************************************** | ||
Line 31: | Line 34: | ||
// ******************************************************************** | // ******************************************************************** | ||
// Movement Constants | // Movement Constants | ||
vector OFFSET = <-2.0, 0.0, 0.0>; // Directional offset for moving the door | vector OFFSET = <-2.0, 0.0, 0.0>; // Directional offset for moving the door in x,y,z coordinates | ||
float OPENTIME = 3.5; // Time taken to open door | float OPENTIME = 3.5; // Time taken to open door | ||
float CLOSETIME = 3.5; // Time taken to close door | float CLOSETIME = 3.5; // Time taken to close door | ||
Line 58: | Line 49: | ||
vector vTargetPos; | vector vTargetPos; | ||
integer bOpen = FALSE; | integer bOpen = FALSE; | ||
integer bMoving = FALSE; | |||
// ******************************************************************** | // ******************************************************************** | ||
// Functions | // Functions | ||
// ******************************************************************** | // ******************************************************************** | ||
Line 111: | Line 61: | ||
if(!bOpen) | if(!bOpen) | ||
{ // Initial conditions | { // Initial conditions | ||
bOpen = TRUE; | |||
rRot = llGetRot(); | rRot = llGetRot(); | ||
vPosition = llGetPos(); | vPosition = llGetPos(); | ||
Line 118: | Line 69: | ||
vTargetPos = vPosition+OFFSET*rRot; | vTargetPos = vPosition+OFFSET*rRot; | ||
// Set the timer to cleanup position | // Set the timer to cleanup position | ||
llSetTimerEvent(OPENTIME); | llSetTimerEvent(OPENTIME); | ||
}else | }else | ||
{ | { | ||
bOpen = FALSE; | |||
// Target Position | // Target Position | ||
omega=CLOSETIME/llVecDist(<0,0,0>,OFFSET); | omega=CLOSETIME/llVecDist(<0,0,0>,OFFSET); | ||
vTargetPos = vPosition; | vTargetPos = vPosition; | ||
// Set the timer to cleanup position | // Set the timer to cleanup position | ||
llSetTimerEvent(CLOSETIME); | llSetTimerEvent(CLOSETIME); | ||
} | } | ||
// Set Door Physical and move it | // Set Door Physical and move it | ||
bMoving = TRUE; | |||
llSetStatus(STATUS_PHANTOM, TRUE); | llSetStatus(STATUS_PHANTOM, TRUE); | ||
llSetStatus(STATUS_PHYSICS, TRUE); | llSetStatus(STATUS_PHYSICS, TRUE); | ||
Line 146: | Line 94: | ||
{ | { | ||
state_entry() | state_entry() | ||
{ // Initial conditions | |||
rRot = llGetRot(); | |||
vPosition = llGetPos(); | |||
} | |||
touch_start(integer num_detected) | |||
{ | { | ||
MoveDoor(); | |||
} | |||
timer() | |||
{ | |||
// Clean up Position | |||
bMoving = FALSE; | |||
llSetTimerEvent(0.0); | |||
llSetStatus(STATUS_PHYSICS, FALSE); | |||
llSetStatus(STATUS_PHANTOM, FALSE); | |||
llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]); | |||
} | } | ||
}</source> | |||
{ | ==The Script with Auto-Close== | ||
// | |||
[[User:Flax Quirina|Flax Quirina]]: A minor off-spin of the script above would be to add an auto-close feature so that the door slides back after a certain user-defined period of time. | |||
<source lang="lsl2"> | |||
// ******************************************************************** | |||
// | |||
// Basic Physical Sliding Door Script | |||
// by SimonT Quinnell (11/07/2009) edited by Flax Quirina | |||
// for auto-close (17/06/2011). | |||
// | |||
// NOTE: If you are going to reposition the door, do it while the door is closed. | |||
// Otherwise it will try and use the old close position as a reference point. | |||
// | |||
// Licensed under the "OpenCollar License" | |||
// Ie. Licensed under the GPLv2, with the additional requirement that these scripts remain "full perms" in Second Life. | |||
// | |||
// Edit: Simplified the script to be just a basic move script .. removed the sound triggers (5/1/2010) | |||
// | |||
// ******************************************************************** | |||
// ******************************************************************** | |||
// CONSTANTS | |||
// ******************************************************************** | |||
// Movement Constants | |||
vector OFFSET = <-2.0, 0.0, 0.0>; // Directional offset for moving the door in x,y,z coordinates | |||
float OPENTIME = 3.5; // Time taken to open door | |||
float CLOSETIME = 3.5; // Time taken to close door | |||
float AUTO_CLOSE_TIME = 5; // Time to auto-close the door | |||
// ******************************************************************** | |||
// Variables | |||
// ******************************************************************** | |||
vector vPosition; | |||
rotation rRot; | |||
float omega=0.0; | |||
vector vTargetPos; | |||
integer bOpen = FALSE; | |||
integer bMoving = FALSE; | |||
integer destTarget; | |||
// ******************************************************************** | |||
// Functions | |||
// ******************************************************************** | |||
MoveDoor() | |||
{ | |||
if(!bOpen) | |||
{ // Initial conditions | |||
bOpen = TRUE; | |||
rRot = llGetRot(); | |||
vPosition = llGetPos(); | |||
// Target Position | |||
omega=OPENTIME/llVecDist(<0,0,0>,OFFSET); | |||
vTargetPos = vPosition+OFFSET*rRot; | |||
// Set the timer to cleanup position | |||
//llSetTimerEvent(OPENTIME); | |||
}else | |||
{ | |||
bOpen = FALSE; | |||
// Target Position | |||
omega=CLOSETIME/llVecDist(<0,0,0>,OFFSET); | |||
vTargetPos = vPosition; | |||
// Set the timer to cleanup position | |||
//llSetTimerEvent(CLOSETIME); | |||
} | } | ||
// Set Door Physical and move it | |||
bMoving = TRUE; | |||
llSetStatus(STATUS_PHANTOM, TRUE); | |||
llSetStatus(STATUS_PHYSICS, TRUE); | |||
destTarget = llTarget(vTargetPos, llVecDist(<0,0,0>,OFFSET)); | |||
llMoveToTarget(vTargetPos,omega); | |||
} | |||
{ | |||
default | |||
{ | |||
state_entry() | |||
{ // Initial conditions | |||
rRot = llGetRot(); | |||
vPosition = llGetPos(); | |||
} | |||
at_target(integer tnum, vector targetpos, vector ourpos) { | |||
if(llVecDist(targetpos, ourpos) < 0.1) { | |||
// Clean up Position | |||
bMoving = FALSE; | |||
llSetStatus(STATUS_PHYSICS, FALSE); | |||
llSetStatus(STATUS_PHANTOM, FALSE); | |||
llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]); | |||
llTargetRemove(destTarget); | |||
if(bOpen) { | |||
llSetTimerEvent(AUTO_CLOSE_TIME); | |||
} | } | ||
} | |||
} | |||
} | } | ||
touch_start(integer num_detected) | |||
{ | |||
MoveDoor(); | |||
} | |||
timer() | |||
{ | { | ||
llSetTimerEvent(0.0); | |||
MoveDoor(); | |||
} | } | ||
} | } | ||
</source> | |||
==Alternative Script== | |||
<source lang="lsl2"> | |||
// A go-Physical+Phantom Sliding Door by Omei Qunhua | |||
// with Auto-computation of movement axis and distance | |||
// To avoid problems, the script ignores touches while the door is moving | |||
vector gHome; // Position of the door in its initial closed position | |||
rotation gRot; // The initial rotation of the door prim | |||
vector gOffset; // This will be populated with the move distance stored in the appropriate axis position | |||
integer AUTO_CLOSE_TIME = 8; // Can be zero if no auto-close is desired | |||
StartMove(vector Target) | |||
{ | |||
// Set the door PHANTOM and PHYSICAL and start moving it | |||
llMoveToTarget(Target, 3); // Do this first, to avoid the door dropping | |||
llSetStatus(STATUS_PHANTOM, TRUE); | |||
llSetStatus(STATUS_PHYSICS, TRUE); | |||
llSetTimerEvent(5); // Start a timer. We will end the move after this time. | |||
} | |||
EndMove(vector Target) | |||
{ | |||
// Return the door to non-phantom, non-physical and do a final confirmatory move | |||
llSetTimerEvent(0); | |||
llSetStatus(STATUS_PHYSICS, FALSE); | |||
llSetStatus(STATUS_PHANTOM, FALSE); | |||
llSetPrimitiveParams([ PRIM_POSITION, Target, PRIM_ROTATION, gRot ]); | |||
} | |||
default | |||
{ | { | ||
state_entry() | state_entry() | ||
{ | { | ||
gRot = llGetRot(); | |||
gHome = llGetPos(); | |||
vector Scale = llGetScale(); | |||
// Find the middle sized dimension of the door prim | |||
// This determines the axis to move on, and the distance to move | |||
list lx = llListSort( [Scale.x, <1,0,0>, Scale.y, <0,1,0>, Scale.z, <0,0,1> ], 2, TRUE ); | |||
gOffset = llList2Vector(lx, 3) * llList2Float(lx, 2); // Apply the distance to move to the appropriate dimension | |||
} | } | ||
touch_end(integer total_number) | |||
{ | { | ||
state opening; | |||
} | |||
} | |||
state opening // In this state, the door is in process of opening | |||
{ | |||
state_entry() | |||
{ | |||
StartMove(gHome + gOffset * gRot); | |||
} | } | ||
timer() | |||
{ | { | ||
EndMove(gHome + gOffset * gRot); | |||
state open; | |||
} | |||
} | |||
} | } | ||
state | state open // The door is fully open | ||
{ | { | ||
state_entry() | state_entry() | ||
{ | { | ||
llSetTimerEvent(AUTO_CLOSE_TIME); // Close the door after this time (or not, if value is zero) | |||
} | |||
// We will close the door either if it's touched while fully open, or after a time | |||
touch_end(integer num) | |||
{ | |||
state closing; | |||
} | } | ||
timer() | |||
{ | { | ||
state closing; | |||
} | } | ||
} | |||
state closing // State for when the door is in the process of closing | |||
{ | |||
state_entry() | |||
{ | { | ||
StartMove(gHome); | |||
} | } | ||
timer() | timer() | ||
{ | { | ||
EndMove(gHome); | |||
state default; | |||
state | |||
} | } | ||
} | } | ||
</source> | |||
==See also== | ==See also== | ||
*[[ Script_Library | Script Library ]] | *[[ Script_Library | Script Library ]] | ||
[[Category:LSL Library|Smooth Sliding Door Script]] |
Latest revision as of 08:22, 25 January 2015
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Smooth Sliding Door Script
Introduction
It really annoys me that there are so many bad looking doors out there that jerk around. While you can use llSetPos for a sliding door you have no control at what speed it moves. This sliding door script i created because i wanted to time my sliding door movements with the door sounds i had. It uses llMoveToTarget to move the door, with the door temporally turning phantom as it moves.
In laggy sims it will behave a little bit funky .. the door sometimes seeming to zoom off to the side before popping into the correct final position as the door becomes a physical object. However, even with that defect it still looks much better IMHO
For a script with fewer problems, see "Alternative Script" at the end of this page.
The Script
// ********************************************************************
//
// Basic Physical Sliding Door Script
// by SimonT Quinnell
// 11/07/2009
//
// NOTE: If you are going to reposition the door, do it while the door is closed.
// Otherwise it will try and use the old close position as a reference point.
//
// Licensed under the "OpenCollar License"
// Ie. Licensed under the GPLv2, with the additional requirement that these scripts remain "full perms" in Second Life.
//
// Edit: Simplified the script to be just a basic move script .. removed the sound triggers (5/1/2010)
//
// ********************************************************************
// ********************************************************************
// CONSTANTS
// ********************************************************************
// Movement Constants
vector OFFSET = <-2.0, 0.0, 0.0>; // Directional offset for moving the door in x,y,z coordinates
float OPENTIME = 3.5; // Time taken to open door
float CLOSETIME = 3.5; // Time taken to close door
// ********************************************************************
// Variables
// ********************************************************************
vector vPosition;
rotation rRot;
float omega=0.0;
vector vTargetPos;
integer bOpen = FALSE;
integer bMoving = FALSE;
// ********************************************************************
// Functions
// ********************************************************************
MoveDoor()
{
if(!bOpen)
{ // Initial conditions
bOpen = TRUE;
rRot = llGetRot();
vPosition = llGetPos();
// Target Position
omega=OPENTIME/llVecDist(<0,0,0>,OFFSET);
vTargetPos = vPosition+OFFSET*rRot;
// Set the timer to cleanup position
llSetTimerEvent(OPENTIME);
}else
{
bOpen = FALSE;
// Target Position
omega=CLOSETIME/llVecDist(<0,0,0>,OFFSET);
vTargetPos = vPosition;
// Set the timer to cleanup position
llSetTimerEvent(CLOSETIME);
}
// Set Door Physical and move it
bMoving = TRUE;
llSetStatus(STATUS_PHANTOM, TRUE);
llSetStatus(STATUS_PHYSICS, TRUE);
llMoveToTarget(vTargetPos,omega);
}
default
{
state_entry()
{ // Initial conditions
rRot = llGetRot();
vPosition = llGetPos();
}
touch_start(integer num_detected)
{
MoveDoor();
}
timer()
{
// Clean up Position
bMoving = FALSE;
llSetTimerEvent(0.0);
llSetStatus(STATUS_PHYSICS, FALSE);
llSetStatus(STATUS_PHANTOM, FALSE);
llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]);
}
}
The Script with Auto-Close
Flax Quirina: A minor off-spin of the script above would be to add an auto-close feature so that the door slides back after a certain user-defined period of time.
// ********************************************************************
//
// Basic Physical Sliding Door Script
// by SimonT Quinnell (11/07/2009) edited by Flax Quirina
// for auto-close (17/06/2011).
//
// NOTE: If you are going to reposition the door, do it while the door is closed.
// Otherwise it will try and use the old close position as a reference point.
//
// Licensed under the "OpenCollar License"
// Ie. Licensed under the GPLv2, with the additional requirement that these scripts remain "full perms" in Second Life.
//
// Edit: Simplified the script to be just a basic move script .. removed the sound triggers (5/1/2010)
//
// ********************************************************************
// ********************************************************************
// CONSTANTS
// ********************************************************************
// Movement Constants
vector OFFSET = <-2.0, 0.0, 0.0>; // Directional offset for moving the door in x,y,z coordinates
float OPENTIME = 3.5; // Time taken to open door
float CLOSETIME = 3.5; // Time taken to close door
float AUTO_CLOSE_TIME = 5; // Time to auto-close the door
// ********************************************************************
// Variables
// ********************************************************************
vector vPosition;
rotation rRot;
float omega=0.0;
vector vTargetPos;
integer bOpen = FALSE;
integer bMoving = FALSE;
integer destTarget;
// ********************************************************************
// Functions
// ********************************************************************
MoveDoor()
{
if(!bOpen)
{ // Initial conditions
bOpen = TRUE;
rRot = llGetRot();
vPosition = llGetPos();
// Target Position
omega=OPENTIME/llVecDist(<0,0,0>,OFFSET);
vTargetPos = vPosition+OFFSET*rRot;
// Set the timer to cleanup position
//llSetTimerEvent(OPENTIME);
}else
{
bOpen = FALSE;
// Target Position
omega=CLOSETIME/llVecDist(<0,0,0>,OFFSET);
vTargetPos = vPosition;
// Set the timer to cleanup position
//llSetTimerEvent(CLOSETIME);
}
// Set Door Physical and move it
bMoving = TRUE;
llSetStatus(STATUS_PHANTOM, TRUE);
llSetStatus(STATUS_PHYSICS, TRUE);
destTarget = llTarget(vTargetPos, llVecDist(<0,0,0>,OFFSET));
llMoveToTarget(vTargetPos,omega);
}
default
{
state_entry()
{ // Initial conditions
rRot = llGetRot();
vPosition = llGetPos();
}
at_target(integer tnum, vector targetpos, vector ourpos) {
if(llVecDist(targetpos, ourpos) < 0.1) {
// Clean up Position
bMoving = FALSE;
llSetStatus(STATUS_PHYSICS, FALSE);
llSetStatus(STATUS_PHANTOM, FALSE);
llSetPrimitiveParams([ PRIM_POSITION, vTargetPos, PRIM_ROTATION, rRot ]);
llTargetRemove(destTarget);
if(bOpen) {
llSetTimerEvent(AUTO_CLOSE_TIME);
}
}
}
touch_start(integer num_detected)
{
MoveDoor();
}
timer()
{
llSetTimerEvent(0.0);
MoveDoor();
}
}
Alternative Script
// A go-Physical+Phantom Sliding Door by Omei Qunhua
// with Auto-computation of movement axis and distance
// To avoid problems, the script ignores touches while the door is moving
vector gHome; // Position of the door in its initial closed position
rotation gRot; // The initial rotation of the door prim
vector gOffset; // This will be populated with the move distance stored in the appropriate axis position
integer AUTO_CLOSE_TIME = 8; // Can be zero if no auto-close is desired
StartMove(vector Target)
{
// Set the door PHANTOM and PHYSICAL and start moving it
llMoveToTarget(Target, 3); // Do this first, to avoid the door dropping
llSetStatus(STATUS_PHANTOM, TRUE);
llSetStatus(STATUS_PHYSICS, TRUE);
llSetTimerEvent(5); // Start a timer. We will end the move after this time.
}
EndMove(vector Target)
{
// Return the door to non-phantom, non-physical and do a final confirmatory move
llSetTimerEvent(0);
llSetStatus(STATUS_PHYSICS, FALSE);
llSetStatus(STATUS_PHANTOM, FALSE);
llSetPrimitiveParams([ PRIM_POSITION, Target, PRIM_ROTATION, gRot ]);
}
default
{
state_entry()
{
gRot = llGetRot();
gHome = llGetPos();
vector Scale = llGetScale();
// Find the middle sized dimension of the door prim
// This determines the axis to move on, and the distance to move
list lx = llListSort( [Scale.x, <1,0,0>, Scale.y, <0,1,0>, Scale.z, <0,0,1> ], 2, TRUE );
gOffset = llList2Vector(lx, 3) * llList2Float(lx, 2); // Apply the distance to move to the appropriate dimension
}
touch_end(integer total_number)
{
state opening;
}
}
state opening // In this state, the door is in process of opening
{
state_entry()
{
StartMove(gHome + gOffset * gRot);
}
timer()
{
EndMove(gHome + gOffset * gRot);
state open;
}
}
state open // The door is fully open
{
state_entry()
{
llSetTimerEvent(AUTO_CLOSE_TIME); // Close the door after this time (or not, if value is zero)
}
// We will close the door either if it's touched while fully open, or after a time
touch_end(integer num)
{
state closing;
}
timer()
{
state closing;
}
}
state closing // State for when the door is in the process of closing
{
state_entry()
{
StartMove(gHome);
}
timer()
{
EndMove(gHome);
state default;
}
}