CODE
// radial align effector
//
// Take N objects and space them evenly in a circle of a given diamenter.
// and position. This is particularly useful for precision placement of
// columns or supports for circular structures.
//
// Usage:
// 1. add objects to be evenly radially aligned to this effector's
// object's inventory
// 2. insure that the effector is centered over the desired area
// (obviously you can link the placed objects and move them later)
// 3. touch the effector; each object will be copied round the effector
// at evenly divided intervals five meters from the effector with the object
// heights centered at the effector.
//
// Commands:
// this effector listens for "status", which will then whisper status
// messages
//
// TODO: linking created objects together so they can be fine tuned en masse
// TODO: add commands to set placement radius
// TODO: add commands for internal inventory management (though the user
// can always manually tweak the effector inventory)
// TODO: discover a way to pass in externally selected objects to this script
// so that internal inventory is unnecessary; it would just manipulate
// user selected objects
//
// Mark Coletti (Piprrr Godel)
//
vector gCirclePosition; // the circle round which we'll be orienting things
float gDiameter; // diameter for placed objects
integer gListenHandle; // handle to llListen() filter; currently unused;
// but could be used in the future for manipulation
// dump out this script's state
status()
{
llWhisper( 0, "gCirclePosition:\t" + (string)gCirclePosition );
llWhisper( 0, "\tdiameter:\t" + (string)gDiameter );
integer num_objects = llGetInventoryNumber( INVENTORY_OBJECT );
llWhisper( 0, (string)num_objects + " objects in inventory:" );
integer i;
for ( i = 0; i < num_objects; i++ )
{
string object_name = llGetInventoryName( INVENTORY_OBJECT, i );
llWhisper( 0, "\t" + object_name );
}
} // status
// error reporting
error( string message )
{
llWhisper( 0, "error:\t" + message );
} // error
// do the object placement
// Note that the original objects are KEPT IN INVENTORY; ONLY COPIES
// ARE PLACED IN THE ENVIRONMENT. I did some hand wringing over this;
// presumably the user may want to do this N times with the same
// objects, so it might be useful to keep them in inventory until such
// time that the user is done with the current configuration.
perform()
{
integer num_objects = llGetInventoryNumber( INVENTORY_OBJECT );
float x_obj;
float y_obj; // coordinates of current object being placed
float object_spacing = TWO_PI / (float)num_objects;
llWhisper( 0, "objects spaced " + (string)object_spacing + " radians apart" );
float current_angle = 0.0; // current angle of placed object in radians
vector new_pos = <0.0,0.0,gCirclePosition.z>; // position of new object
integer i;
for ( i = 0; i < num_objects; i++ )
{
string object_name = llGetInventoryName( INVENTORY_OBJECT, i );
new_pos.x = gCirclePosition.x + llCos(current_angle) * gDiameter / 2.0;
new_pos.y = gCirclePosition.y + llSin(current_angle) * gDiameter / 2.0;
llWhisper( 0, "target position:\t" + (string)new_pos );
llRezObject( object_name,
new_pos,
ZERO_VECTOR,
ZERO_ROTATION,
0 );
current_angle += object_spacing;
}
} // perform
default
{
state_entry()
{
// the center point of orientation be that of this effector
// object
gCirclePosition = llGetPos();
diameter = 10.0; // by default we'll place the items in a 10m
// diameter circle XXX add parameter change
status(); // blat status at start
gListenHandle = llListen( 0, "", llGetOwner(), "status" );
} // state_entry
// touching the effector performs the object placement
// XXX is this too, emmm, touchy? Maybe should have command to do this as
// XXX it'd be easy to accidentally touch the effector and have it
// XXX blat out more copies of the effector inventory
touch_start(integer total_number)
{
perform();
} // touch_start
listen( integer channel, string name, key id, string message )
{
if ( id == llGetOwner() )
{
if ( "status" == message )
{
status();
}
else
{
error( "don't understand " + message );
}
}
else
{
llWhisper( 0, "Go ask my owner first." );
}
} // listen
changed( integer changed_flag )
{
llWhisper( 0, "item added to inventory" );
} // changed
} // default
Please feel free to follow-up with comments and criticism.