Prim_Animation_Compiler_1983.lsl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // :CATEGORY:Bird
  2. // :NAME:flamingo
  3. // :AUTHOR:Ferd Frederix
  4. // :CREATED:2013-09-06
  5. // :EDITED:2013-09-18 15:38:53
  6. // :ID:314
  7. // :NUM:419
  8. // :REV:1
  9. // :WORLD:Second Life
  10. // :DESCRIPTION:
  11. // Compiler for movement
  12. // :CODE:
  13. // 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>
  14. //
  15. //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.
  16. // ______ _ ______ _ _
  17. // | ___| | | | ___| | | (_)
  18. // | |_ ___ _ __ __| | | |_ _ __ ___ __| | ___ _ __ ___ __
  19. // | _/ _ \ '__/ _` | | _| '__/ _ \/ _` |/ _ \ '__| \ \/ /
  20. // | || __/ | | (_| | | | | | | __/ (_| | __/ | | |> <
  21. // \_| \___|_| \__,_| \_| |_| \___|\__,_|\___|_| |_/_/\_\
  22. //
  23. // fred@mitsi.com
  24. // 2-19-2012
  25. // Animator front-end for Compiler Script
  26. // This is free software, it is not for sale at any price
  27. integer playchannel = 1; // the playback channel, this is the channel you use in LinkMessages
  28. integer debug = FALSE; // if set to TRUE, debug info appears
  29. integer dialogchannel ; // dialog boxes
  30. integer nPrims; // total number of prims
  31. integer wantname; // flag indicating we are waiting for a name to be chatted
  32. integer wantnum; // flag asking for numbers to be chatted.
  33. // Link messages
  34. integer CLEAR = -234756;
  35. integer DATA = -234757;
  36. integer COMPILE = -234758;
  37. integer DIE = -234759;
  38. // the list of coords
  39. list masterlist; // master list of all positions
  40. list llastPrimList; // storage of the last prim position we learned
  41. string curranimation; // what we are playing
  42. integer STRIDE = 5; // size of the master list
  43. integer lastSTRIDE = 3; // size of the last prim list
  44. integer listener; // temp listener when we are waiting for them to give us a name
  45. vector InitSize; // the initial size when the prims were recorded
  46. list LoadedAnims; // animations added to the Menu display
  47. DEBUG(string msg)
  48. {
  49. if (debug) llOwnerSay("// " + msg);
  50. }
  51. Record()
  52. {
  53. if (llStringLength(curranimation) > 0)
  54. {
  55. integer foundmovement = 0; // will be set if any child moved
  56. integer PrimCounter ; // skip past the root prim
  57. for (PrimCounter =2; PrimCounter <= nPrims; PrimCounter++ )
  58. {
  59. //DEBUG("Checking Prim " + (string) PrimCounter);
  60. list my_list = llGetLinkPrimitiveParams(PrimCounter,[PRIM_POSITION,PRIM_ROTATION, PRIM_SIZE ]);
  61. // position is always in region coordinates, even if the prim is a child or the root prim of an attachment.
  62. // rot is always the global rotation, even if the prim is a child or the root prim of an attachment.
  63. // get current prim pos, rot and size
  64. vector vrealPrimPos = llList2Vector (my_list,0) - llGetPos(); // position subtract Global Pos
  65. vrealPrimPos /= llGetRot();
  66. rotation rrealPrimRot = llList2Rot (my_list,1) / llGetRot(); // rotation subtract Global Rot
  67. vector vrealPrimSize = llList2Vector (my_list,2); // size
  68. // compare it to the last one we had
  69. integer iindex = (PrimCounter - 2) * lastSTRIDE; // zeroth position is PrimCounter - start, or 2
  70. // get the last thing we remembered about this prim
  71. vector vlastPrimPos = llList2Vector (llastPrimList, iindex);
  72. rotation rlastPrimRot = llList2Rot (llastPrimList, iindex+1);
  73. vector vlastPrimSize = llList2Vector (llastPrimList, iindex+2);
  74. //if (debug)
  75. //{
  76. // vrealPrimPos = <1,2,llFrand(1)>; // make a small change for debugging in LSL Editor
  77. //}
  78. // if anything changed on this prim, we must record it.
  79. if (vlastPrimPos != vrealPrimPos ||
  80. rlastPrimRot != rrealPrimRot ||
  81. vlastPrimSize!= vrealPrimSize
  82. )
  83. {
  84. foundmovement++;
  85. //Save changes in the master list of all animations
  86. masterlist += curranimation;
  87. masterlist += (float) PrimCounter;
  88. masterlist += vrealPrimPos;
  89. masterlist += rrealPrimRot;
  90. masterlist += vrealPrimSize;
  91. string msg = curranimation + "|" + (string) PrimCounter + "|" + (string) vrealPrimPos + "|" + (string) rrealPrimRot + "|" + (string) vrealPrimSize ;
  92. llMessageLinked(LINK_ROOT,DATA,msg,"");
  93. // update the last movement list
  94. llastPrimList = llListReplaceList(llastPrimList,[vrealPrimPos],iindex,iindex);
  95. llastPrimList = llListReplaceList(llastPrimList,[rrealPrimRot],iindex+1,iindex+1);
  96. llastPrimList = llListReplaceList(llastPrimList,[vrealPrimSize],iindex+2,iindex+2);
  97. } // if
  98. else
  99. {
  100. //DEBUG( (string) PrimCounter);
  101. }
  102. } // for
  103. //DEBUG("history:" + llDumpList2String(llastPrimList,":"));
  104. if (foundmovement)
  105. {
  106. llOwnerSay("Recorded " + (string) foundmovement + " prims" );
  107. }
  108. else
  109. {
  110. llOwnerSay("You must move at least one child prim.");
  111. }
  112. }
  113. else
  114. {
  115. llOwnerSay("You must name your animation.");
  116. llOwnerSay("Type the new animation name on channel /" + (string) dialogchannel);
  117. wantname++;
  118. }
  119. }
  120. // on reset, record the base position in history so we can see changes
  121. Clear()
  122. {
  123. llMessageLinked(LINK_ROOT,CLEAR,"","");
  124. LoadedAnims = []; // wipe out Menu
  125. masterlist = []; // wipe all recordings
  126. llastPrimList = []; // wipe last animations
  127. integer PrimCounter ; // skip 1, which is the root prim
  128. integer counter = 0;
  129. // save all the current settings in memory
  130. for (PrimCounter=2; PrimCounter <= nPrims; PrimCounter++ )
  131. {
  132. list my_list = llGetLinkPrimitiveParams(PrimCounter,[PRIM_POSITION,PRIM_ROTATION, PRIM_SIZE ]);
  133. // save the local pos and rot, since llGetLinkPrimitiveParams returns global pos and rot
  134. vector primpos = llList2Vector (my_list,0) - llGetPos();
  135. primpos /= llGetRot();
  136. rotation primrot = llList2Rot (my_list,1) / llGetRot();
  137. vector primsize = llList2Vector (my_list,2) ;
  138. llastPrimList += primpos;
  139. llastPrimList += primrot;
  140. llastPrimList += primsize;
  141. counter++;
  142. }
  143. llOwnerSay("There are " + (string) counter + " animatable prims");
  144. }
  145. DumpBack ()
  146. {
  147. integer imax = llGetListLength(masterlist);
  148. integer howmany = imax / STRIDE ;
  149. llOwnerSay("Preprocessing " + (string) howmany + " movements. " );
  150. llMessageLinked(LINK_ROOT,COMPILE,"","");
  151. }
  152. rotation calcChildRot(rotation rdeltaRot)
  153. {
  154. if (llGetAttached())
  155. return rdeltaRot/llGetLocalRot();
  156. else
  157. return rdeltaRot/llGetRootRotation();
  158. }
  159. PlayBack (string name)
  160. {
  161. integer i;
  162. integer imax = llGetListLength(masterlist);
  163. integer linknum = 0;
  164. for (i = 0; i < imax; i+= STRIDE)
  165. {
  166. string saniName = llList2String(masterlist,i);
  167. vector scale = llGetScale();
  168. float delta = scale.x / InitSize.x ; // see if the root prim has grown or shrunk as a percentage
  169. if (saniName == name)
  170. {
  171. float fprimNum = llList2Float(masterlist,i+1);
  172. vector vPos = llList2Vector(masterlist,i+2);
  173. rotation rRot = llList2Rot(masterlist,i+3) ;
  174. vector vprimSize = llList2Vector(masterlist,i+4) ;
  175. vPos *= delta; // add any difference in size to it positions there
  176. vprimSize *= delta; // grow the child prim, too
  177. // support negative prim numbers as a delay
  178. if (fprimNum < 0)
  179. {
  180. // DEBUG("Sleeping " + (string) (fprimNum * -1));
  181. llSleep((float) fprimNum * -1);
  182. }
  183. else
  184. {
  185. // set the local pos and locat rot to the prims orientation and position
  186. rRot = calcChildRot(rRot);
  187. list actions = [PRIM_POSITION,vPos,PRIM_ROTATION,rRot,PRIM_SIZE,vprimSize];
  188. //DEBUG("Moving prim :" + (string) fprimNum + ":" + llDumpList2String(actions,":"));
  189. llSetLinkPrimitiveParamsFast((integer) fprimNum,actions);
  190. }
  191. }
  192. }
  193. }
  194. MakeMenu()
  195. {
  196. list amenu = ["Reset","Record","Help","Name","Compile","Pause", "Finish"] + LoadedAnims;
  197. llListenRemove(listener);
  198. listener = llListen(dialogchannel,"","","");
  199. amenu = llDeleteSubList(amenu,12,99);
  200. llDialog(llGetOwner(), "Pick a command",amenu,dialogchannel);
  201. }
  202. default
  203. {
  204. state_entry()
  205. {
  206. InitSize = llGetScale(); // save the size when we recorded the prims
  207. nPrims = llGetNumberOfPrims(); // how many we are recording
  208. llOwnerSay("Prim count = " + (string) nPrims);
  209. Clear();
  210. dialogchannel = (integer) (llFrand(100) +600);
  211. MakeMenu();
  212. }
  213. touch_start(integer total_number)
  214. {
  215. if (llDetectedKey(0) == llGetOwner())
  216. {
  217. llOwnerSay("FreeMemory="+(string)llGetFreeMemory());
  218. MakeMenu();
  219. }
  220. }
  221. listen( integer channel, string name, key id, string message )
  222. {
  223. if (message == "Finish")
  224. {
  225. llMessageLinked(LINK_ROOT,DIE,"die","");
  226. if (! debug)
  227. {
  228. llRemoveInventory(llGetScriptName());
  229. }
  230. }
  231. else if (message == "Reset")
  232. {
  233. llResetScript();
  234. }
  235. else if (wantnum)
  236. {
  237. float num = (float) message;
  238. if (num > 0.0)
  239. {
  240. num = -1 * (num /1000);
  241. masterlist += curranimation;
  242. masterlist += num;
  243. masterlist += <0,0,0>; // pos
  244. masterlist += <0,0,0,1>;// rot
  245. masterlist += <0,0,0>; // size
  246. string msg = curranimation + "|" + (string) num + "|<0,0,0>|<0,0,0,1>|<0,0,0>" ;
  247. llMessageLinked(LINK_ROOT,DATA,msg,"");
  248. }
  249. else
  250. {
  251. llOwnerSay("Please enter numbers in milliseconds. 1000=1000ms = 1 second. 500=500ms = 1/2 a second.");
  252. llOwnerSay("What is a milliHelen? A milliHelen is a face that can launch one ship!");
  253. }
  254. wantnum = FALSE;
  255. MakeMenu();
  256. }
  257. else if (message =="Pause")
  258. {
  259. wantnum= TRUE;
  260. llListenRemove(listener);
  261. listener = llListen(dialogchannel,"","","");
  262. llTextBox(llGetOwner(), "Enter a delay in milliseconds:\n1000 = 1 second\n500 = 1/2 second",dialogchannel);
  263. }
  264. else if (message == "Record")
  265. {
  266. Record();
  267. MakeMenu();
  268. }
  269. else if (message == "Name")
  270. {
  271. llOwnerSay("Enter a new name, or type the animation name on channel /" + (string) dialogchannel);
  272. wantname = TRUE;
  273. MakeMenu();
  274. llTextBox(llGetOwner(),"Enter an Animation Name",dialogchannel);
  275. }
  276. else if (message == "Compile")
  277. {
  278. DumpBack();
  279. MakeMenu();
  280. }
  281. else if (message == "Help")
  282. {
  283. llLoadURL(llGetOwner(),"View online help", "http://secondlife.mitsi.com/secondlife/Posts/Prim-Compiler");
  284. }
  285. else if (wantname)
  286. {
  287. curranimation = message;
  288. LoadedAnims += message;
  289. MakeMenu();
  290. llOwnerSay("Recording is ready for animation '" + curranimation + "'");
  291. 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");
  292. wantname = 0;
  293. }
  294. else
  295. {
  296. if (llListFindList(LoadedAnims,[message]) != -1)
  297. {
  298. PlayBack(message);
  299. MakeMenu();
  300. }
  301. }
  302. }
  303. }