//////////
// Stackable Graph Cube script
//
// Author: Peter R. Bloomfield (SL: Pedro McMillan)
//
// Place this script inside several independent cubes.
// You can then drag the cubes around, and they will stack neatly.
// Hopefully. :-)
//
//
// Note regarding object naming:
// You can name the cubes whatever you like, but make sure all cubes which need
// stack together have the SAME name.
//
// Note regarding scaling:
// This is currently setup for a cube of size 0.5x0.5x0.5.
// If you want to use a different scale, then change the "cubeSize" variable below.
// Also update the "scanRange" variable to roughly double the width of a cube.
//
// You can use shapes other than cubes too.
// Just update "scanRange" to double the largest dimension.
//
//
// Known problems:
// - can end up with 2 cubes occupying same space easily
// - does not always detect when it has been moved
//
//
//////////
// GPL:
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//////////
// What size are all cubes expected to be?
vector cubeSize = <0.5, 0.5, 0.5>;
// How far should we scan for other cubes?
float scanRange = 1.0;
// This will store the position after our last movement
vector lastMove = <0.0, 0.0, 0.0>;
default
{
state_entry()
{
}
moving_start()
{
// Activate physics for as long as the cube is being moved
llSetPrimitiveParams([PRIM_PHYSICS, TRUE]);
}
moving_end()
{
// Store our current position (in case the sensor is delayed)
lastMove = llGetPos();
// Look around for other nearby graph cubes
llSensor(llGetObjectName(), NULL_KEY, SCRIPTED | PASSIVE | ACTIVE, scanRange, PI);
// Deactivate physics so we don't get a feedback loop
// (aligns self -> physics moves it slightly -> realigns self -> etc..)
llSetPrimitiveParams([PRIM_PHYSICS, FALSE]);
}
sensor(integer num_detected)
{
// Go through each sensed object to find the nearest one BELOW this
integer i = 0;
float nearestDist = -1.0;
float curDist = 0.0;
vector nearestPos = <0.0, 0.0, 0.0>;
vector curPos = <0.0, 0.0, 0.0>;
rotation nearestRot = ZERO_ROTATION;
for (i = 0; i < num_detected; i++) {
// Is this below our current position?
curPos = llDetectedPos(i);
if (curPos.z < lastMove.z) {
// Yes - is it the nearest so far?
curDist = llVecDist(curPos, lastMove);
if (nearestDist < 0.0 || curDist < nearestDist) {
nearestDist = curDist;
nearestPos = curPos;
nearestRot = llDetectedRot(i);
}
}
}
// Did we end up finding a suitable cube underneath us?
if (nearestDist > 0.0) {
// Yes - move directly above above, and use the same orientation
nearestPos.z += cubeSize.z;
llSetPrimitiveParams([PRIM_POSITION, nearestPos, PRIM_ROTATION, nearestRot]);
}
}
no_sensor()
{
// Nothing detected
}
}