SkidzPartz.com OpenSim Open Source Prim Animation Script
|

OpenSim Categories

Who's Online

We have 11 guests online

Users Online

None

Help support us

Prim Animation Script PDF Print E-mail
OpenSim - Open Source
Written by Skidz Tweak   
Friday, 07 October 2011 14:12

This script animates linked sets of prims. For details on how to use it read in the comments. This script won't work in Second Life because it uses the function osMakeNotecard. 

You can download it here.




//------------------------------------------------------
// Skidz Partz Multiprim animator
//------------------------------------------------------
// The latest version of this script can always be found
// in the Opensim section of www.SkidzPartz:
// http://www.skidzpartz.com/index.php/opensim/67-open-source/308-prim-animation-script
// This script is free to use, but whereever it is used
// the SCRIPT's permissions MUST be set to:
// [x] Next owner can modify
// [x] Next owner can copy
// [x] Next owner can transfer
// [x] Allow anyone to copy
// [x] Share with group

//------------------------------------------------------
// Acknowledgement
//------------------------------------------------------
// This script was based on Timeless linked Door script 
// orginally, but has been heavly modified to use note
// cards, more than 2 frames, and multiple prims

//------------------------------------------------------
// USAGE INSTRUCTIONS FOR EVERYDAY USE:
//------------------------------------------------------
// Say the following commands on channel 0:
// 'unlock'     - Unlocks all doors in range.
// 'lock'       - Locks all doors in range and allows
//                only the permitted users to open it.
// To open the door, either Touch it, Walk into it or
// say 'open' or say 'close'.

//------------------------------------------------------
// USAGE INSTRUCTIONS FOR BUILDERS:
//------------------------------------------------------
// 1. Copy and paste this script into the door prim and
//    change the settings (see further down).
// 2. The door prim must be linked to at least one other
//    prim (could be linked to the house for example).
// 3. The door prim MUST NOT be the root prim.
// 4. If you wish to animate more than one prim, ensure 
//    each one is named the same. 
// 4. Use Edit Linked Parts to move, rotate and size the
//    door prim for the closed state.
// 5. When ready, stand close to the door and say
//    '/1 /door record' (this records the closed door
//    position, rotation and size to the object's
//    name and description).
// 6. Use the Edit Linked parts to move, rotate and size
//    the door prim for the opened state.
// 7. When ready, stand close to the door and say
//    '/1 /door record' (this records the opened door
//    position, rotation and size).
// 9. When finished say '/1 finished'.
// 8. Once recorded it will not accept these commands
//    again. If you do need to redo the settings then
//    delete the Name and Description of the door prim
//    (these are where the position information is
//    stored), and then follow the steps above again.
//    Note: deleting the object name won't save, so set
//    the object name to 'Object' to reset the object
//    name.

//------------------------------------------------------
// Tips
//------------------------------------------------------
// 1. osMakeNotecard must be enabled on the region for 
//    the setup to work.
// 2. You can have multiple animations in the samed linked
//    set, just ensure the prims are named different things
// 3. There can be as many frames in the animation as you like

//------------------------------------------------------
// Change these settings to suit your needs.
//------------------------------------------------------
// To mute any/all of the sounds set the sound string(s)
// to "" (empty string).
// To get the UUID of a sound, right click on the sound
// in your inventory and choose "Copy Asset UUID", then
// paste the UUID in here.
string      doorOpenSound       = "aa0751fc-3df3-4020-b06c-e71a7234d1f4";
string      doorCloseSound      = "95b3c22e-de8a-4893-b8f4-67bbd83d4466";
string      confirmedSound      = "2669ee8d-9aa3-48c7-b801-455681581def";
string      accessDeniedSound   = "a7d6da2a-f372-4a36-8915-3cd16624732c";
string      doorBellSound       = "741bbe0c-20ca-4569-8b4b-8a3f9424211a"; // Setting to empty stops door announcements too.
float       autoCloseTime       = 120.0; // 0 seconds to disable auto close.
integer     allowGroupToo       = TRUE; // Set to FALSE to disallow same group access to door.
list        allowedAgentUUIDs   = ["da7e3fbe-72bf-40a7-8a26-db752ff2c41d"]; // Comma-separated, quoted list of avatar UUIDs who are allowed access to this door.
integer     listenChannel       = 1;
string      doorName            = "Door";  // How this door will identify itself when speaking on chat
float	 	timeToSleepBetweenFrames = 1.0;

//------------------------------------------------------
// Leave the rest of the settings alone, these are
// handled by the script itself.
//------------------------------------------------------
integer     isLocked            = FALSE; // Only when the door is locked do the permissions apply.
integer     isOpen              = FALSE;
vector      openPos             = ZERO_VECTOR;
rotation    openRot             = ZERO_ROTATION;
vector      openScale           = ZERO_VECTOR;
vector      closedPos           = ZERO_VECTOR;
rotation    closedRot           = ZERO_ROTATION;
vector      closedScale         = ZERO_VECTOR;
key         openerKey           = NULL_KEY;
key         closerKey           = NULL_KEY;
integer     isSetup             = FALSE;
integer     listenHandle        = 0;
string      avatarName          = "";

// don't touch anything below this!!!!!!!!!
list         loadedValues        = [];
integer     frame                = -1;
integer     noteCount             = -1;
integer        noteNumber             = -1;
key         lineID; 
integer     primLooper            = 0;
integer     isLoadingParams     = FALSE;
integer     primsUsedInAnimaton = 0;
integer        framesUsedInAnimation = 0;
integer     foundAnyOnThisFrame = FALSE;

mySayName(integer channel, string objectName, string message)
{
    string name = llGetObjectName();
    llSetObjectName(objectName);
    llSay(0, "/me " + message);
    llSetObjectName(name);
}

mySay(integer channel, string message)
{
    string name = llGetObjectName();
    llSetObjectName(doorName);
    llSay(0, message);
    llSetObjectName(name);
}

myOwnerSay(string message)
{
    string name = llGetObjectName();
    llSetObjectName(doorName);
    llOwnerSay(message);
    llSetObjectName(name);
}

mySoundConfirmed()
{
    if (confirmedSound != "")
    {
        llTriggerSound(confirmedSound, 1.0);
    }
}

mySoundAccessDenied()
{
    if (accessDeniedSound != "")
    {
        llTriggerSound(accessDeniedSound, 1.0);
    }
}

string mySubStr(string data, list drop, string replace)
{
    list listdata = llParseString2List(data,drop,[]);
    return llDumpList2String(listdata,replace);
}

string myDropWS(string data)
{
    data = mySubStr(data,[" ","<",">"],""); // get rid of spaces and vector/rotation delimiters
    data = mySubStr(data,["-0."],"-.");     // no leading zeros
    data = mySubStr(data,[",0."],",.");
    data = mySubStr(data,[";0."],";.");
    return data;
}

vector myGetVector(string data)
{
    return (vector)("<"+(string)data+">");
}

rotation myGetRot(string data)
{
    return llEuler2Rot(myGetVector(data));
}

readNextNotecard()
{
    integer primCount = llGetNumberOfPrims();
    integer foundOne = 0;
    // we have to load them in order..
    foundOne = 0;
    do
    {
        primLooper = primLooper + 1;
        
        if (primCount >= primLooper)
        {
            
            if (llGetInventoryType("Prim-" + (string)primLooper + "-" + (string)frame) != INVENTORY_NONE)
            {
                foundOne = 1 ;
                foundAnyOnThisFrame = TRUE ;
                if (frame == 1)
                    primsUsedInAnimaton = primsUsedInAnimaton + 1;
                lineID = llGetNotecardLine("Prim-" + (string)primLooper + "-" + (string)frame, 0);
                llSetTimerEvent(4);
            }
        }
        else
        {        
            foundOne = 1;
        }
        
        
    } while(foundOne == 0);

    if ((foundAnyOnThisFrame) && (primLooper > primCount))
    {
        frame = frame + 1;
        primLooper = -1;
        foundAnyOnThisFrame = FALSE;
		isLoadingParams = FALSE;
        readNextNotecard();
        
    }
    else if ((!foundAnyOnThisFrame) && (primLooper > primCount))
    {
        framesUsedInAnimation = frame;
		isLoadingParams = FALSE;
        isSetup = TRUE;
        llOwnerSay("Finished loading - (" + (string)framesUsedInAnimation + ") Frames in animation, (" + (string)primsUsedInAnimaton + ") Prims used in animation.");
    }
}

myGetDoorParams()
{
    isLoadingParams = TRUE ;
    noteCount = llGetInventoryNumber(INVENTORY_NOTECARD);
    noteNumber = -1;
    primLooper = -1;
    primsUsedInAnimaton = 0;
    frame = 0;
    foundAnyOnThisFrame = FALSE;
    readNextNotecard();
}

integer myPermissionCheck(key id)
{
    integer hasPermission = FALSE;
    if (isLocked == FALSE)
    {
        hasPermission = TRUE;
    }
    else if (llGetOwnerKey(id) == llGetOwner())
    {
        hasPermission = TRUE;
    }
    else if (allowGroupToo == TRUE && llSameGroup(id))
    {
        hasPermission = TRUE;
    }
    else if (llListFindList(allowedAgentUUIDs, [(string)id]) != -1)
    {
        hasPermission = TRUE;
    }
    return hasPermission;
}

myOpenDoor()
{
    isOpen = FALSE;
    myToggleDoor();
}

myCloseDoor()
{
    isOpen = TRUE;
    myToggleDoor();
}

myToggleDoor()
{
    if (isSetup == FALSE)
    {
        myOwnerSay("The "+doorName+" prim has not been configured yet. Please read the usage instructions in the "+doorName+" script.");
    }
    else if (llGetLinkNumber() == 0 || llGetLinkNumber() == 1)
    {
        myOwnerSay("The "+doorName+" prim must be linked to at least one other prim and the "+doorName+" prim must not be the root prim");
    }
    else
    {
        isOpen = !isOpen;
        if (isOpen)
        {
            if (doorBellSound != "")
            {
                llTriggerSound(doorBellSound, 1.0);
                if (avatarName != "")
                {
                    mySayName(0, avatarName, "is at the "+doorName+".");
                    avatarName = "";
                }
            }
            if (doorOpenSound != "")
            {
                llTriggerSound(doorOpenSound, 1.0);
            }
            
            
            integer ii =  0;
            while(framesUsedInAnimation >= ++ii)
            {
				
                integer i = 0;
                while(primsUsedInAnimaton >= ++i)
                {
					integer positionOffset = ((ii * primsUsedInAnimaton) * 4);
                    positionOffset = positionOffset - (i * 4);
					if (llGetLinkNumber() == (integer)llList2String(loadedValues, positionOffset))
                        llSetPrimitiveParams([ PRIM_POSITION , myGetVector(llList2String(loadedValues, positionOffset + 1)) , PRIM_ROTATION , ZERO_ROTATION * myGetRot(llList2String(loadedValues, positionOffset + 2)) / llGetRootRotation(), PRIM_SIZE , myGetVector(llList2String(loadedValues, positionOffset + 3)) ] );
                    else
                        llSetLinkPrimitiveParamsFast((integer)llList2String(loadedValues, positionOffset), [ PRIM_POSITION , myGetVector(llList2String(loadedValues, positionOffset + 1)) , PRIM_ROTATION , ZERO_ROTATION * myGetRot(llList2String(loadedValues, positionOffset + 2)) / llGetRootRotation(), PRIM_SIZE , myGetVector(llList2String(loadedValues, positionOffset + 3)) ] );
                }
                llSleep(timeToSleepBetweenFrames);
            }
			
            llMessageLinked(LINK_SET, 255, "cmd|door|opened", NULL_KEY);
        }
        else
        {
            if (doorCloseSound != "")
            {
                llTriggerSound(doorCloseSound, 1.0);
            }
            
            
            integer iiii = framesUsedInAnimation + 1;
            while(1 <= --iiii)
            {
				
                integer iii = primsUsedInAnimaton + 1;
                while(1 <= --iii)
                {
                    integer positionOffset = ((iiii * primsUsedInAnimaton) * 4);
					positionOffset = positionOffset - (iii * 4);
					if (llGetLinkNumber() == (integer)llList2String(loadedValues, positionOffset))
                        llSetPrimitiveParams([ PRIM_POSITION , myGetVector(llList2String(loadedValues, positionOffset + 1)) , PRIM_ROTATION , ZERO_ROTATION * myGetRot(llList2String(loadedValues, positionOffset + 2)) / llGetRootRotation(), PRIM_SIZE , myGetVector(llList2String(loadedValues, positionOffset + 3)) ] );
                    else
						llSetLinkPrimitiveParamsFast((integer)llList2String(loadedValues, positionOffset), [ PRIM_POSITION , myGetVector(llList2String(loadedValues, positionOffset + 1)) , PRIM_ROTATION , ZERO_ROTATION * myGetRot(llList2String(loadedValues, positionOffset + 2)) / llGetRootRotation(), PRIM_SIZE , myGetVector(llList2String(loadedValues, positionOffset + 3)) ] );
                }
                llSleep(timeToSleepBetweenFrames);
            }
            
            llMessageLinked(LINK_SET, 255, "cmd|door|closed", NULL_KEY);
        }
        
        llSetTimerEvent(0.0);
        if (isOpen == TRUE && autoCloseTime != 0.0)
        {
            llSetTimerEvent(autoCloseTime);
        }
    }
}

default
{
    state_entry()
    {
        listenHandle = llListen(listenChannel, "", NULL_KEY, "");
        myGetDoorParams();
    }

    touch_start(integer total_number)
    {
        if (myPermissionCheck(llDetectedKey(0)) == TRUE)
        {
            avatarName = llDetectedName(0);
            myToggleDoor();
        }
        else
        {
            mySoundAccessDenied();
        }
    }
    
    timer()
    {
        if (isLoadingParams)
        {
            llSetTimerEvent(0);
            // roll back the count and try again
            primLooper = primLooper - 1;
            if (frame == 1)
            {
                primsUsedInAnimaton = primsUsedInAnimaton - 1;
            }
            readNextNotecard();
        }
        else
        {
            myCloseDoor();
        }
    }
    
    link_message(integer sender_num, integer num, string str, key id)
    {
        // Door API. The API is here in case you want to create PIN entry keypads or whatever.
        if (num == llGetLinkNumber())
        {
            if (str == "cmd|door|doOpen")
            {
                myOpenDoor();
            }
            else if (str == "cmd|door|doClose")
            {
                myCloseDoor();
            }
        }
        if (str == "cmd|door|discover")
        {
            llMessageLinked(LINK_SET, 255, "cmd|door|discovered|" + (string)llGetKey(), id);
        }
    }
    
    listen(integer channel, string name, key id, string message)
    {
        // Performance note: it's quicker to compare the strings than to compare permissions each time anyone says anything on this channel.
        if (message == "open")
        {
            if (myPermissionCheck(id) == TRUE)
            {
                // Only open the door if the person is quite close to this door.
                openerKey = id;
                closerKey = NULL_KEY;
                avatarName = name;
                llSensor(name, id, AGENT, 5.0, TWO_PI);
            }
            else
            {
                mySoundAccessDenied();
            }
        }
        else if (message == "close")
        {
            if (myPermissionCheck(id) == TRUE)
            {
                openerKey = NULL_KEY;
                closerKey = id;
                avatarName = name;
                // Only close the door if the person is quite close to this door.
                llSensor(name, id, AGENT, 5.0, TWO_PI);
            }
            else
            {
                mySoundAccessDenied();
            }
        }
        else if (message == "lock")
        {
            if (myPermissionCheck(id) == TRUE)
            {
                isLocked = TRUE;
                mySoundConfirmed();
            }
            else
            {
                mySoundAccessDenied();
            }
        }
        else if (message == "unlock")
        {
            if (myPermissionCheck(id) == TRUE)
            {
                isLocked = FALSE;
                mySoundConfirmed();
            }
            else
            {
                mySoundAccessDenied();
            }
        }
        else if (message == "/door record" && llSubStringIndex(llGetObjectDesc(), "Finished") == -1)
        {
            if (llGetOwnerKey(id) == llGetOwner())
            {
                integer i = 0;
                mySoundConfirmed();
                while(llGetNumberOfPrims() >= ++i)
                {
                    if (llGetLinkName(i) == llGetObjectName())
                    {
						list tosave = llGetLinkPrimitiveParams(i, [ PRIM_POS_LOCAL , PRIM_ROT_LOCAL, PRIM_SIZE ]);
						tosave = llListReplaceList(tosave, [llRot2Euler((rotation)llList2String(tosave, 1))], 1, 1);
                        osMakeNotecard("Prim-" + (string)i + "-" + (string)frame, myDropWS("SKIDZ-PARTZ;" + (string)i + ";" + llDumpList2String(tosave, ";")));
                    }
                }
                frame = frame + 1;
            }
            else
            {
                mySoundAccessDenied();
            }
        }
        else if (message == "finished")
        {
            llSetObjectDesc("Finished");
			llResetScript();
        }
    }
    
    sensor(integer num_detected)
    {
        if (openerKey != NULL_KEY)
        {
            integer i;
            for (i = 0; i < num_detected; i++)
            {
                if (llDetectedKey(i) == openerKey && myPermissionCheck(llDetectedKey(i)) == TRUE)
                {
                    myOpenDoor();
                }
            }
            openerKey = NULL_KEY;
        }
        else
        {
            integer i;
            for (i = 0; i < num_detected; i++)
            {
                if (llDetectedKey(i) == closerKey && myPermissionCheck(llDetectedKey(i)) == TRUE)
                {
                    myCloseDoor();
                }
            }
            closerKey = NULL_KEY;
        }
    }
    
    dataserver(key query_id, string data) 
    {
        if (query_id == lineID) 
        {
            // llSay(0,data);
            llSetTimerEvent(0);
            list noteresults = llParseString2List(data,[";"],[]);
            if (llList2String(noteresults,0) == "SKIDZ-PARTZ")
            {
                loadedValues = loadedValues + llList2List(noteresults, 1, -1);
                readNextNotecard();
            }
        }
    }

// ------------------------------------------------------
// Uncomment the following code if you particularly want
// collisions to affect the door state.    
// ------------------------------------------------------

//    collision_start(integer num_detected)
//    {
//        integer i;
//        for (i = 0; i < num_detected; i++)
//        {
//            if (myPermissionCheck(llDetectedKey(i)) == TRUE)
//            {
//                avatarName = llDetectedName(i);
//                myOpenDoor();
//            }
//            else if (llDetectedType(i) & AGENT)
//            {
//                mySoundAccessDenied();
//            }
//        }
//    }

} // End of default state and end of script.


Last Updated on Friday, 07 October 2011 22:23
 

Skidz Partz Shopping

Your cart is empty

Skidz Partz Blog RSS

Skidz Partz

SkidzPartz Login

Polls

Should the TMat 4.0 be made of Mesh? This does not mean it will support mesh, just made of mesh..
 

CB Workflows