Join us in Outworldz at www.outworldz.com:9000 or follow us:

This prim animator is is one of the most useful scripts in Second Life. It is compatible with Archipelis Designer, sculpts, mesges, and prims. Setup is very simple. Just drop the scripts into the object, click the object, and give your animation a name. Move all the prims around, and click Record. When done, click the Animation Name, and watch it play back every move! This script uses a new and very fast command called 'llSetPrimitiveParamsFast'. This means that dozens of prims can move almost instantly.

You can easily make almost anything move with no scripting knowledge needed.

Great Features and a great price - Free!


Limits: It cannot move/animate avatars that are sitting on a linked prim.

Unlike other $$ prim puppeteers and animators, there is no need to rename any prims, no need to rez and re-rez, and no limits on memory storage or number of animations or prims. It's also expandable and can take commands from other scripts.
And best of all, it is open source!

Easy menu driven controls:

menu graphic
Storage: The system automatically saves your animations to one or more storage scripts so you will not run out of memory. If you reset your script, it will lose the contents, but you can click a Save to Server button and save your data in secure, safe online database.

Easy to control: I am including example Sensor, Rez, and Wandering Pet scripts to make it easy to add animation triggers.

API support: If you have some scripting knowledge, you can use Linked Messages to can control your animation in any way you want. You can also type commands into main chat or a private chat channel. Scripts can control your animation anywhere on your sim.

Custom name your animations to run different animation sets independently of each-other in the same object.

Simple step by step directions


Make one prim and add these script: Download the scripts

Add one or more child prims, and link them to the first prim. Make sure the first prim is the last one you click, then press Ctrl-L to link them together. Here is a simple demo:



Click the prim anywhere to get the menu:



General:
Help - takes you to this web page

Finish - locks the Menu out so you cannot animate by accident.

Animation and Playback Controls:
Recordings - Lists all recordings you have made for playback
Play All - Plays back all recordings in order

External Storage controls:
Erase - Empty the remote database of all contents
Load - Loads the saved animations from external storage
Publish - Saves the recordings to the external storage

Recording Controls:
Name - Start a New Animation and give it a Name
Record - Saves the current position of any prims that have moved.
Pause - Inserts a 0.1 second pause into an animation

How to Use the Prim Animator

The first step is to name your animation. You can store as many animations as you want in the menu.

Click 'Name' on the Menu. A menu will prompt you for the name of this animation step. (Some viewers will prompt you to enter the name on a channel) The number changes each time so it will not interfere with other people who may be editing while using the same script. In this example, it suggests channel /656.

Type in a name on the channel it indicates, such as '/656 Test1'. This would be for an animation named 'Test1'. The slash and number tells Second Life this is a private conversation with the prim.



The script will tell you to Position all the child prims.

Select the Menu item 'Record'.

Move the child prim and rotate it, as I have done below, by 45 degrees:




Click Record
Click Pause to add a 0.1 second delay
Move child back with Ctrl-Z
Click Record

Click the name that you called your animation, and watch it play back the movements.

You can click PUBLISH to store the coordinates on an online database. If you reset reset the script, you can recover the data by clicking LOAD. It will reload all the coordinates and be ready to go again.

Trigger scripts:


The first script is a simple touch and playback script. When touched, it plays back animations named 'stand' and 'sit' in order, then the next time it is clicked, it plays 'sit'.


integer flag;

default
{
    touch_start(integer total_number)
    {
        if (flag++ %2 == 0)
        {
            llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
            llMessageLinked(LINK_SET,1,"wag",""); // stand on all 4's
        }
        else
            llMessageLinked(LINK_SET,1,"sit","");   // sit on rear     
    }
}



This next script is a sensor script. If an avatar gets within 5 meters distance, it plays back animation 'sit'. When all avatars have left, it plays a 'stand' animation.

		
// Sensor
integer sitting = FALSE;

default
{
    state_entry()
    {
        llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
        llSensorRepeat("","",AGENT,5,PI,5.0);   // look for people within 5 meters every 5 seconds
    }
    
    // found an avatar
    sensor(integer num_detected)
    {     
        if (sitting)
        {
            llMessageLinked(LINK_SET,1,"sit","");   // sit on rear
            sitting = FALSE;
        }
    }
    
    // no one detected?
    no_sensor()
    {
        if (! sitting)
        {
            llMessageLinked(LINK_SET,1,"stand","");     // stand on all 4's
            sitting = TRUE;
        }
    }
}

Animated Pet Script

This animated pet script requires recorded animations for left, stand , right, sit, wag

You need to pre-record 5 animations to use this script:

'right' should put the right legs forward, as when walking, and 'left' should do the opposite.
'sit should be the animal sitting down, or begging.
'stand' should be the position the animal is in when walking, with legs in a standing position.
'wag' is the tail wagging back and forth.




// pet that wanders 


vector start_pos;
integer what;
vector Destination;
float roam_range = 10;
float STRENGTH = 4.0;  // how hard to turn, bigger = ?
float DAMPING = 0.2;    // and how soon
vector direction = <3,0,0>; // push 3 
vector last_pos = <0,0,0>;  // save last position so we can detect when to walk

list buttons = ["Sit","Stand","Wag","Range","Home","Help"];
integer listener;           // handle for menus to use
key Owner;                    // you
integer channel;            // random channel for listener

tMenu()
{
    channel = llCeil(llFrand(10000) + 876);
    listener = llListen(channel,"","","");
    llDialog(Owner,"Choose an item",buttons,channel);
}

// sets up the vehicle as a car
Physics()
{
    llSetBuoyancy(0.0);
    llSetVehicleFlags(-1);
    llSetVehicleType(VEHICLE_TYPE_CAR);
    llRemoveVehicleFlags(VEHICLE_FLAG_LIMIT_MOTOR_UP | VEHICLE_FLAG_LIMIT_ROLL_ONLY);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_EFFICIENCY, 0.8);
    llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_EFFICIENCY, 0.8);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_DEFLECTION_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_LINEAR_DEFLECTION_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_HOVER_EFFICIENCY, 0.8);  // hover 
    llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_DECAY_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, .1);
    llSetVehicleVectorParam(VEHICLE_LINEAR_FRICTION_TIMESCALE, <1.0, .1, 1000.0>);
    llSetVehicleVectorParam(VEHICLE_ANGULAR_FRICTION_TIMESCALE, <.1, .1, .1>);
    llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_EFFICIENCY, .8);
    llSetVehicleFloatParam(VEHICLE_VERTICAL_ATTRACTION_TIMESCALE, .1);
    llSetVehicleFloatParam(VEHICLE_BANKING_EFFICIENCY, 0.25);
    llSetVehicleFloatParam(VEHICLE_BANKING_TIMESCALE, 0.1);
    
}

// points the animal in the correct diriction and give it a walk-like push
DoMove()
{
    llStopLookAt();
    llRotLookAt(llRotBetween(<1,0,0>, Destination - llGetPos()), STRENGTH, DAMPING);
    llSleep(DAMPING*3);
    llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, 1 * direction);
    llSleep(0.1);
    llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, ZERO_VECTOR);

}

// get a new destination
next_move()
{
     // random direction
    Destination = llGetPos();
    Destination.x += llFrand(roam_range);
    Destination.y += llFrand(roam_range);
}

DoMenu(string msg)
{
    if (msg == "Sit")
    {
       llMessageLinked(LINK_SET,1,"sit","");
       llListenRemove(listener);
    }
    else if (msg == "Wag")
    {
        llMessageLinked(LINK_SET,1,"wag","");
        llListenRemove(listener);
    }
    else if (msg == "Stand")
    {
        llMessageLinked(LINK_SET,1,"stand","");
        llListenRemove(listener);
    }
    else if (msg == "Range")
    {
        llDialog(Owner,"Range from Home:",["5","10","15","20","25","30","40","50","75"],channel);
    }
    else if (msg == "Home")
    {
        start_pos = llGetPos(); // remember our home
        llListenRemove(listener);
        llOwnerSay("Home is set, wander distance is set to " + (string) roam_range + " meters");
    }
    else if (msg == "Help")
    {
        llLoadURL(Owner,"Click for Help", "/Secondlife/Posts/Prim-Animator");
        llListenRemove(listener);
    }
    else 
    {
        roam_range = (float) msg;
        llOwnerSay("Range set to " + (string) roam_range + " meters");
        llListenRemove(listener);
    }

}



// startup state where we sit, stand and wag tail
default
{
    state_entry()
    {
        Owner = llGetOwner();
        llOwnerSay("Range set to " + (string) roam_range + " meters");
        llOwnerSay("Home set here");
        llOwnerSay("Click me for help");
        start_pos = llGetPos(); // remember our home
        
        state sitting;
    }
}

state sitting
{
    state_entry()
    {
        llSetStatus(STATUS_PHYSICS, FALSE);
        llSetTimerEvent(5);
    }
    
    listen(integer channel,string name, key id, string msg)
    {
        DoMenu(msg);
    }
        
    touch_start(integer n)
    {
       if (llDetectedKey(0) == Owner)
            tMenu();
    }
    
    timer()
    {
       if (what++ %2 == 0)
       {
            llMessageLinked(LINK_SET,1,"stand","");
            llMessageLinked(LINK_SET,1,"wag","");
        }
        else
        {
            llMessageLinked(LINK_SET,1,"sit","");
        }
       
        if (what > 2)
        {
            what = 0;
            state  moving;
        }
    }
    on_rez(integer p)
    {
        llResetScript();
    }
}

// walking around
state moving
{
    state_entry()
    {
        
        Physics();              
        llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
        llSetStatus(STATUS_PHYSICS, TRUE);      // get ready to move
        llSetTimerEvent(0.1);
    }
    
    listen(integer channel,string name, key id, string msg)
    {
        DoMenu(msg);
    }
    
    touch_start(integer n)
    {
        if (llDetectedKey(0) == Owner)
            tMenu();
    }

    
    timer()
    {
        DoMove();
        
        if (llVecDist(last_pos, llGetPos()) > .1)
        {
            llMessageLinked(LINK_SET,1,"left",""); // left foot forward
            llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
            llMessageLinked(LINK_SET,1,"right",""); // right foot forward
            llMessageLinked(LINK_SET,1,"stand",""); // stand on all 4's
            last_pos = llGetPos();
        }
        if (llVecDist(start_pos,llGetPos()) > roam_range)
            Destination = start_pos;
        
        if (llVecDist(start_pos,llGetPos()) < .5)       // at home
            state sitting;
    
        if (llVecDist(Destination,llGetPos()) < .2)     // at destination
            next_move();
            
       
        
    } 
    
    on_rez(integer p)
    {
        llResetScript();
    }
    
}

Back to the Best Free Tools in Second Life and OpenSim.