removed useless _ folders
This commit is contained in:
@@ -0,0 +1,555 @@
|
||||
// :CATEGORY:Prim Animator
|
||||
// :NAME:Archipelis scripts for prim animator
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :CREATED:2013-09-06
|
||||
// :EDITED:2013-09-18 15:38:48
|
||||
// :ID:52
|
||||
// :NUM:72
|
||||
// :REV:2
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// An almost unlimited space prim animator. It uses multiple Store Scripts, that can hold thousands of prim animations
|
||||
// This is the latest version of the script. Must be used with Multiple copies of Store 0..1,2, to animate prims
|
||||
|
||||
// :CODE:
|
||||
|
||||
// 06/20/2011
|
||||
// Author Ferd Frederix
|
||||
// Use with one or more copies of the script 'Store 0..Store 1.. Store N'
|
||||
// Copyright 2011 Fred Beckhusen aka Ferd Frederix
|
||||
//
|
||||
// Licensed under the GNU Version3 license at http://www.gnu.org/copyleft/gpl.html
|
||||
// This program and the STORE scipts it uses must be left Copy/Transfer/MOD
|
||||
// Any items that use these scripts may have more restrictive permissions.
|
||||
|
||||
// for help and how to use, see "http://meteverse.mitsi.com/secondlife/Posts/Prim-Animator-DB
|
||||
|
||||
// Prim position root script
|
||||
// Put this script in the root prim.
|
||||
// touch the prim to start recording
|
||||
|
||||
// Record - store a new set of child prim positions
|
||||
// Clear RAM - wipe out all recording in the prim. Leaves the database intact
|
||||
// Pause - insert a 0.1 second pause
|
||||
// Erase - Erases the Server data
|
||||
// Load - Loads the data from the Server
|
||||
// Publisgh - Saves the data to the database
|
||||
// Recordings - Lists all recordings ( up to 16)
|
||||
// Name - name a new recording
|
||||
// Play All Plays back all recordings with a 1 second Pause.
|
||||
|
||||
// Publish - Saves to database
|
||||
// Help - Get Web Help
|
||||
// More - TBD
|
||||
|
||||
// configurable things
|
||||
|
||||
|
||||
|
||||
|
||||
string MyName ; // The creator of the animation
|
||||
string MyItemName; // a Name just for this unique item and any copies
|
||||
|
||||
integer debug = FALSE; // if set to TRUE, debug info appears
|
||||
|
||||
// Code follows - no need to edit below this line.
|
||||
// remote db reading
|
||||
key kHttpRequestID;
|
||||
|
||||
|
||||
integer countLoaded = 0; // how many nanims have been loaded via HTTP
|
||||
|
||||
integer iPlayChannel = 1; // the playback channel, this is the channel you use in LinkMessages
|
||||
integer countchannel= 2001; // how many have been saved
|
||||
integer iDialogChannel ; // dialog boxes
|
||||
integer iPrimCount ; // total number of prims
|
||||
integer iWantNameFlag; // flag indicating we are waiting for a name to be chatted
|
||||
integer imax; // total records in store
|
||||
integer runtime = 0; // set to 1 after Recording and publishing.
|
||||
// animation store
|
||||
string sCurrentAnimationName; // The name of the animation we are playing
|
||||
string sPriorAniName; // the prior animation name so we can spot differences as we read them in
|
||||
list lLastPrimList; // storage of the last prim position we learned
|
||||
integer iLastSTRIDE = 4; // size of the last prim list
|
||||
integer iListenerHandle; // temp iListenerHandle when we are waiting for them to give us a name
|
||||
list lUserAnimNames; // animations read from the notecard added to the Menu display
|
||||
|
||||
|
||||
// Commands
|
||||
integer Clear = 99; // erase local db
|
||||
integer Erase = 100; // erase Server DB command
|
||||
integer Add = 101; // add a coordinate
|
||||
integer Publish = 102; // save to db
|
||||
integer Name = 103; // send Name to db
|
||||
integer thisName = 104; // send thisName to db
|
||||
integer Play = 105; // play channel to make an animation run
|
||||
|
||||
Debug( string msg)
|
||||
{
|
||||
if (debug) llOwnerSay(msg);
|
||||
}
|
||||
|
||||
// clear any old listeners and make a new on to control lag
|
||||
NewListen()
|
||||
{
|
||||
iDialogChannel = (integer) (llFrand(400) + 300);
|
||||
llListenRemove(iListenerHandle);
|
||||
iListenerHandle = llListen(iDialogChannel,"","","");
|
||||
}
|
||||
|
||||
// prompt the user for an animation name. Uses text box or chat
|
||||
AskForName()
|
||||
{
|
||||
iWantNameFlag = TRUE;
|
||||
llSetTimerEvent(60);
|
||||
NewListen();
|
||||
llOwnerSay("Enter the name in the text box or type the new animation name on channel /" + (string) iDialogChannel );
|
||||
llTextBox(llGetOwner(),"Type the new animation name",iDialogChannel);
|
||||
}
|
||||
|
||||
|
||||
Get(string data)
|
||||
{
|
||||
Debug("Data was " + data);
|
||||
|
||||
list lLine = (llParseString2List(data, ["|"], []));
|
||||
string sAniName = llList2String(lLine,0);
|
||||
string sNum = (string) Getline(lLine,1);
|
||||
float fNum = (float) sNum;
|
||||
vector vPos = (vector) Getline(lLine,2); // global for calcChild()
|
||||
rotation rRot = (rotation) Getline(lLine,3); // global for calcChild()
|
||||
vector vprimSize = (vector) Getline(lLine,4);
|
||||
countLoaded++;
|
||||
// the first record is always the root prim size
|
||||
if (fNum == 0)
|
||||
{
|
||||
FetchNext();
|
||||
return;
|
||||
}
|
||||
|
||||
if (sAniName != sPriorAniName)
|
||||
{
|
||||
sPriorAniName = sAniName;
|
||||
sCurrentAnimationName = sAniName;
|
||||
if (llListFindList(lUserAnimNames,[sAniName]) == -1)
|
||||
{
|
||||
Debug("Loading animation " + sAniName);
|
||||
lUserAnimNames += sAniName;
|
||||
}
|
||||
|
||||
}
|
||||
// Debug("Loading Prim #" + (string) fNum);
|
||||
if(fNum != 1) // skip root prim
|
||||
{
|
||||
sCurrentAnimationName = sAniName;
|
||||
llMessageLinked(LINK_THIS,Add,sAniName
|
||||
+"|"
|
||||
+ (string) fNum
|
||||
+"|"
|
||||
+ (string) vPos
|
||||
+ "|"
|
||||
+ (string) rRot
|
||||
+ "|"
|
||||
+ (string) vprimSize,"");
|
||||
|
||||
|
||||
|
||||
llSetText("Initialising... \n" + (string) (countLoaded) , <1,1,1>, 1.0);
|
||||
}
|
||||
llSleep(1); // http throttle avoidance
|
||||
|
||||
FetchNext();
|
||||
|
||||
}
|
||||
// in case of hand editing, we wupe out extra stuff at end
|
||||
string Getline(list Input, integer line)
|
||||
{
|
||||
return llStringTrim(llList2String(Input, line),STRING_TRIM);
|
||||
}
|
||||
|
||||
Record()
|
||||
{
|
||||
if (llStringLength(sCurrentAnimationName) > 0)
|
||||
{
|
||||
integer ifoundmovement = 0; // will be set if any child moved
|
||||
integer iPrimCounter ; // skip past the root prim
|
||||
for (iPrimCounter =2; iPrimCounter <= iPrimCount ; iPrimCounter++ )
|
||||
{
|
||||
list my_list = llGetLinkPrimitiveParams(iPrimCounter,[PRIM_POSITION,PRIM_ROTATION, PRIM_SIZE ]);
|
||||
|
||||
// position is always in region coordinates, even if the prim is a child or the root prim of an attachment.
|
||||
// rot is always the global rotation, even if the prim is a child or the root prim of an attachment.
|
||||
// get current prim pos, rot and size
|
||||
|
||||
vector vrealPrimPos = llList2Vector (my_list,0) - llGetPos(); // position subtract Global Pos
|
||||
vrealPrimPos /= llGetRot();
|
||||
rotation rrealPrimRot = llList2Rot (my_list,1) / llGetRot(); // rotation subtract Global Rot
|
||||
vector vrealPrimSize = llList2Vector (my_list,2); // size
|
||||
|
||||
// compare it to the last one we had, stride of list is a 4, and it is already sorted
|
||||
integer iindex = (iPrimCounter - 2) * iLastSTRIDE; // zeroth position is fPrimCounter - start, or 2
|
||||
|
||||
// get the last thing we remembered about this prim
|
||||
integer iprimNum = llList2Integer (lLastPrimList, iindex); // must be 0,1,2, in order
|
||||
vector vlastPrimPos = llList2Vector (lLastPrimList, iindex+1);
|
||||
rotation rlastPrimRot = llList2Rot (lLastPrimList, iindex+2);
|
||||
vector vlastPrimSize = llList2Vector (lLastPrimList, iindex+3);
|
||||
|
||||
// if anything changed on this prim, we must record it.
|
||||
if (vlastPrimPos != vrealPrimPos ||
|
||||
rlastPrimRot != rrealPrimRot ||
|
||||
vlastPrimSize!= vrealPrimSize
|
||||
)
|
||||
{
|
||||
ifoundmovement++;
|
||||
|
||||
//Save them in the master list of all animations
|
||||
llMessageLinked(LINK_THIS,Add,sCurrentAnimationName+ "|"
|
||||
+ (string) iPrimCounter
|
||||
+ "|"
|
||||
+ (string) vrealPrimPos
|
||||
+ "|"
|
||||
+ (string) rrealPrimRot
|
||||
+ "|"
|
||||
+ (string) vrealPrimSize,"");
|
||||
|
||||
|
||||
imax = llGetListLength(lLastPrimList);
|
||||
// save the changes in the last prim list so we can keep our lists smaller
|
||||
|
||||
lLastPrimList = llListReplaceList(lLastPrimList,[vrealPrimPos],iPrimCounter+1,iPrimCounter+1);
|
||||
lLastPrimList = llListReplaceList(lLastPrimList,[rrealPrimRot],iPrimCounter+2,iPrimCounter+2);
|
||||
lLastPrimList = llListReplaceList(lLastPrimList,[vrealPrimSize],iPrimCounter+3,iPrimCounter+3);
|
||||
//Debug("Saved in history at prim # " + (string) (iPrimCounter));
|
||||
llSleep(0.1);
|
||||
} // if
|
||||
else
|
||||
{
|
||||
Debug("Same @" + (string) iPrimCounter);
|
||||
}
|
||||
|
||||
} // for
|
||||
|
||||
if (!ifoundmovement)
|
||||
{
|
||||
llOwnerSay("You must move at least one child prim.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
AskForName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// on reset, record the base position in history so we can see changes
|
||||
|
||||
ClearRAM()
|
||||
{
|
||||
|
||||
iPrimCount = llGetNumberOfPrims(); // how many we are recording
|
||||
Debug("Prim Count = " + (string) iPrimCount);
|
||||
|
||||
sCurrentAnimationName = ""; // no name in use
|
||||
|
||||
lLastPrimList = []; // wipe last animations list
|
||||
integer iPrimCounter ;
|
||||
integer primCounter = 0;
|
||||
for (iPrimCounter=2; iPrimCounter <= iPrimCount ; iPrimCounter++ ) // skip 1, which is the root prim
|
||||
{
|
||||
list my_list = llGetLinkPrimitiveParams(iPrimCounter,[PRIM_POSITION, PRIM_ROTATION, PRIM_SIZE ]);
|
||||
|
||||
// save the local pos and rot, since llGetLinkPrimitiveParams returns global pos and rot
|
||||
vector primpos = llList2Vector (my_list,0) - llGetPos();
|
||||
primpos /= llGetRot();
|
||||
rotation primrot = llList2Rot (my_list,1) / llGetRot();
|
||||
|
||||
vector primsize = llList2Vector (my_list,2) ;
|
||||
lLastPrimList += iPrimCounter;
|
||||
lLastPrimList += primpos;
|
||||
lLastPrimList += primrot;
|
||||
lLastPrimList += primsize;
|
||||
primCounter++;
|
||||
}
|
||||
llOwnerSay("RAM is cleared - Initial Settings saved for " + (string) primCounter + " child prims");
|
||||
}
|
||||
|
||||
|
||||
rotation calcChildRot(rotation rdeltaRot)
|
||||
{
|
||||
if (llGetAttached())
|
||||
return rdeltaRot/llGetLocalRot();
|
||||
else
|
||||
return rdeltaRot/llGetRootRotation();
|
||||
}
|
||||
|
||||
|
||||
MakeMenu()
|
||||
{
|
||||
if (runtime)
|
||||
{
|
||||
MakeMenu2();
|
||||
return;
|
||||
}
|
||||
|
||||
list amenu = ["Name", "Record","Pause"] +
|
||||
["Erase","Load","Publish"] +
|
||||
["Recordings","-","Play All"] +
|
||||
["Help","-", "Finish"];
|
||||
|
||||
string menuText = "Available Memory: " + (string) llGetFreeMemory() +
|
||||
"\n\n" +
|
||||
"Recordings: Select a named animation\n" +
|
||||
"Name: Set the animation name\n" +
|
||||
"Play All: Play all animations\n" +
|
||||
"Erase: Delete Recorded Data\n" +
|
||||
"Load: Get from Server\n" +
|
||||
"Publish: Save to Server\n" +
|
||||
"Record: Record a snapshot of prim positions\n" +
|
||||
"Pause: Insert 0.1 second pause\n" +
|
||||
"Finish: End all programming\n" +
|
||||
"Help: Help";
|
||||
|
||||
NewListen();
|
||||
llDialog(llGetOwner(), menuText,amenu,iDialogChannel);
|
||||
|
||||
}
|
||||
|
||||
MakeMenu2()
|
||||
{
|
||||
string menuText ;
|
||||
list menu2 = lUserAnimNames;
|
||||
menu2 = llDeleteSubList(menu2,11,999); // 12 max
|
||||
|
||||
if (runtime)
|
||||
menu2 += "Unlock";
|
||||
if (llGetListLength(lUserAnimNames) == 0)
|
||||
{
|
||||
menu2 += ["Back"] ;
|
||||
menuText = " There are no animation names to display\n\n" +
|
||||
"Back:- Go back to programming menu";
|
||||
}
|
||||
else
|
||||
menuText = "Pick an animation to play.";
|
||||
|
||||
NewListen();
|
||||
llDialog(llGetOwner(), menuText,menu2,iDialogChannel);
|
||||
}
|
||||
|
||||
|
||||
FetchNext()
|
||||
{
|
||||
string url = "http://www.outworldz.com/cgi/animate.plx?Type=Load&Count=" + (string) countLoaded + "&Name=" + llEscapeURL(MyName) + "&Password=" + llEscapeURL(MyItemName);
|
||||
Debug(url);
|
||||
|
||||
kHttpRequestID = llHTTPRequest(url, [], "");
|
||||
}
|
||||
|
||||
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
MyName = llGetCreator(); // assign the creator if we get reset
|
||||
MyItemName = llGetObjectDesc(); // and get the name of the Object
|
||||
llOwnerSay("Animation name from the description is " + MyItemName);
|
||||
|
||||
if (MyItemName == "(No Description)" || llStringLength(MyItemName) == 0)
|
||||
{
|
||||
MyItemName = "Archipelis_" + (string) (llCeil(llFrand(200000) + 5000000)); // pick a large random number for a name
|
||||
llOwnerSay("Animations will be saved as '" + MyItemName + "'");
|
||||
llSetObjectDesc(MyItemName);
|
||||
}
|
||||
|
||||
|
||||
llMessageLinked(LINK_THIS,Name,MyName,"");
|
||||
llMessageLinked(LINK_THIS,thisName,MyItemName,"");
|
||||
|
||||
if (runtime)
|
||||
{
|
||||
ClearRAM();
|
||||
FetchNext(); // start with first line in DB
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearRAM();
|
||||
}
|
||||
}
|
||||
|
||||
http_response(key queryid, integer status, list metadata, string data)
|
||||
{
|
||||
if (queryid == kHttpRequestID )
|
||||
{
|
||||
if (status == 200) // HTTP success status
|
||||
{
|
||||
if (data == "nothing to do")
|
||||
{
|
||||
llOwnerSay("Initialized with " + (string) countLoaded + " settings");
|
||||
llSetText("" , <1,1,1>, 1.0);
|
||||
return;
|
||||
}
|
||||
Get(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
llOwnerSay("Server Error loading animations");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
touch_start(integer total_number)
|
||||
{
|
||||
if (llDetectedKey(0) == llGetOwner() )
|
||||
{
|
||||
MakeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
// timed out waitig for a name of an animation
|
||||
timer()
|
||||
{
|
||||
iWantNameFlag = FALSE;
|
||||
llSetTimerEvent(0);
|
||||
llOwnerSay(" Timeout waiting for animation name");
|
||||
llListenRemove(iListenerHandle);
|
||||
}
|
||||
|
||||
listen( integer channel, string name, key id, string message )
|
||||
{
|
||||
llListenRemove(iListenerHandle);
|
||||
// Debug(message);
|
||||
|
||||
if (message == "Finish")
|
||||
{
|
||||
runtime++;
|
||||
llOwnerSay("The animator is now locked. Further touches will bring up a list of animations. You must unlock the menu to add more animations");
|
||||
}
|
||||
else if (message == "Unlock")
|
||||
{
|
||||
runtime = 0;
|
||||
llOwnerSay("The animator is now unlocked for programming.");
|
||||
}
|
||||
|
||||
else if (message == "Erase")
|
||||
{
|
||||
ClearRAM();
|
||||
llMessageLinked(LINK_THIS,Erase,"",""); // erase the db
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message =="Pause")
|
||||
{
|
||||
llMessageLinked(LINK_THIS,Add,"sCurrentAnimationName|"
|
||||
+ "-0.1" // sleep 1 tenth a second
|
||||
+ "|"
|
||||
+ "<0,0,0>" // null pos
|
||||
+ "<0,0,0,1>" // null rot
|
||||
+ "|"
|
||||
+ "<0,0,0>",""); // null size
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Recordings")
|
||||
{
|
||||
MakeMenu2();
|
||||
}
|
||||
else if (message == "Load")
|
||||
{
|
||||
countLoaded = 0;
|
||||
FetchNext(); // start with first line in DB
|
||||
}
|
||||
else if (message == "Record")
|
||||
{
|
||||
Record();
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Publish")
|
||||
{
|
||||
llMessageLinked(LINK_THIS,Name,MyName,""); // in case we reset just the stores
|
||||
llMessageLinked(LINK_THIS,thisName,MyItemName,"");
|
||||
llMessageLinked(LINK_THIS,Publish,"","");
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Name")
|
||||
{
|
||||
AskForName();
|
||||
}
|
||||
else if (message == "Back")
|
||||
{
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "More")
|
||||
{
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Play All")
|
||||
{
|
||||
integer l = llGetListLength(lUserAnimNames);
|
||||
if (l == 0)
|
||||
llOwnerSay("Nothing to do");
|
||||
else
|
||||
{
|
||||
integer i = 0;
|
||||
for ( i = 0; i < l; i++)
|
||||
{
|
||||
string ani = llList2String(lUserAnimNames,i);
|
||||
llMessageLinked(LINK_THIS,Play,ani,"");
|
||||
llSleep(1);
|
||||
}
|
||||
}
|
||||
MakeMenu();
|
||||
|
||||
}
|
||||
else if (message == "Help")
|
||||
{
|
||||
llLoadURL(llGetOwner(),"View online help", "http://www.outworldz.com/secondlife/Posts/Prim-Animator-DB");
|
||||
}
|
||||
else if (iWantNameFlag)
|
||||
{
|
||||
sCurrentAnimationName = message;
|
||||
if (llGetListLength(lUserAnimNames) < 11)
|
||||
{
|
||||
if (llListFindList(lUserAnimNames,[sCurrentAnimationName]) == -1)
|
||||
lUserAnimNames += message;
|
||||
}
|
||||
else
|
||||
{
|
||||
lUserAnimNames = llDeleteSubList(lUserAnimNames,11,99);
|
||||
}
|
||||
|
||||
MakeMenu();
|
||||
|
||||
llOwnerSay("Ready to record animation '" + sCurrentAnimationName + "'");
|
||||
llOwnerSay("Position all child prims, then select the Menu item 'Record', and repeat as necessary. When finished, click 'Recordings' to play back the animation. Click 'Name' again to start a new animation sequence.");
|
||||
|
||||
iWantNameFlag = 0;
|
||||
llSetTimerEvent(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (llListFindList(lUserAnimNames,[message]) != -1)
|
||||
{
|
||||
Debug("playback animation " + message);
|
||||
llMessageLinked(LINK_THIS,Play,message,"");
|
||||
MakeMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
link_message(integer sender_num, integer num, string message, key id)
|
||||
{
|
||||
if (num == countchannel)
|
||||
{
|
||||
llSetText("Loaded " + message,<1,1,1>,1.0);
|
||||
}
|
||||
else if (num == iPlayChannel) // external messages come in channel 1 - change them to channel Play
|
||||
{
|
||||
Debug("playback animation " + message);
|
||||
llMessageLinked(LINK_THIS,Play,message,"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
ਊ
|
||||
Binary file not shown.
@@ -0,0 +1,332 @@
|
||||
// :CATEGORY:Prim Animator
|
||||
// :NAME:Archipelis scripts for prim animator
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :CREATED:2013-09-06
|
||||
// :EDITED:2013-09-18 15:38:48
|
||||
// :ID:52
|
||||
// :NUM:73
|
||||
// :REV:2
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// Prim storage Script
|
||||
// Should be named Store 0, Store 1 Stor32 etc.
|
||||
// As you need more storage, just copy it and increment the number
|
||||
// :CODE:
|
||||
|
||||
// Prim Animator DB
|
||||
// 06/20/2011
|
||||
// Author Ferd Frederix
|
||||
|
||||
// Prim Storage script.
|
||||
// Copyright 2011 Fred Beckhusen - all rights reserved
|
||||
|
||||
|
||||
integer debug =FALSE;
|
||||
// return codes
|
||||
integer playchannel = 2000; // the script to do the actual playback
|
||||
integer countchannel= 2001; // the script to do the actual playback
|
||||
|
||||
// constants
|
||||
integer MAX = 999; // Maximum number of anims per script, if set to very high, oit clamps with free memory < 1000
|
||||
integer full = FALSE; // this script RAM is full
|
||||
|
||||
|
||||
// Commands
|
||||
integer Erase = 100; // erase command
|
||||
integer Add = 101; // add a coordinate
|
||||
integer Publish = 102; // save to db
|
||||
integer Name = 103; // send Name to db
|
||||
integer Password = 104; // send Password to db
|
||||
integer Play = 105; //
|
||||
|
||||
// vars
|
||||
integer myNum = 0; // the number at the end of this script name 0, 1, 2....
|
||||
integer imax; // total records in store
|
||||
integer datum; // the load counter increments as we load anims from db
|
||||
string MyName;
|
||||
string MyPassword;
|
||||
|
||||
|
||||
// remote db reading
|
||||
key kHttpRequestID;
|
||||
|
||||
// lists
|
||||
list names; // a list of distnct animation names stored here
|
||||
list db; // name, prin num, pos, rot, size
|
||||
integer STRIDE = 5; // 4 items in the above list
|
||||
integer recordcount = 0; // how many anims are stored
|
||||
|
||||
|
||||
vector vRootScale ; // the initial size when the prims were recorded
|
||||
vector vScaleChange = <1,1,1>; // The change percent if resized
|
||||
|
||||
GetScale(vector orig_size)
|
||||
{
|
||||
//Debug ("Size:" + (string) orig_size);
|
||||
vRootScale = orig_size; // save the size when we recorded the prims
|
||||
vector newScale = llGetScale();
|
||||
vScaleChange.x = newScale.x / vRootScale.x;
|
||||
vScaleChange.y = newScale.y / vRootScale.y;
|
||||
vScaleChange.z = newScale.z / vRootScale.z;
|
||||
|
||||
}
|
||||
|
||||
|
||||
rotation calcChildRot(rotation rdeltaRot)
|
||||
{
|
||||
if (llGetAttached())
|
||||
return rdeltaRot/llGetLocalRot();
|
||||
else
|
||||
return rdeltaRot/llGetRootRotation();
|
||||
}
|
||||
// Start saving records. The first record is the prim size.
|
||||
|
||||
StartPublishing ()
|
||||
{
|
||||
imax = llGetListLength(db);
|
||||
datum = 0; // point to the first record, counts as we load records
|
||||
integer howmany = imax / STRIDE ;
|
||||
llOwnerSay((string) howmany + " movements recorded - now saving to server.");
|
||||
string url;
|
||||
|
||||
// cannot save or delete unless we are the first prim to Publish
|
||||
string save;
|
||||
string erase = "0";
|
||||
if (myNum == 0) {
|
||||
erase = "1";
|
||||
save = "Save";
|
||||
}
|
||||
|
||||
//Debug( "Saving Size:" + (string) llGetScale());
|
||||
url = "http://secondlife.mitsi.com/cgi/animate.plx?Type=";
|
||||
url += save;
|
||||
url += "&Name=" + llEscapeURL(MyName) + "&Password=" + llEscapeURL(MyPassword);
|
||||
url += "&Delete=";
|
||||
url += erase;
|
||||
url += "&aniName=RootPosition" ;
|
||||
url += "&PrimNum=" + (string) 0;
|
||||
url += "&Size=" + (string) llGetScale(); // save the scale as the first record
|
||||
url += "&Pos=<1,1,1>" ;
|
||||
url += "&Rot=<0,0,0,1>" ;
|
||||
|
||||
Debug(url);
|
||||
kHttpRequestID = llHTTPRequest(url, [], "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Put()
|
||||
{
|
||||
if (datum < imax)
|
||||
{
|
||||
string sAniName = llList2String (db, datum);
|
||||
float fprimNum = llList2Float (db, datum+1);
|
||||
vector vprimPos = llList2Vector (db, datum+2);
|
||||
rotation rprimRot = llList2Rot (db, datum+3) ;
|
||||
vector vprimSize = llList2Vector (db, datum+4);
|
||||
|
||||
string url = "http://secondlife.mitsi.com/cgi/animate.plx?Type=Save&Name=" + llEscapeURL(MyName) + "&Password=" + llEscapeURL(MyPassword);
|
||||
url += "&aniName=" + llEscapeURL(sAniName);
|
||||
url += "&PrimNum=" + (string) fprimNum;
|
||||
url += "&Pos=" + (string) vprimPos;
|
||||
url += "&Rot=" + (string) rprimRot;
|
||||
url += "&Size=" + (string) vprimSize;
|
||||
|
||||
Debug(url);
|
||||
if ((datum/STRIDE) % 10 == 0 && datum)
|
||||
llMessageLinked(LINK_THIS,countchannel,"Saved " + (string) (datum/STRIDE) + " records","");
|
||||
|
||||
|
||||
kHttpRequestID = llHTTPRequest(url, [], "");
|
||||
llSleep(1);
|
||||
datum += STRIDE;
|
||||
}
|
||||
else
|
||||
{
|
||||
llMessageLinked(LINK_THIS,countchannel,(string) (datum/STRIDE) + " movements saved.","");
|
||||
llSleep(2.0);
|
||||
llMessageLinked(LINK_THIS,countchannel,"","");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Debug(string msg)
|
||||
{
|
||||
if (debug)
|
||||
llOwnerSay(llGetScriptName() + ":" + msg);
|
||||
}
|
||||
|
||||
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
string name = llGetScriptName();
|
||||
list parts = llParseString2List(name,[" "],[""]);
|
||||
myNum = llList2Integer(parts,1);
|
||||
|
||||
vRootScale = llGetScale();
|
||||
Add += 10 * myNum;
|
||||
}
|
||||
|
||||
link_message(integer sender_num, integer num, string msg, key id)
|
||||
{
|
||||
|
||||
Debug("cmd:" + (string) num + ":" + msg);
|
||||
|
||||
// valid commands only.
|
||||
if (num != Erase && num != Play && num != Add && num != Publish && num != Name && num!= Password)
|
||||
return;
|
||||
|
||||
Debug("cmd:" + (string) num + ":" + msg);
|
||||
|
||||
|
||||
if (num == Erase)
|
||||
{
|
||||
db = [];
|
||||
Debug((string) myNum + " erased " );
|
||||
full = FALSE;
|
||||
recordcount = 0;
|
||||
return;
|
||||
}
|
||||
else if (num == Add)
|
||||
{
|
||||
if (full)
|
||||
{
|
||||
Debug((string) myNum + " pass Add on to " + (string) (num +10));
|
||||
llMessageLinked(LINK_THIS,num +10,msg,id);
|
||||
return;
|
||||
}
|
||||
|
||||
//Debug("Add");
|
||||
list vecs = llParseString2List(msg,["|"],[""]);
|
||||
|
||||
// Debug(llDumpList2String(vecs,"---"));
|
||||
string name= llList2String(vecs,0);
|
||||
if (llListFindList(names,[name]) == -1)
|
||||
names += name;
|
||||
|
||||
float fNum = (float) (llList2String(vecs,1));
|
||||
vector vPos = (vector) (llList2String(vecs,2));
|
||||
rotation rRot = (rotation) (llList2String(vecs,3));
|
||||
vector vprimSize = (vector) (llList2String(vecs,4));
|
||||
|
||||
db += name;
|
||||
db += fNum;
|
||||
db += vPos;
|
||||
db += rRot;
|
||||
db += vprimSize;
|
||||
|
||||
recordcount ++;
|
||||
Debug("Store contains " + (string) recordcount + "Records");
|
||||
//if (recordcount> MAX)
|
||||
//{
|
||||
// Debug("Full, record count = " + (string) recordcount);
|
||||
// full++;
|
||||
//}
|
||||
if (llGetFreeMemory() < 1000)
|
||||
{
|
||||
Debug("Full");
|
||||
full++;
|
||||
}
|
||||
|
||||
Debug("Free:" + (string) llGetFreeMemory());
|
||||
}
|
||||
else if (num == Name)
|
||||
{
|
||||
MyName = msg;
|
||||
}
|
||||
else if (num == Password)
|
||||
{
|
||||
MyPassword = msg;
|
||||
}
|
||||
else if (num == Play)
|
||||
{
|
||||
if (llListFindList(names,[msg]) == -1)
|
||||
{
|
||||
Debug("Animation " + msg + " not found");
|
||||
return;
|
||||
}
|
||||
integer currpos;
|
||||
integer end = recordcount * STRIDE;
|
||||
// play back all we find
|
||||
for (currpos = 0; currpos < end; currpos+= STRIDE)
|
||||
{
|
||||
if ( msg == llList2String(db,currpos) )
|
||||
{
|
||||
float fPrim = (float) llList2String(db,currpos+1);
|
||||
vector vPos = (vector) llList2String(db,currpos+2);
|
||||
rotation rRot = (rotation) llList2String (db,currpos+3);
|
||||
vector vprimSize = (vector) llList2String(db,currpos+4);
|
||||
|
||||
//Debug(msg + "|" + spos + "|" + srot + "|" + sthesize);
|
||||
GetScale(vRootScale); // original prim size
|
||||
|
||||
// set the local pos and locat rot to the prims orientation and position
|
||||
rRot = calcChildRot(rRot);
|
||||
|
||||
if (fPrim < 0)
|
||||
{
|
||||
//DebugllOwnerSay("Sleeping " + (string) (fprimNum * -1));
|
||||
llSleep( fPrim * -1);
|
||||
}
|
||||
else if (fPrim > 1 ) // skip root prim
|
||||
{
|
||||
vPos.x *= vScaleChange.x;
|
||||
vprimSize.x *= vScaleChange.x;
|
||||
|
||||
vPos.y *= vScaleChange.y;
|
||||
vprimSize.y *= vScaleChange.y;
|
||||
|
||||
vPos.z *= vScaleChange.z;
|
||||
vprimSize.z *= vScaleChange.z;
|
||||
|
||||
Debug("p=" + (string) fPrim
|
||||
+ " l=" + (string) vPos
|
||||
+ " r=" + (string) rRot
|
||||
+ " s=" + (string) vprimSize);
|
||||
|
||||
llSetLinkPrimitiveParamsFast((integer) fPrim,[PRIM_POSITION,vPos,PRIM_ROTATION,rRot,PRIM_SIZE,vprimSize]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (num == Publish)
|
||||
{
|
||||
if (myNum)
|
||||
llSleep(5); // time to delete the database and save the root prim
|
||||
StartPublishing();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug("Bad command");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// use for publishing in parallel
|
||||
http_response(key queryid, integer status, list metadata, string data)
|
||||
{
|
||||
if (queryid == kHttpRequestID )
|
||||
{
|
||||
if (status == 200) // HTTP success status
|
||||
{
|
||||
Debug(data);
|
||||
if (data == "ok")
|
||||
{
|
||||
Put();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llOwnerSay("Server Error loading animations");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// :CATEGORY:Prim Animator
|
||||
// :NAME:Archipelis scripts for prim animator
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :CREATED:2013-09-06
|
||||
// :EDITED:2013-09-18 15:38:48
|
||||
// :ID:52
|
||||
// :NUM:74
|
||||
// :REV:1
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// When touched will trigger an animation named "jump"
|
||||
// :CODE:
|
||||
|
||||
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
touch_start(integer count)
|
||||
{
|
||||
llMessageLinked(LINK_SET, 1,"jump","");
|
||||
}
|
||||
}
|
||||
630
Archipelis scripts for prim animator/Archipelis/Latest/vtp.lsl
Normal file
630
Archipelis scripts for prim animator/Archipelis/Latest/vtp.lsl
Normal file
@@ -0,0 +1,630 @@
|
||||
// :CATEGORY:Prim Animator
|
||||
// :NAME:Archipelis scripts for prim animator
|
||||
// :AUTHOR:Ferd Frederix
|
||||
// :CREATED:2013-09-06
|
||||
// :EDITED:2013-09-18 15:38:48
|
||||
// :ID:52
|
||||
// :NUM:75
|
||||
// :REV:1
|
||||
// :WORLD:Second Life
|
||||
// :DESCRIPTION:
|
||||
// Prim storage renumber animation recorder
|
||||
// - Not a fully debugged useful script.
|
||||
// It tries to make each prim have a number that matches the prim animator numbers so you can add more prims.
|
||||
// :CODE:
|
||||
|
||||
|
||||
// Prim Animator DB
|
||||
// 06/20/2011
|
||||
// Author Ferd Frederix
|
||||
// Use with one or more copies of the script 'Store 0..Store 1.. Store N'
|
||||
// Copyright 2011 Fred Beckhusen aka Ferd Frederix
|
||||
//
|
||||
// Licensed under the GNU Version3 license at http://www.gnu.org/copyleft/gpl.html
|
||||
// This program and the STORE scipts it uses must be left Copy/Transfer/MOD
|
||||
// Any items that use these scripts may have more restrictive permissions.
|
||||
|
||||
// for help and how to use, see "http://meteverse.mitsi.com/secondlife/Posts/Prim-Animator-DB
|
||||
|
||||
// Prim position root script
|
||||
// Put this script in the root prim.
|
||||
// touch the prim to start recording
|
||||
|
||||
// Record - store a new set of child prim positions
|
||||
// Clear RAM - wipe out all recording in the prim. Leaves the database intact
|
||||
// Pause - insert a 0.1 second pause
|
||||
// Erase - Erases the Server data
|
||||
// Load - Loads the data from the Server
|
||||
// Publisgh - Saves the data to the database
|
||||
// Recordings - Lists all recordings ( up to 16)
|
||||
// Name - name a new recording
|
||||
// Play All Plays back all recordings with a 1 second Pause.
|
||||
|
||||
// Publish - Saves to database
|
||||
// Help - Get Web Help
|
||||
// More - TBD
|
||||
|
||||
// configurable things
|
||||
|
||||
|
||||
|
||||
|
||||
string MyName ; // The creator of the animation
|
||||
string MyItemName; // a Name just for this unique item and any copies
|
||||
|
||||
integer debug = TRUE; // if set to TRUE, debug info appears
|
||||
|
||||
// Code follows - no need to edit below this line.
|
||||
// remote db reading
|
||||
key kHttpRequestID;
|
||||
|
||||
|
||||
integer countLoaded = 0; // how many nanims have been loaded via HTTP
|
||||
|
||||
integer iPlayChannel = 1; // the playback channel, this is the channel you use in LinkMessages
|
||||
integer countchannel= 2001; // how many have been saved
|
||||
integer iDialogChannel ; // dialog boxes
|
||||
integer iPrimCount ; // total number of prims
|
||||
integer iWantNameFlag; // flag indicating we are waiting for a name to be chatted
|
||||
integer imax; // total records in store
|
||||
integer runtime = 0; // set to 1 after Recording and publishing.
|
||||
// animation store
|
||||
string sCurrentAnimationName; // The name of the animation we are playing
|
||||
string sPriorAniName; // the prior animation name so we can spot differences as we read them in
|
||||
list lLastPrimList; // storage of the last prim position we learned
|
||||
integer iLastSTRIDE = 4; // size of the last prim list
|
||||
integer iListenerHandle; // temp iListenerHandle when we are waiting for them to give us a name
|
||||
list lUserAnimNames; // animations read from the notecard added to the Menu display
|
||||
|
||||
|
||||
// Commands
|
||||
integer Clear = 99; // erase local db
|
||||
integer Erase = 100; // erase Server DB command
|
||||
integer Add = 101; // add a coordinate
|
||||
integer Publish = 102; // save to db
|
||||
integer Name = 103; // send Name to db
|
||||
integer thisName = 104; // send thisName to db
|
||||
integer Play = 105; // play channel to make an animation run
|
||||
|
||||
list NameNum; // 2 stride list of real vs virtual numbers of prims
|
||||
|
||||
Debug( string msg)
|
||||
{
|
||||
if (debug) llOwnerSay(msg);
|
||||
}
|
||||
|
||||
|
||||
integer getVirtual(integer real)
|
||||
{
|
||||
llOwnerSay("Seeking " + (string) real);
|
||||
integer i;
|
||||
integer num = llGetListLength(NameNum);
|
||||
for (i = 0 ; i < num; i += 2)
|
||||
{
|
||||
llOwnerSay("Examine " + (string) i);
|
||||
if (llList2Integer(NameNum,i) == real)
|
||||
{
|
||||
llOwnerSay("Located " + (string) real);
|
||||
return (real);
|
||||
}
|
||||
}
|
||||
|
||||
integer new = i/2 +1;
|
||||
llOwnerSay("Returning " + (string) new);
|
||||
return new;
|
||||
}
|
||||
|
||||
Renumber()
|
||||
{
|
||||
integer realPrimNum ;
|
||||
for ( realPrimNum = 2; realPrimNum < iPrimCount; realPrimNum++)
|
||||
{
|
||||
list name = llGetLinkPrimitiveParams(realPrimNum,[PRIM_DESC] );
|
||||
|
||||
integer num = (integer) llList2String(name,0);
|
||||
if (num == realPrimNum)
|
||||
{
|
||||
NameNum += num;
|
||||
NameNum += num;
|
||||
}
|
||||
else
|
||||
{
|
||||
integer newNum = getVirtual(realPrimNum); // get the next unused prim Number
|
||||
string newname = generate_index(newNum); // make 2 digits
|
||||
llSetLinkPrimitiveParamsFast(realPrimNum,[ PRIM_DESC,newname ]); // save it
|
||||
NameNum += (integer) newname; // save it in the Real to Virtual List
|
||||
NameNum += num;
|
||||
}
|
||||
}
|
||||
|
||||
llOwnerSay(llDumpList2String(NameNum,","));
|
||||
|
||||
}
|
||||
|
||||
// get a 2-digit string fiven a number
|
||||
string generate_index(integer i)
|
||||
{
|
||||
if (i < 10)
|
||||
return "0" + (string)i;
|
||||
|
||||
return (string)i;
|
||||
}
|
||||
|
||||
|
||||
// clear any old listeners and make a new on to control lag
|
||||
NewListen()
|
||||
{
|
||||
iDialogChannel = (integer) (llFrand(400) + 300);
|
||||
llListenRemove(iListenerHandle);
|
||||
iListenerHandle = llListen(iDialogChannel,"","","");
|
||||
}
|
||||
|
||||
// prompt the user for an animation name. Uses text box or chat
|
||||
AskForName()
|
||||
{
|
||||
iWantNameFlag = TRUE;
|
||||
llSetTimerEvent(60);
|
||||
NewListen();
|
||||
llOwnerSay("Enter the name in the text box or type the new animation name on channel /" + (string) iDialogChannel );
|
||||
llTextBox(llGetOwner(),"Type the new animation name",iDialogChannel);
|
||||
}
|
||||
|
||||
|
||||
Get(string data)
|
||||
{
|
||||
Debug("Data was " + data);
|
||||
|
||||
list lLine = (llParseString2List(data, ["|"], []));
|
||||
string sAniName = llList2String(lLine,0);
|
||||
string sNum = (string) Getline(lLine,1);
|
||||
float fNum = (float) sNum;
|
||||
vector vPos = (vector) Getline(lLine,2); // global for calcChild()
|
||||
rotation rRot = (rotation) Getline(lLine,3); // global for calcChild()
|
||||
vector vprimSize = (vector) Getline(lLine,4);
|
||||
countLoaded++;
|
||||
// the first record is always the root prim size
|
||||
if (fNum == 0)
|
||||
{
|
||||
FetchNext();
|
||||
return;
|
||||
}
|
||||
|
||||
if (sAniName != sPriorAniName)
|
||||
{
|
||||
sPriorAniName = sAniName;
|
||||
sCurrentAnimationName = sAniName;
|
||||
if (llListFindList(lUserAnimNames,[sAniName]) == -1)
|
||||
{
|
||||
Debug("Loading animation " + sAniName);
|
||||
lUserAnimNames += sAniName;
|
||||
}
|
||||
|
||||
}
|
||||
// Debug("Loading Prim #" + (string) fNum);
|
||||
if(fNum != 1) // skip root prim
|
||||
{
|
||||
sCurrentAnimationName = sAniName;
|
||||
llMessageLinked(LINK_THIS,Add,sAniName
|
||||
+"|"
|
||||
+ (string) fNum
|
||||
+"|"
|
||||
+ (string) vPos
|
||||
+ "|"
|
||||
+ (string) rRot
|
||||
+ "|"
|
||||
+ (string) vprimSize,"");
|
||||
|
||||
|
||||
|
||||
llSetText("Initialising... \n" + (string) (countLoaded) , <1,1,1>, 1.0);
|
||||
}
|
||||
llSleep(1); // http throttle avoidance
|
||||
|
||||
FetchNext();
|
||||
|
||||
}
|
||||
// in case of hand editing, we wupe out extra stuff at end
|
||||
string Getline(list Input, integer line)
|
||||
{
|
||||
return llStringTrim(llList2String(Input, line),STRING_TRIM);
|
||||
}
|
||||
|
||||
Record()
|
||||
{
|
||||
if (llStringLength(sCurrentAnimationName) > 0)
|
||||
{
|
||||
integer ifoundmovement = 0; // will be set if any child moved
|
||||
integer iPrimCounter ; // skip past the root prim
|
||||
for (iPrimCounter =2; iPrimCounter <= iPrimCount ; iPrimCounter++ )
|
||||
{
|
||||
list my_list = llGetLinkPrimitiveParams(iPrimCounter,[PRIM_POSITION,PRIM_ROTATION, PRIM_SIZE ]);
|
||||
|
||||
// position is always in region coordinates, even if the prim is a child or the root prim of an attachment.
|
||||
// rot is always the global rotation, even if the prim is a child or the root prim of an attachment.
|
||||
// get current prim pos, rot and size
|
||||
|
||||
vector vrealPrimPos = llList2Vector (my_list,0) - llGetPos(); // position subtract Global Pos
|
||||
vrealPrimPos /= llGetRot();
|
||||
rotation rrealPrimRot = llList2Rot (my_list,1) / llGetRot(); // rotation subtract Global Rot
|
||||
vector vrealPrimSize = llList2Vector (my_list,2); // size
|
||||
|
||||
// compare it to the last one we had, stride of list is a 4, and it is already sorted
|
||||
integer iindex = (iPrimCounter - 2) * iLastSTRIDE; // zeroth position is fPrimCounter - start, or 2
|
||||
|
||||
// get the last thing we remembered about this prim
|
||||
integer iprimNum = llList2Integer (lLastPrimList, iindex); // must be 0,1,2, in order
|
||||
vector vlastPrimPos = llList2Vector (lLastPrimList, iindex+1);
|
||||
rotation rlastPrimRot = llList2Rot (lLastPrimList, iindex+2);
|
||||
vector vlastPrimSize = llList2Vector (lLastPrimList, iindex+3);
|
||||
|
||||
// if anything changed on this prim, we must record it.
|
||||
if (vlastPrimPos != vrealPrimPos ||
|
||||
rlastPrimRot != rrealPrimRot ||
|
||||
vlastPrimSize!= vrealPrimSize
|
||||
)
|
||||
{
|
||||
ifoundmovement++;
|
||||
|
||||
//Save them in the master list of all animations
|
||||
llMessageLinked(LINK_THIS,Add,sCurrentAnimationName+ "|"
|
||||
+ (string) iPrimCounter
|
||||
+ "|"
|
||||
+ (string) vrealPrimPos
|
||||
+ "|"
|
||||
+ (string) rrealPrimRot
|
||||
+ "|"
|
||||
+ (string) vrealPrimSize,"");
|
||||
|
||||
|
||||
imax = llGetListLength(lLastPrimList);
|
||||
// save the changes in the last prim list so we can keep our lists smaller
|
||||
|
||||
lLastPrimList = llListReplaceList(lLastPrimList,[vrealPrimPos],iPrimCounter+1,iPrimCounter+1);
|
||||
lLastPrimList = llListReplaceList(lLastPrimList,[rrealPrimRot],iPrimCounter+2,iPrimCounter+2);
|
||||
lLastPrimList = llListReplaceList(lLastPrimList,[vrealPrimSize],iPrimCounter+3,iPrimCounter+3);
|
||||
//Debug("Saved in history at prim # " + (string) (iPrimCounter));
|
||||
llSleep(0.1);
|
||||
} // if
|
||||
else
|
||||
{
|
||||
Debug("Same @" + (string) iPrimCounter);
|
||||
}
|
||||
|
||||
} // for
|
||||
//Debug("history:" + llDumpList2String(lLastPrimList,":"));
|
||||
//Debug("master:" + llDumpList2String(lAniStore," "));
|
||||
|
||||
if (!ifoundmovement)
|
||||
{
|
||||
llOwnerSay("You must move at least one child prim.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
AskForName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// on reset, record the base position in history so we can see changes
|
||||
|
||||
ClearRAM()
|
||||
{
|
||||
|
||||
iPrimCount = llGetNumberOfPrims(); // how many we are recording
|
||||
Debug("Prim Count = " + (string) iPrimCount);
|
||||
|
||||
sCurrentAnimationName = ""; // no name in use
|
||||
|
||||
lLastPrimList = []; // wipe last animations list
|
||||
integer iPrimCounter ;
|
||||
integer primCounter = 0;
|
||||
for (iPrimCounter=2; iPrimCounter <= iPrimCount ; iPrimCounter++ ) // skip 1, which is the root prim
|
||||
{
|
||||
list my_list = llGetLinkPrimitiveParams(iPrimCounter,[PRIM_POSITION, PRIM_ROTATION, PRIM_SIZE ]);
|
||||
|
||||
// save the local pos and rot, since llGetLinkPrimitiveParams returns global pos and rot
|
||||
vector primpos = llList2Vector (my_list,0) - llGetPos();
|
||||
primpos /= llGetRot();
|
||||
rotation primrot = llList2Rot (my_list,1) / llGetRot();
|
||||
|
||||
vector primsize = llList2Vector (my_list,2) ;
|
||||
lLastPrimList += iPrimCounter;
|
||||
lLastPrimList += primpos;
|
||||
lLastPrimList += primrot;
|
||||
lLastPrimList += primsize;
|
||||
primCounter++;
|
||||
}
|
||||
llOwnerSay("RAM is cleared - Initial Settings saved for " + (string) primCounter + " child prims");
|
||||
}
|
||||
|
||||
|
||||
rotation calcChildRot(rotation rdeltaRot)
|
||||
{
|
||||
if (llGetAttached())
|
||||
return rdeltaRot/llGetLocalRot();
|
||||
else
|
||||
return rdeltaRot/llGetRootRotation();
|
||||
}
|
||||
|
||||
|
||||
MakeMenu()
|
||||
{
|
||||
if (runtime)
|
||||
{
|
||||
MakeMenu2();
|
||||
return;
|
||||
}
|
||||
|
||||
list amenu = ["Record","Clear RAM","Pause"] +
|
||||
["Erase","Load","Publish"] +
|
||||
["Recordings","Name","Play All"] +
|
||||
["Help","More", "Finish"];
|
||||
|
||||
string menuText = "Available Memory: " + (string) llGetFreeMemory() +
|
||||
"\n\n" +
|
||||
"Recordings: Select a named animation\n" +
|
||||
"Name: Set the animation name\n" +
|
||||
"Play All: Play all animations\n" +
|
||||
"Clear RAM: Erase SL memory\n"+
|
||||
"Erase: Delete Server Data\n" +
|
||||
"Load: Get from Server\n" +
|
||||
"Publish: Save to Server\n" +
|
||||
"Record: Record a snapshot of prim positions\n" +
|
||||
"Pause: Insert 0.1 second pause\n" +
|
||||
"Finish: End all programming\n" +
|
||||
"Help: Help";
|
||||
|
||||
NewListen();
|
||||
llDialog(llGetOwner(), menuText,amenu,iDialogChannel);
|
||||
|
||||
}
|
||||
|
||||
MakeMenu2()
|
||||
{
|
||||
string menuText ;
|
||||
list menu2 = lUserAnimNames;
|
||||
menu2 = llDeleteSubList(menu2,11,999); // 12 max
|
||||
|
||||
if (runtime)
|
||||
menu2 += "Unlock";
|
||||
if (llGetListLength(lUserAnimNames) == 0)
|
||||
{
|
||||
menu2 += ["Back"] ;
|
||||
menuText = " There are no animation names to display\n\n" +
|
||||
"Back:- Go back to programming menu";
|
||||
}
|
||||
else
|
||||
menuText = "Pick an animation to play.";
|
||||
|
||||
NewListen();
|
||||
llDialog(llGetOwner(), menuText,menu2,iDialogChannel);
|
||||
}
|
||||
|
||||
|
||||
FetchNext()
|
||||
{
|
||||
string url = "http://www.outworldz.com/cgi/animate.plx?Type=Load&Count=" + (string) countLoaded + "&Name=" + llEscapeURL(MyName) + "&Password=" + llEscapeURL(MyItemName);
|
||||
Debug(url);
|
||||
|
||||
kHttpRequestID = llHTTPRequest(url, [], "");
|
||||
}
|
||||
|
||||
|
||||
default
|
||||
{
|
||||
state_entry()
|
||||
{
|
||||
MyName = llGetOwner(); // assign the owner if we get reset
|
||||
MyItemName = llGetObjectDesc(); // and get the name of the Object
|
||||
llOwnerSay("Animation name from the description is " + MyItemName);
|
||||
|
||||
if (MyItemName == "(No Description)" || llStringLength(MyItemName) == 0)
|
||||
{
|
||||
MyItemName = "Archipelis_" + (string) (llCeil(llFrand(200000) + 5000000)); // pick a large random number for a name
|
||||
llOwnerSay("Animations will be saved as '" + MyItemName + "'");
|
||||
llSetObjectDesc(MyItemName);
|
||||
}
|
||||
|
||||
llMessageLinked(LINK_THIS,Name,MyName,"");
|
||||
llMessageLinked(LINK_THIS,thisName,MyItemName,"");
|
||||
|
||||
|
||||
|
||||
|
||||
if (runtime)
|
||||
{
|
||||
ClearRAM();
|
||||
FetchNext(); // start with first line in DB
|
||||
}
|
||||
else
|
||||
{
|
||||
ClearRAM();
|
||||
}
|
||||
|
||||
Renumber();
|
||||
|
||||
}
|
||||
|
||||
http_response(key queryid, integer status, list metadata, string data)
|
||||
{
|
||||
if (queryid == kHttpRequestID )
|
||||
{
|
||||
if (status == 200) // HTTP success status
|
||||
{
|
||||
if (data == "nothing to do")
|
||||
{
|
||||
llOwnerSay("Initialized with " + (string) countLoaded + " settings");
|
||||
llSetText("" , <1,1,1>, 1.0);
|
||||
return;
|
||||
}
|
||||
Get(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
llOwnerSay("Server Error loading animations");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
touch_start(integer total_number)
|
||||
{
|
||||
if (llDetectedKey(0) == llGetOwner() )
|
||||
{
|
||||
MakeMenu();
|
||||
}
|
||||
}
|
||||
|
||||
// timed out waitig for a name of an animation
|
||||
timer()
|
||||
{
|
||||
iWantNameFlag = FALSE;
|
||||
llSetTimerEvent(0);
|
||||
llOwnerSay(" Timeout waiting for animation name");
|
||||
llListenRemove(iListenerHandle);
|
||||
}
|
||||
|
||||
listen( integer channel, string name, key id, string message )
|
||||
{
|
||||
llListenRemove(iListenerHandle);
|
||||
// Debug(message);
|
||||
|
||||
if (message == "Finish")
|
||||
{
|
||||
runtime++;
|
||||
llOwnerSay("The animator is now locked. Further touches will bring up a list of animations. You must unlock the menu to add more animations");
|
||||
}
|
||||
else if (message == "Unlock")
|
||||
{
|
||||
runtime = 0;
|
||||
llOwnerSay("The animator is now unlocked for programming.");
|
||||
}
|
||||
|
||||
else if (message == "Erase")
|
||||
{
|
||||
llMessageLinked(LINK_THIS,Erase,"",""); // erase the db
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Clear RAM")
|
||||
{
|
||||
ClearRAM();
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message =="Pause")
|
||||
{
|
||||
llMessageLinked(LINK_THIS,Add,"sCurrentAnimationName|"
|
||||
+ "-0.1" // sleep 1 tenth a second
|
||||
+ "|"
|
||||
+ "<0,0,0>" // null pos
|
||||
+ "<0,0,0,1>" // null rot
|
||||
+ "|"
|
||||
+ "<0,0,0>",""); // null size
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Recordings")
|
||||
{
|
||||
MakeMenu2();
|
||||
}
|
||||
else if (message == "Load")
|
||||
{
|
||||
countLoaded = 0;
|
||||
FetchNext(); // start with first line in DB
|
||||
}
|
||||
else if (message == "Record")
|
||||
{
|
||||
Record();
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Publish")
|
||||
{
|
||||
llMessageLinked(LINK_THIS,Name,MyName,""); // in case we reset just the stores
|
||||
llMessageLinked(LINK_THIS,thisName,MyItemName,"");
|
||||
llMessageLinked(LINK_THIS,Publish,"","");
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Name")
|
||||
{
|
||||
AskForName();
|
||||
}
|
||||
else if (message == "Back")
|
||||
{
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "More")
|
||||
{
|
||||
MakeMenu();
|
||||
}
|
||||
else if (message == "Play All")
|
||||
{
|
||||
integer l = llGetListLength(lUserAnimNames);
|
||||
if (l == 0)
|
||||
llOwnerSay("Nothing to do");
|
||||
else
|
||||
{
|
||||
integer i = 0;
|
||||
for ( i = 0; i < l; i++)
|
||||
{
|
||||
string ani = llList2String(lUserAnimNames,i);
|
||||
llMessageLinked(LINK_THIS,Play,ani,"");
|
||||
llSleep(1);
|
||||
}
|
||||
}
|
||||
MakeMenu();
|
||||
|
||||
}
|
||||
else if (message == "Help")
|
||||
{
|
||||
llLoadURL(llGetOwner(),"View online help", "http://www.outworldz.com/secondlife/Posts/Prim-Animator-DB");
|
||||
}
|
||||
else if (iWantNameFlag)
|
||||
{
|
||||
sCurrentAnimationName = message;
|
||||
if (llGetListLength(lUserAnimNames) < 11)
|
||||
{
|
||||
if (llListFindList(lUserAnimNames,[sCurrentAnimationName]) == -1)
|
||||
lUserAnimNames += message;
|
||||
}
|
||||
else
|
||||
{
|
||||
lUserAnimNames = llDeleteSubList(lUserAnimNames,11,99);
|
||||
}
|
||||
|
||||
MakeMenu();
|
||||
|
||||
llOwnerSay("Ready to record animation '" + sCurrentAnimationName + "'");
|
||||
llOwnerSay("Position all child prims, then select the Menu item 'Record', and repeat as necessary. When finished, click the name to play back the animation. Click 'Name' again to start a new animation sequence.");
|
||||
|
||||
iWantNameFlag = 0;
|
||||
llSetTimerEvent(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (llListFindList(lUserAnimNames,[message]) != -1)
|
||||
{
|
||||
Debug("playback animation " + message);
|
||||
llMessageLinked(LINK_THIS,Play,message,"");
|
||||
MakeMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
link_message(integer sender_num, integer num, string message, key id)
|
||||
{
|
||||
if (num == countchannel)
|
||||
{
|
||||
llSetText("Loaded " + message,<1,1,1>,1.0);
|
||||
}
|
||||
else if (num == iPlayChannel) // external messages come in channel 1 - change them to channel Play
|
||||
{
|
||||
Debug("playback animation " + message);
|
||||
llMessageLinked(LINK_THIS,Play,message,"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user