Difference between revisions of "Smooth Rotating Door"
(Version 1.1) |
(Version 1.2) |
||
Line 5: | Line 5: | ||
Most doors in SL use the same method for opening. They set the door's rotation in one or more steps, resulting in a somewhat choppy motion. This script uses a mixture of llTargetOmega() and llSetLocalRot() to achieve a very smooth, pleasant looking animation for the door. In laggy environments it might be that the script displays a somewhat flaky behavior, but for most cases it will work nicely. | Most doors in SL use the same method for opening. They set the door's rotation in one or more steps, resulting in a somewhat choppy motion. This script uses a mixture of llTargetOmega() and llSetLocalRot() to achieve a very smooth, pleasant looking animation for the door. In laggy environments it might be that the script displays a somewhat flaky behavior, but for most cases it will work nicely. | ||
<lsl>// Smooth Door Script - Version 1. | For those unfamiliar with the typical swinging door, you use a box and do a path cut 0.375 / 0.875 to remove one-half of the prim. This will make appear as if it is swinging on its edge and not around it's middle. | ||
<lsl>// Smooth Door Script - Version 1.2 | |||
// by Toy Wylie | // by Toy Wylie | ||
// Distributed under the following licence: | // Distributed under the following licence: | ||
Line 14: | Line 16: | ||
// - You may modify this script as needed | // - You may modify this script as needed | ||
float openingTime= | float openingTime=3.0; // in seconds | ||
float openingAngle=90.0; // in degrees | float openingAngle=90.0; // in degrees | ||
float autocloseTime= | float autocloseTime=15.0; // in seconds | ||
integer steps=4; // number of internal rotation steps | integer steps=4; // number of internal rotation steps | ||
integer world=TRUE; // align to world or root prim rotation | |||
string soundOpen="door_open"; | |||
string soundClose="door_close"; | |||
float omega=0.0; | float omega=0.0; | ||
Line 28: | Line 34: | ||
integer open; | integer open; | ||
sound(string name) | |||
{ | { | ||
if(llGetInventoryType(name)==INVENTORY_SOUND) | |||
llTriggerSound(name,1.0); | |||
if( | |||
} | } | ||
openDoor(integer yes) | |||
{ | { | ||
if(yes) | |||
sound(soundOpen); | |||
vector useAxis=axis; | vector useAxis=axis; | ||
open=yes; | open=yes; | ||
Line 161: | Line 61: | ||
if(!open) | if(!open) | ||
{ | { | ||
axis= | axis=<0.0,0.0,1.0>/llGetRootRotation(); | ||
closedRot=llGetLocalRot(); | closedRot=llGetLocalRot(); | ||
openRot=llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD)* | |||
if(world) | |||
openRot=llGetRot()*llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD)/llGetRootRotation(); | |||
else | |||
openRot=closedRot*llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD); | |||
} | } | ||
swinging=steps; | swinging=steps; | ||
Line 205: | Line 110: | ||
if(open) | if(open) | ||
amount=1.0-amount; | amount=1.0-amount; | ||
llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,slerp(closedRot,openRot,amount)]); | |||
return; | return; | ||
} | } | ||
Line 212: | Line 117: | ||
if(open) | if(open) | ||
{ | { | ||
llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,openRot]); | |||
llSetTimerEvent(autocloseTime); | llSetTimerEvent(autocloseTime); | ||
} | } | ||
else | else | ||
{ | { | ||
llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,closedRot]); | |||
sound(soundClose); | |||
llSetTimerEvent(0.0); | llSetTimerEvent(0.0); | ||
} | } | ||
Line 231: | Line 137: | ||
==Changelog== | ==Changelog== | ||
Version 1.2: | |||
* Now always aligns to the global coordinate system or root prim rotation, so you don't need two scripts anymore | |||
* Added graceful sound handling | |||
Version 1.1: | Version 1.1: | ||
* Added rotation steps so people can start walking through the halfways-open door already | * Added rotation steps so people can start walking through the halfways-open door already | ||
* Added opening on collision | * Added opening on collision |
Revision as of 13:06, 1 January 2011
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Smooth Rotating Door Script
Introduction
Most doors in SL use the same method for opening. They set the door's rotation in one or more steps, resulting in a somewhat choppy motion. This script uses a mixture of llTargetOmega() and llSetLocalRot() to achieve a very smooth, pleasant looking animation for the door. In laggy environments it might be that the script displays a somewhat flaky behavior, but for most cases it will work nicely.
For those unfamiliar with the typical swinging door, you use a box and do a path cut 0.375 / 0.875 to remove one-half of the prim. This will make appear as if it is swinging on its edge and not around it's middle.
<lsl>// Smooth Door Script - Version 1.2 // by Toy Wylie // Distributed under the following licence: // - You can use it in your own works // - You can sell it with your work // - This script must remain full permissions // - This header notice must remain intact // - You may modify this script as needed
float openingTime=3.0; // in seconds float openingAngle=90.0; // in degrees float autocloseTime=15.0; // in seconds integer steps=4; // number of internal rotation steps integer world=TRUE; // align to world or root prim rotation
string soundOpen="door_open"; string soundClose="door_close";
float omega=0.0;
vector axis; rotation closedRot; rotation openRot;
integer swinging; integer open;
sound(string name) {
if(llGetInventoryType(name)==INVENTORY_SOUND) llTriggerSound(name,1.0);
}
openDoor(integer yes) {
if(yes) sound(soundOpen);
vector useAxis=axis; open=yes;
if(!yes) useAxis=-axis;
llSetTimerEvent(openingTime/(float) steps); llTargetOmega(useAxis,omega,1.0);
}
go() {
if(swinging==0) { if(!open) { axis=<0.0,0.0,1.0>/llGetRootRotation();
closedRot=llGetLocalRot();
if(world) openRot=llGetRot()*llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD)/llGetRootRotation(); else openRot=closedRot*llEuler2Rot(<0.0,0.0,openingAngle>*DEG_TO_RAD); } swinging=steps; openDoor(!open); }
}
rotation slerp(rotation source,rotation target,float amount) {
return llAxisAngle2Rot(llRot2Axis(target/=source),amount*llRot2Angle(target))*source;
}
default {
state_entry() { swinging=0; open=FALSE; omega=TWO_PI/360*openingAngle/openingTime; llTargetOmega(ZERO_VECTOR,1.0,1.0); }
touch_start(integer dummy) { go(); }
collision_start(integer dummy) { go(); }
timer() { if(swinging>0) { swinging--; if(swinging!=0) { float amount=(float) swinging/(float) steps; if(open) amount=1.0-amount; llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,slerp(closedRot,openRot,amount)]); return; }
llTargetOmega(axis,0.0,0.0); if(open) { llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,openRot]); llSetTimerEvent(autocloseTime); } else { llSetLinkPrimitiveParamsFast(LINK_THIS,[PRIM_ROT_LOCAL,closedRot]); sound(soundClose); llSetTimerEvent(0.0); } } else // autoclose time reached { llSetTimerEvent(0.0); openDoor(!open); swinging=steps; } }
}</lsl>
Changelog
Version 1.2:
- Now always aligns to the global coordinate system or root prim rotation, so you don't need two scripts anymore
- Added graceful sound handling
Version 1.1:
- Added rotation steps so people can start walking through the halfways-open door already
- Added opening on collision