Difference between revisions of "Smooth Sliding Door"

From Second Life Wiki
Jump to navigation Jump to search
m
(Alternative script)
Line 6: Line 6:


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
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==
Line 228: Line 231:
     }
     }
}
}
</lsl>
==Alternative Script==
<lsl>
// 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
string    gAxis;                      // will be "x", "y" or "z" after we compute the desired axis
vector    gOffset;
rotation  gRot;
vector    gHome;
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, "x", Scale.y, "y", Scale.z, "z"], 2, TRUE);
        float Dist  = llList2Float(lx, 2);
        gAxis  = llList2String(lx, 3);
        gOffset = < (Dist * (gAxis == "x") ), (Dist * (gAxis == "y")), (Dist * (gAxis == "z"))>;
    }
    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;
    }
}
</lsl>
</lsl>



Revision as of 06:42, 25 April 2014

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

<lsl> // ******************************************************************** // // 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 ]);        
   }

}</lsl>

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.

<lsl> // ******************************************************************** // // 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();
   }

} </lsl>

Alternative Script

<lsl> // 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

string gAxis; // will be "x", "y" or "z" after we compute the desired axis vector gOffset; rotation gRot; vector gHome; 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, "x", Scale.y, "y", Scale.z, "z"], 2, TRUE);
       float Dist   = llList2Float(lx, 2);
       gAxis   = llList2String(lx, 3);
       gOffset = < (Dist * (gAxis == "x") ), (Dist * (gAxis == "y")), (Dist * (gAxis == "z"))>;
   }
   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;
   }

}

</lsl>

See also