| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630 |
- // :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,"");
- }
- }
- }
|