Animator.lsl 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. // :CATEGORY:XS Pet
  2. // :NAME:XS Pet Robot
  3. // :AUTHOR:Ferd Frederix
  4. // :KEYWORDS: Pet,XS,breed,breedable,companion,Ozimal,Meeroo,Amaretto,critter,Fennux,Pets
  5. // :CREATED:2013-09-06
  6. // :EDITED:2014-01-30 12:24:21
  7. // :ID:988
  8. // :NUM:1456
  9. // :REV:0.50
  10. // :WORLD:Second Life, OpenSim
  11. // :DESCRIPTION:
  12. // XS Pet prim animator compiler
  13. // :CODE:
  14. // Author: Ferd Frederix
  15. // This prim animator compiler is a very useful and easy to use script for Second Life and OpenSim. Setup is very simple. Just drop the two script into the object, click the object, and give your animation a name. Move all the prims around, and click Record. When done, click the Compile button. It writes fast, optimized code for you.
  16. // Downloaded from : http://www.outworldz.com/cgi/freescripts.plx?ID=1691
  17. // This program is free software; you can redistribute it and/or modify it.
  18. // Additional Licenes may apply that prevent you from selling this code
  19. // and these licenses may require you to publish any changes you make on request.
  20. //
  21. // There are literally thousands of hours of work in these scripts. Please respect
  22. // the creators wishes and Copyright law and follow their license requirements.
  23. //
  24. // License information included herein must be included in any script you give out or use.
  25. // Licenses may also be included in the script or comments by the original author, in which case
  26. // the authors license must be followed, and their licenses override any licenses outlined in this header.
  27. //
  28. // You cannot attach a license to any of these scripts to make any license more or less restrictive.
  29. //
  30. // All scripts by avatar Ferd Frederix, unless stated otherwise in the script, are licensed as Creative Commons By Attribution and Non-Commercial.
  31. // Commercial use is NOT allowed - no resale of my scripts in any form.
  32. // This means you cannot sell my scripts but you can give them away if they are FREE.
  33. // Scripts by Ferd Frederix may be sold when included in a new object that actually uses these scripts. Putting my script in a prim and selling it on marketplace does not constitute a build.
  34. // For any reuse or distribution, you must make clear to others the license terms of my works. This is done by leaving headers intact.
  35. // See http://creativecommons.org/licenses/by-nc/3.0/ for more details and the actual license agreement.
  36. // You must leave any author credits and any headers intact in any script you use or publish.
  37. ///////////////////////////////////////////////////////////////////////////////////////////////////
  38. // If you don't like these restrictions and licenses, then don't use these scripts.
  39. //////////////////////// ORIGINAL AUTHORS CODE BEGINS ////////////////////////////////////////////
  40. // For more details on how this script works, see <a href="http://www.outworldz.com/secondlife/posts/prim-compiler/">http://www.outworldz.com/secondlife/posts/prim-compiler/</a>
  41. //
  42. //This is the Animator menu system. You will also need to the compiler script. You can adjust the script for OpenSim or Second Life with one variable set to TRUE or FALSE for memory checking.
  43. // ______ _ ______ _ _
  44. // | ___| | | | ___| | | (_)
  45. // | |_ ___ _ __ __| | | |_ _ __ ___ __| | ___ _ __ ___ __
  46. // | _/ _ \ '__/ _` | | _| '__/ _ \/ _` |/ _ \ '__| \ \/ /
  47. // | || __/ | | (_| | | | | | | __/ (_| | __/ | | |> <
  48. // \_| \___|_| \__,_| \_| |_| \___|\__,_|\___|_| |_/_/\_\
  49. //
  50. // fred@mitsi.com
  51. // 2-19-2012
  52. // Animator front-end for Compiler Script
  53. // This is free software, it is not for sale at any price
  54. integer playchannel = 1; // the playback channel, this is the channel you use in LinkMessages
  55. integer debug = FALSE; // if set to TRUE, debug info appears
  56. integer dialogchannel ; // dialog boxes
  57. integer nPrims; // total number of prims
  58. integer wantname; // flag indicating we are waiting for a name to be chatted
  59. integer wantnum; // flag asking for numbers to be chatted.
  60. // Link messages
  61. integer CLEAR = -234756;
  62. integer DATA = -234757;
  63. integer COMPILE = -234758;
  64. integer DIE = -234759;
  65. // the list of coords
  66. list masterlist; // master list of all positions
  67. list llastPrimList; // storage of the last prim position we learned
  68. string curranimation; // what we are playing
  69. integer STRIDE = 5; // size of the master list
  70. integer lastSTRIDE = 3; // size of the last prim list
  71. integer listener; // temp listener when we are waiting for them to give us a name
  72. vector InitSize; // the initial size when the prims were recorded
  73. list LoadedAnims; // animations added to the Menu display
  74. DEBUG(string msg)
  75. {
  76. if (debug) llOwnerSay("// " + msg);
  77. }
  78. Record()
  79. {
  80. if (llStringLength(curranimation) > 0)
  81. {
  82. integer foundmovement = 0; // will be set if any child moved
  83. integer PrimCounter ; // skip past the root prim
  84. for (PrimCounter =2; PrimCounter <= nPrims; PrimCounter++ )
  85. {
  86. //DEBUG("Checking Prim " + (string) PrimCounter);
  87. list my_list = llGetLinkPrimitiveParams(PrimCounter,[PRIM_POSITION,PRIM_ROTATION, PRIM_SIZE ]);
  88. // position is always in region coordinates, even if the prim is a child or the root prim of an attachment.
  89. // rot is always the global rotation, even if the prim is a child or the root prim of an attachment.
  90. // get current prim pos, rot and size
  91. vector vrealPrimPos = llList2Vector (my_list,0) - llGetPos(); // position subtract Global Pos
  92. vrealPrimPos /= llGetRot();
  93. rotation rrealPrimRot = llList2Rot (my_list,1) / llGetRot(); // rotation subtract Global Rot
  94. vector vrealPrimSize = llList2Vector (my_list,2); // size
  95. // compare it to the last one we had
  96. integer iindex = (PrimCounter - 2) * lastSTRIDE; // zeroth position is PrimCounter - start, or 2
  97. // get the last thing we remembered about this prim
  98. vector vlastPrimPos = llList2Vector (llastPrimList, iindex);
  99. rotation rlastPrimRot = llList2Rot (llastPrimList, iindex+1);
  100. vector vlastPrimSize = llList2Vector (llastPrimList, iindex+2);
  101. //if (debug)
  102. //{
  103. // vrealPrimPos = <1,2,llFrand(1)>; // make a small change for debugging in LSL Editor
  104. //}
  105. // if anything changed on this prim, we must record it.
  106. if (vlastPrimPos != vrealPrimPos ||
  107. rlastPrimRot != rrealPrimRot ||
  108. vlastPrimSize!= vrealPrimSize
  109. )
  110. {
  111. foundmovement++;
  112. //Save changes in the master list of all animations
  113. masterlist += curranimation;
  114. masterlist += (float) PrimCounter;
  115. masterlist += vrealPrimPos;
  116. masterlist += rrealPrimRot;
  117. masterlist += vrealPrimSize;
  118. string msg = curranimation + "|" + (string) PrimCounter + "|" + (string) vrealPrimPos + "|" + (string) rrealPrimRot + "|" + (string) vrealPrimSize ;
  119. llMessageLinked(LINK_ROOT,DATA,msg,"");
  120. // update the last movement list
  121. llastPrimList = llListReplaceList(llastPrimList,[vrealPrimPos],iindex,iindex);
  122. llastPrimList = llListReplaceList(llastPrimList,[rrealPrimRot],iindex+1,iindex+1);
  123. llastPrimList = llListReplaceList(llastPrimList,[vrealPrimSize],iindex+2,iindex+2);
  124. } // if
  125. else
  126. {
  127. //DEBUG( (string) PrimCounter);
  128. }
  129. } // for
  130. //DEBUG("history:" + llDumpList2String(llastPrimList,":"));
  131. if (foundmovement)
  132. {
  133. llOwnerSay("Recorded " + (string) foundmovement + " prims" );
  134. }
  135. else
  136. {
  137. llOwnerSay("You must move at least one child prim.");
  138. }
  139. }
  140. else
  141. {
  142. llOwnerSay("You must name your animation.");
  143. llOwnerSay("Type the new animation name on channel /" + (string) dialogchannel);
  144. wantname++;
  145. }
  146. }
  147. // on reset, record the base position in history so we can see changes
  148. Clear()
  149. {
  150. llMessageLinked(LINK_ROOT,CLEAR,"","");
  151. LoadedAnims = []; // wipe out Menu
  152. masterlist = []; // wipe all recordings
  153. llastPrimList = []; // wipe last animations
  154. integer PrimCounter ; // skip 1, which is the root prim
  155. integer counter = 0;
  156. // save all the current settings in memory
  157. for (PrimCounter=2; PrimCounter <= nPrims; PrimCounter++ )
  158. {
  159. list my_list = llGetLinkPrimitiveParams(PrimCounter,[PRIM_POSITION,PRIM_ROTATION, PRIM_SIZE ]);
  160. // save the local pos and rot, since llGetLinkPrimitiveParams returns global pos and rot
  161. vector primpos = llList2Vector (my_list,0) - llGetPos();
  162. primpos /= llGetRot();
  163. rotation primrot = llList2Rot (my_list,1) / llGetRot();
  164. vector primsize = llList2Vector (my_list,2) ;
  165. llastPrimList += primpos;
  166. llastPrimList += primrot;
  167. llastPrimList += primsize;
  168. counter++;
  169. }
  170. llOwnerSay("There are " + (string) counter + " animatable prims");
  171. }
  172. DumpBack ()
  173. {
  174. integer imax = llGetListLength(masterlist);
  175. integer howmany = imax / STRIDE ;
  176. llOwnerSay("Preprocessing " + (string) howmany + " movements. " );
  177. llMessageLinked(LINK_ROOT,COMPILE,"","");
  178. }
  179. rotation calcChildRot(rotation rdeltaRot)
  180. {
  181. if (llGetAttached())
  182. return rdeltaRot/llGetLocalRot();
  183. else
  184. return rdeltaRot/llGetRootRotation();
  185. }
  186. PlayBack (string name)
  187. {
  188. integer i;
  189. integer imax = llGetListLength(masterlist);
  190. integer linknum = 0;
  191. for (i = 0; i < imax; i+= STRIDE)
  192. {
  193. string saniName = llList2String(masterlist,i);
  194. vector scale = llGetScale();
  195. float delta = scale.x / InitSize.x ; // see if the root prim has grown or shrunk as a percentage
  196. if (saniName == name)
  197. {
  198. float fprimNum = llList2Float(masterlist,i+1);
  199. vector vPos = llList2Vector(masterlist,i+2);
  200. rotation rRot = llList2Rot(masterlist,i+3) ;
  201. vector vprimSize = llList2Vector(masterlist,i+4) ;
  202. vPos *= delta; // add any difference in size to it positions there
  203. vprimSize *= delta; // grow the child prim, too
  204. // support negative prim numbers as a delay
  205. if (fprimNum < 0)
  206. {
  207. // DEBUG("Sleeping " + (string) (fprimNum * -1));
  208. llSleep((float) fprimNum * -1);
  209. }
  210. else
  211. {
  212. // set the local pos and locat rot to the prims orientation and position
  213. rRot = calcChildRot(rRot);
  214. list actions = [PRIM_POSITION,vPos,PRIM_ROTATION,rRot,PRIM_SIZE,vprimSize];
  215. //DEBUG("Moving prim :" + (string) fprimNum + ":" + llDumpList2String(actions,":"));
  216. llSetLinkPrimitiveParamsFast((integer) fprimNum,actions);
  217. }
  218. }
  219. }
  220. }
  221. MakeMenu()
  222. {
  223. list amenu = ["Reset","Record","Help","Name","Compile","Pause", "Finish"] + LoadedAnims;
  224. llListenRemove(listener);
  225. listener = llListen(dialogchannel,"","","");
  226. amenu = llDeleteSubList(amenu,12,99);
  227. llDialog(llGetOwner(), "Pick a command",amenu,dialogchannel);
  228. }
  229. default
  230. {
  231. state_entry()
  232. {
  233. InitSize = llGetScale(); // save the size when we recorded the prims
  234. nPrims = llGetNumberOfPrims(); // how many we are recording
  235. llOwnerSay("Prim count = " + (string) nPrims);
  236. Clear();
  237. dialogchannel = (integer) (llFrand(100) +600);
  238. MakeMenu();
  239. }
  240. touch_start(integer total_number)
  241. {
  242. if (llDetectedKey(0) == llGetOwner())
  243. {
  244. llOwnerSay("FreeMemory="+(string)llGetFreeMemory());
  245. MakeMenu();
  246. }
  247. }
  248. listen( integer channel, string name, key id, string message )
  249. {
  250. if (message == "Finish")
  251. {
  252. llMessageLinked(LINK_ROOT,DIE,"die","");
  253. if (! debug)
  254. {
  255. llRemoveInventory(llGetScriptName());
  256. }
  257. }
  258. else if (message == "Reset")
  259. {
  260. llResetScript();
  261. }
  262. else if (wantnum)
  263. {
  264. float num = (float) message;
  265. if (num > 0.0)
  266. {
  267. num = -1 * (num /1000);
  268. masterlist += curranimation;
  269. masterlist += num;
  270. masterlist += <0,0,0>; // pos
  271. masterlist += <0,0,0,1>;// rot
  272. masterlist += <0,0,0>; // size
  273. string msg = curranimation + "|" + (string) num + "|<0,0,0>|<0,0,0,1>|<0,0,0>" ;
  274. llMessageLinked(LINK_ROOT,DATA,msg,"");
  275. }
  276. else
  277. {
  278. llOwnerSay("Please enter numbers in milliseconds. 1000=1000ms = 1 second. 500=500ms = 1/2 a second.");
  279. llOwnerSay("What is a milliHelen? A milliHelen is a face that can launch one ship!");
  280. }
  281. wantnum = FALSE;
  282. MakeMenu();
  283. }
  284. else if (message =="Pause")
  285. {
  286. wantnum= TRUE;
  287. llListenRemove(listener);
  288. listener = llListen(dialogchannel,"","","");
  289. llTextBox(llGetOwner(), "Enter a delay in milliseconds:\n1000 = 1 second\n500 = 1/2 second",dialogchannel);
  290. }
  291. else if (message == "Record")
  292. {
  293. Record();
  294. MakeMenu();
  295. }
  296. else if (message == "Name")
  297. {
  298. llOwnerSay("Enter a new name, or type the animation name on channel /" + (string) dialogchannel);
  299. wantname = TRUE;
  300. MakeMenu();
  301. llTextBox(llGetOwner(),"Enter an Animation Name",dialogchannel);
  302. }
  303. else if (message == "Compile")
  304. {
  305. DumpBack();
  306. MakeMenu();
  307. }
  308. else if (message == "Help")
  309. {
  310. llLoadURL(llGetOwner(),"View online help", "http://secondlife.mitsi.com/secondlife/Posts/Prim-Compiler");
  311. }
  312. else if (wantname)
  313. {
  314. curranimation = message;
  315. LoadedAnims += message;
  316. MakeMenu();
  317. llOwnerSay("Recording is ready for animation '" + curranimation + "'");
  318. llOwnerSay("Position any child prims, then select the menu item 'Record', and repeat as necessary. When finished, click 'Compile' to save the animation, or click the animation name to play it back. Click 'Name' to start a new animation sequence");
  319. wantname = 0;
  320. }
  321. else
  322. {
  323. if (llListFindList(LoadedAnims,[message]) != -1)
  324. {
  325. PlayBack(message);
  326. MakeMenu();
  327. }
  328. }
  329. }
  330. }