Av-Sitter To PMAC Converter.
Contents
AV-Sitter2 to PMAC conversion script – Introduction
The Covey AV-Sitter2 to PMAC conversion script reads AV-Sitter position cards and converts them to PMAC menus. AV-Sitter uses 2 scripts per avatar and another for setting up pose positions. PMAC, written Aine Caoimhe is a single script. AV-Sitter has a few features PMAC does not support and can be used in Second Life.
About PMAC
The Paramour Multi-Animation Controller (PMAC) is a no pose ball script system. Use PMAC in almost any piece of furniture to animate multiple avatars simultaneously. PMAC reads notecards directly and uses significantly fewer resources than AV-Sitter, map or many others.
AV-Sitter2 to PMAC conversion script – Instructions
Add the conversion script to a prim containing an AV-Sitter positions notecard (AVpos). Script status is in local chat and so is a finish notice. New PMAC menu cards are in the item inventory. Next add the PMAC core script, default animation and configuration notecard.
Important – Work on a copy
Please work on a copy, this script does not convert all AV-Sitter features to PMAC
Single Menus
PMAC handles singles differently to AV-Sitter. When a singles menu is used only one sitter is enabled. To try and work around this, the script looks for singles poses with matching button names from each sitter. If found it will turn the two or more matching singles poses into a set of 2 or more that work like Av-Sitter SYNCS (Couples poses). If a name has no match, it is a single menu.entry.
Menu And Button Names
AV-Sitter can have many configurations. Animations are grouped by menu and button names. In each sitter, the Menu Name must match. When matching menu names are found, it drops down to line by line checking, only pairing matching button names.
The Script
Also available on GitHub, Fire And Ice Grid Blog and in the Fire And Ice Grid at the Covey Stores And Welcome Region.
Licence
1 BSD 3-Clause License
2 Copyright (c) 2020, Sara Payne
3 All rights reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 1. Redistributions of source code must retain the above copyright notice, this
7 list of conditions and the following disclaimer.
8 2. Redistributions in binary form must reproduce the above copyright notice,
9 this list of conditions and the following disclaimer in the documentation
10 and/or other materials provided with the distribution.
11 3. Neither the name of the copyright holder nor the names of its
12 contributors may be used to endorse or promote products derived from
13 this software without specific prior written permission.
14 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 integer menuCardNumber = 2; //used at the end when writing the new menu cards
2 string AvPosCardName = "AVpos"; //name of the Av-sitter positions card
3 integer debug = FALSE; //turns this on to see debug output, this generates a LOT of local chat output
4 //if you use the debug option it's suggested you comment them out section by sec
5
6 ConvertRotationsAndFixOffset()
7 { //AvSitter uses x,y,z rotations, PMAC uses quaternion rotations, so convert them.
8 list tempList = [];
9 integer lineNumber;
10 integer notecardLines = osGetNumberOfNotecardLines(AvPosCardName);
11 for (lineNumber = 0; lineNumber < notecardLines; lineNumber++)
12 { //loops through each line of the notecard
13 string initial = osGetNotecardLine(AvPosCardName, lineNumber);
14 string noTimes = RemoveTimes(initial);
15 integer braceIndex = llSubStringIndex(noTimes, "}");
16 string fixedRotation;
17 string fixedOffset;
18 if (braceIndex != -1)
19 { //only deal with lines wich contain a } (pos/rot line)
20 fixedRotation = ConvertLineToRotationsAndFixOffset(noTimes); //convert this line to real rotations
21 }
22 else
23 { //only deal with lines that do not contain a } (pos/rot line)
24 fixedRotation = noTimes;
25 }
26 tempList += fixedRotation; //add the line to the temp list
27 }
28 //write the temp list to a notecard
29 WriteNotecard("FixedRotations", tempList);
30 }
31
32 WriteNotecard(string name, list contents)
33 { //writes a notecard with the supplied name and contents
34 //The conversion script relies on the contents of notecards, Ensure the notecards are deleted and saved before continuing
35 integer inventoryType;
36 if (llGetInventoryType(name) == INVENTORY_NOTECARD)
37 {
38 llRemoveInventory(name);
39 inventoryType = llGetInventoryType(name);
40 while (inventoryType > -1) //-1 means it doesn't exist
41 { //wait to make sure the removal is complete before going on
42 inventoryType = llGetInventoryType(name);
43 }
44 }
45 osMakeNotecard(name, contents);
46 inventoryType = llGetInventoryType(name);
47 while (inventoryType != INVENTORY_NOTECARD)
48 { //wait for the write to finish before going on
49 inventoryType = llGetInventoryType(name);
50 }
51 }
52
53 DebugOwnerSayListContents(string name, list toDisplay)
54 { //outputs the contents of a list nicely to local chat for the owner.
55 string output = "Debug:ListContents:" + "\n" + "ListName: " + name;
56 llOwnerSay(output);
57 integer index;
58 for (index = 0; index < llGetListLength(toDisplay); index++)
59 { //loop through every line of the list outputting to local chat
60 llOwnerSay(llList2String(toDisplay, index));
61 }
62 }
63
64 list ReverseListOrder(list inputList)
65 { //reverses the order of a list.
66 list reverseList;
67 integer index;
68 for (index = llGetListLength(inputList)-1; index >= 0 ; index--)
69 { //loops through the list backwards, adding each line to a new list
70 reverseList += llList2String(inputList, index);
71 }
72 return reverseList;
73 }
74
75 string ConvertLineToRotationsAndFixOffset (string inputString)
76 { //takes in the AVpos format and outputs PMAC format
77 string name = "{"+ NameFromPositionsLine(inputString) + "}";
78 vector posVec = (vector)PosFromPositionsLine(inputString);
79 vector rotVec = (vector)RotFromPositionsLine (inputString);
80 vector fixedOffset = posVec - <0,0,0.3>;
81 rotation rotRot = llEuler2Rot(rotVec * DEG_TO_RAD); //the actual conversion
82 string fixedString = name + (string)fixedOffset + (string)rotRot;
83 return fixedString;
84 }
85
86 list GetSpecificNotecardCards (string searchString)
87 { //uses a partial name string to return all matching notecards from the items inventory
88 list sitterNotecards;
89 integer numOfNotecards = llGetInventoryNumber(INVENTORY_NOTECARD);
90 integer index;
91 for (index = 0; index < numOfNotecards; index++)
92 { //loops through every notecard in the inventory
93 string notecardName = llGetInventoryName(INVENTORY_NOTECARD, index);
94 string testName = llGetSubString(notecardName, 0, llStringLength(searchString)-1);
95 if (testName == searchString)
96 { //if we find a match add it to the list
97 sitterNotecards += notecardName;
98 }
99 }
100 return sitterNotecards;
101 }
102
103 string MenuNameFromMenuLine(string inputString)
104 {
105 integer spaceChar = llSubStringIndex(inputString, " ");//find the space character
106 string menuName = llStringTrim(llGetSubString(inputString, spaceChar +1, -1), STRING_TRIM); //remove everythign before the space
107 return menuName;
108 }
109
110 string NameFromPositionsLine(string inputString)
111 {
112 integer charBracket = llSubStringIndex(inputString, "}"); //find the } character
113 string nValue = llGetSubString(inputString, 1, charBracket-1); //remove curley brackets and position data
114 return nValue;
115 }
116
117 string PosFromPositionsLine(string inputString)
118 {
119 integer charLess = llSubStringIndex (inputString, "<"); // find the first < character
120 integer charMore = llSubStringIndex (inputString, ">"); // find the first > character
121 string vValue = llGetSubString (inputString, charLess, charMore); // removed everything except the vector
122 return vValue;
123 }
124
125 string RotFromPositionsLine (string inputString)
126 {
127 integer charMore = llSubStringIndex (inputString, ">"); // find the first > character
128 string rotValue = llGetSubString (inputString, charMore+1, -1); //remove everything except the rotation vector
129 return rotValue;
130 }
131
132 string RemoveTimes(string inputString)
133 {
134 integer charStart = llSubStringIndex(inputString, "◆");//find the position of the real start of the line and discard all before it
135 string trimed = llGetSubString(inputString, charStart+1, -1); //remove everything before the "◆"
136 return trimed;
137 }
138
139 string GetPoseName (string inputString)
140 {
141 integer charLine = llSubStringIndex(inputString,"|"); //find the | seperator character
142 string lValue = llGetSubString (inputString, 0, charLine-1); // remove everything after the |
143 return lValue;
144 }
145
146 string GetAnimName (string inputString)
147 {
148 integer charLine = llSubStringIndex(inputString, "|"); // find the | seperator
149 string lValue = llGetSubString(inputString, charLine+1, -1); //remove everythign before the |
150 return lValue;
151 }
152
153 string GetSitterNumberFromMenuCardName(string menuCardName)
154 {
155 list elements = llParseStringKeepNulls(menuCardName, "_", ""); //make a list seperated by underscores
156 string sitterNumber = llList2String(elements, 2); //retrieve the sitter number from the list
157 return sitterNumber;
158 }
159
160 string GetMenuNameFromMenuCardName(string menuCardName)
161 {
162 list elements = llParseStringKeepNulls(menuCardName, "_", "");//make a list seperated by underscores
163 string name = llList2String(elements, 3);//retrieve the name number from the list
164 return name;
165 }
166
167 string GetButtonNameFromPmacLine(string inputString)
168 {
169 integer barIndex = llSubStringIndex(inputString, "|");// find the | seperator
170 string name = llGetSubString(inputString, 0, barIndex-1); //remove everything after the |
171 return name;
172 }
173
174 SplitIntoSitters()
175 { //splits the AVpos card down into individual sitters
176 list tempSitterList;
177 integer sitterCount = -1; //start at -1 so that we don't save contents before the first SITTER line
178 integer lineNumber;
179 integer notecardLines = osGetNumberOfNotecardLines("FixedRotations");
180 for (lineNumber = 0; lineNumber < notecardLines; lineNumber++)
181 { //loop through ever line of the AVpos notecard
182 string currentLine1 = osGetNotecardLine("FixedRotations", lineNumber);
183 if (currentLine1 != "")
184 { //ignore blank lines
185 string test = llGetSubString(currentLine1, 0, 3);
186 string test2 = llGetSubString(currentLine1, 0, 0);
187 if (test == "SITT")
188 { //do something for SITTER line found
189 if (sitterCount > -1)
190 { //if we find a new SITTER line write the contents of the temp list to a notecard
191 WriteNotecard("Sitter" + (string)sitterCount, tempSitterList);
192 tempSitterList = [];//clear the list ready to start again
193 }
194 sitterCount++;
195 }
196 else if (test == "MENU" || test == "POSE" || test == "SYNC" || test2 == "{")
197 { //only deal with the menus, poses, syncs and pos/rot lines
198 tempSitterList += currentLine1; //add info to the new list
199 }
200
201 }
202 }
203 //write a notecard containing all needed information for this sitter
204 WriteNotecard("Sitter" + (string)sitterCount, tempSitterList);
205 }
206
207 list GetSitterSyncsAndMenus(string notecardName)
208 { //loops through the named notecard looking for lines which start with SYNC, MENU or { (pos/rot lines)
209 //adds them to the new list as they are found
210 list sitterSyncsAndMenus;
211 list poseNames;
212 integer lineNumber;
213 for (lineNumber = 0; lineNumber < osGetNumberOfNotecardLines(notecardName); lineNumber++)
214 { //loops through every line of the notecard
215 string currentLine2 = osGetNotecardLine(notecardName, lineNumber);
216 string testPose = llGetSubString(currentLine2, 0, 3);
217 string testAnimData = llGetSubString(currentLine2, 0, 0);
218 string testPoseName;
219 if (testPose == "SYNC")
220 { //for every SYNC line remove the word SYNC and the space, retrieve the pose name from the remainder
221 //and add the pose name to the list of pose names
222 string withoutTitle = llStringTrim(llGetSubString(currentLine2, 5, -1), STRING_TRIM);
223 sitterSyncsAndMenus += withoutTitle;
224 testPoseName = GetPoseName(withoutTitle);
225 poseNames += testPoseName;
226 }
227 else if (testPose == "MENU")
228 { //add ever Menu line to the list
229 sitterSyncsAndMenus += currentLine2;
230 }
231 else if (testAnimData == "{")
232 { //come here for every pos/rot line, check the name and if it matches
233 //add it to the list
234 integer closeBraceIndex = llSubStringIndex(currentLine2, "}");
235 string lineAnimName = llGetSubString(currentLine2, 1, closeBraceIndex-1);
236 if(~llListFindList(poseNames, (list)lineAnimName))
237 { //if the name matches any of the ones added to the pose list earlier, add the line
238 //to the main list.
239 sitterSyncsAndMenus += currentLine2;
240 }
241 }
242 }
243 return sitterSyncsAndMenus;
244 }
245
246 list GetSitterPOSEs(string notecardName)
247 { //loop through the supplied notecard name saving just pose names and related pos/rot lines
248 list sitterPoses;
249 list poseNames;
250 integer lineNumber;
251 for (lineNumber = 0; lineNumber < osGetNumberOfNotecardLines(notecardName); lineNumber++)
252 { //loops through every line in the notecard
253 string currentLine2 = osGetNotecardLine(notecardName, lineNumber);
254 string testPose = llGetSubString(currentLine2, 0, 3);
255 string testAnimData = llGetSubString(currentLine2, 0, 0);
256 string testPoseName;
257 if (testPose == "POSE")
258 { //checks each pose line, retrieves the name then adds the name to the poses list
259 string withoutTitle = llStringTrim(llGetSubString(currentLine2, 5, -1), STRING_TRIM);
260 sitterPoses += withoutTitle;
261 testPoseName = GetPoseName(withoutTitle);
262 poseNames += testPoseName;
263 }
264 else if (testAnimData == "{")
265 { //checks every pos/rot line, if the name matches one save earlier add it to the list
266 integer closeBraceIndex = llSubStringIndex(currentLine2, "}");
267 string lineAnimName = llGetSubString(currentLine2, 1, closeBraceIndex-1);
268 if(~llListFindList(poseNames, (list)lineAnimName))
269 { //if the lines name matches one in the pose list add the whole line to the main list
270 sitterPoses += currentLine2;
271 }
272 }
273 }
274 return sitterPoses;
275 }
276
277 FixAndCombineSinglePoses()
278 { //makes new notecards with the sync and poses seperated
279 //along with their related pos/rot information.
280 SeperatePoseNamesAndData();
281 CreateNewSyncSetFromPoses();
282 }
283
284 SeperatePoseNamesAndData()
285 { //loops through every sitter card making new serpate cards for poses (not syncs) and their related pos/rot
286 list sitterNotecards = GetSpecificNotecardCards("Sitter");
287 integer sitterCardIndex;
288 for(sitterCardIndex = 0; sitterCardIndex < llGetListLength(sitterNotecards); sitterCardIndex++)
289 { //loops through every sitter notecard
290 string cardName = llList2String(sitterNotecards, sitterCardIndex);
291 list sitterPoses = GetSitterPOSEs(cardName);
292 list sitterPosRotData;
293 integer lineIndex;
294 for (lineIndex = llGetListLength(sitterPoses)-1; lineIndex >=0; lineIndex--)
295 { //add all lines with braces to the sitte pos/rot list and remove from sitter poses list
296 string currentLine3 = llList2String(sitterPoses, lineIndex);
297 integer hasBraces = llSubStringIndex(currentLine3, "}");
298 if (hasBraces > -1)
299 { //takes every pos/rot line and adds it to the pos/rot line list
300 if (debug) llOwnerSay("Debug:BracesLine: " + currentLine3);
301 sitterPosRotData += currentLine3;
302 sitterPoses = llDeleteSubList(sitterPoses, lineIndex, lineIndex);
303 }
304 }
305 //write out both cards, reversing the order of the pos/rot card so it matches the order of the menu card.
306 WriteNotecard("Poses " + cardName, sitterPoses);
307 sitterPosRotData = ReverseListOrder(sitterPosRotData);
308 WriteNotecard("DataPoses " + cardName, sitterPosRotData);
309 }
310 }
311
312 GeneratePoseToSyncCards(list poseCards, list newSyncNames)
313 { //loops through all pose cards line by line, looking for names with the same button names
314 //assumes these are supposed to be paied up and makes new SYNC menus from them.
315 list newSyncPoses;
316 list newSyncData;
317 integer poseCardIndex;
318 for (poseCardIndex = 0; poseCardIndex < llGetListLength(poseCards); poseCardIndex++)
319 { //loops through each card
320 string cardName = "Poses Sitter" + (string)poseCardIndex;
321 integer cardLength = osGetNumberOfNotecardLines(cardName);
322 if(debug) llOwnerSay("Debug:ReadingCard: " + cardName);
323 integer lineIndex;
324 newSyncPoses = [];
325 newSyncData = [];
326 string menu = "MENU Social-A";
327 newSyncPoses += menu;
328 for (lineIndex = 0; lineIndex < cardLength; lineIndex++)
329 { //loops through each line in the given notecard
330 string posesLine = osGetNotecardLine("Poses Sitter" + (string)poseCardIndex, lineIndex);
331 string dataLine = osGetNotecardLine("DataPoses Sitter" + (string)poseCardIndex,lineIndex);
332 string poseName = GetPoseName (posesLine);
333 if (debug) llOwnerSay("Debug:CheckingPoseName: " + poseName);
334 if (~llListFindList(newSyncNames, (list)poseName))
335 { //come here if the current pose name is found in the new sync names list
336 if (debug) llOwnerSay("Debug:Found" + poseName);
337 string newPoseLine = "SYNC " + posesLine;
338 newSyncPoses += newPoseLine;
339 newSyncData += dataLine;
340 }
341 }
342 list combinedList = newSyncPoses + newSyncData;
343 WriteNotecard("PoseToSyncSitter" + (string)poseCardIndex, combinedList);
344 }
345 }
346
347 CreateNewSyncSetFromPoses()
348 { //loops though every pose card and attempts to find pairs which should be used together.
349 //then makes a list of real single only poses and pairs to treat as syncs, pmac singles
350 //don't allow others to sit, so better to pair them up when possible.
351 list posesCards = GetSpecificNotecardCards("Poses Sitter");
352 integer posesCardIndex;
353 list poseNamesSitter0;
354 list newSyncNames;
355 list newSinglesNames;
356 if (debug) DebugOwnerSayListContents("list of poses cards", posesCards);
357 //loop through all cards checking for duplicate pose names, store them in newSyncNames
358 for (posesCardIndex = 0; posesCardIndex < llGetListLength(posesCards); posesCardIndex++)
359 { //loops through each card, checking against sitter 0
360 integer lineIndex;
361 string notecardName = llList2String(posesCards, posesCardIndex);
362 integer notecardLength = osGetNumberOfNotecardLines(notecardName);
363 for (lineIndex = 0; lineIndex < notecardLength; lineIndex++)
364 {
365 string currnetLine = osGetNotecardLine(notecardName, lineIndex);
366 string poseName = GetPoseName (currnetLine);
367 if (posesCardIndex == 0)
368 {
369 poseNamesSitter0 += poseName;
370 }
371 else
372 {
373 if(~llListFindList(poseNamesSitter0, (list)poseName))
374 { //come here if poseName is found in sitter0
375 if (!(~llListFindList(newSyncNames, (list)poseName)))
376 { //come here only if the pose is not already in the new sync names
377 newSyncNames += poseName;
378 }
379 }
380 else
381 { //come here if the pose is not found in sitter 0
382 if (!(~llListFindList(newSinglesNames, (list)poseName)))
383 { //come here only if the pose is not already in the new sync names
384 newSinglesNames += poseName;
385 }
386 }
387 }
388 }
389 }
390 GenerateNewSinglesCard(newSyncNames);
391 GeneratePoseToSyncCards(posesCards, newSyncNames);
392 CombinePoseToSyncCardsWithSiterCards();
393 }
394
395 CombinePoseToSyncCardsWithSiterCards()
396 { //takes the new sync cards (made from pair poses) and combines
397 //these new menus with the original sitter cards ready for sync set processing
398 list sitterCards = GetSpecificNotecardCards ("Sitter");
399 integer sitterCardIndex;
400 for (sitterCardIndex = 0; sitterCardIndex < llGetListLength(sitterCards); sitterCardIndex++)
401 {
402 list newSitterCard;
403 string currentLine;
404 string CardName = "Sitter" + (string)sitterCardIndex;
405 newSitterCard += AllLinesWithOrWithoutBraces (CardName, FALSE);
406 CardName = "PoseToSyncSitter" + (string)sitterCardIndex;
407 newSitterCard += AllLinesWithOrWithoutBraces (CardName, FALSE);
408 CardName = "Sitter" + (string)sitterCardIndex;
409 newSitterCard += AllLinesWithOrWithoutBraces (CardName, TRUE);
410 CardName = "Sitter" + (string)sitterCardIndex;
411 newSitterCard += AllLinesWithOrWithoutBraces (CardName, TRUE);
412 if (debug) DebugOwnerSayListContents("New Sitter " + (string)sitterCardIndex + " card", newSitterCard);
413 WriteNotecard("Sitter" + (string)sitterCardIndex, newSitterCard);
414 }
415 }
416
417 list AllLinesWithOrWithoutBraces(string cardName, integer with)
418 { //loops through the given notecard name, if the "with" integer is TRUE
419 //adds all lines with braces to a list. If the "with" is FALSE all lines
420 //without braces are added to the list.
421 list newList;
422 integer CardLength = osGetNumberOfNotecardLines(cardName);
423 integer lineNumber;
424 //add lines without braces from the sitter card
425 for (lineNumber = 0; lineNumber < CardLength; lineNumber++)
426 { //loops through the whole notecards
427 string currentLine = osGetNotecardLine(cardName, lineNumber);
428 integer hasBraces = llSubStringIndex(currentLine, "{");
429 if(with)
430 { //we want all lines with braces
431 if (hasBraces > -1)
432 {
433 newList += currentLine;
434 }
435 }
436 else
437 { //we want all lines without braces
438 if (hasBraces == -1)
439 {
440 newList += currentLine;
441 }
442 }
443 }
444 return newList;
445 }
446
447 GenerateNewSinglesCard(list newSyncNames)
448 { //loops through all poses in all the sitter cards, checks to see if they have matching
449 //entries in the newSyncNames list, if they don't ass them to a list of real single
450 //poses and writes the note card when the list is complelete
451 if (debug) llOwnerSay("Debug:GenerateNewSinglesCard: Entered");
452 integer posesSitter0Line;
453 list posesCards = GetSpecificNotecardCards("Poses Sitter");
454 if (debug) DebugOwnerSayListContents("posesCards", posesCards);
455 if (debug) DebugOwnerSayListContents("sync names list", newSyncNames);
456 list newSinglePoses;
457 list newSinglePosesData;
458 integer posesCardIndex;
459 for (posesCardIndex = 0; posesCardIndex < llGetListLength(posesCards); posesCardIndex++)
460 { //loops through each poses card card
461 integer lineIndex;
462 string notecardName = llList2String(posesCards, posesCardIndex);
463 if (debug) llOwnerSay("Debug:CheckingCard: " + notecardName);
464 integer notecardLength = osGetNumberOfNotecardLines(notecardName);
465 for (lineIndex = 0; lineIndex < notecardLength; lineIndex++)
466 { //loops through every line of the current poses card
467 string currentLine4 = osGetNotecardLine(notecardName, lineIndex);
468 string poseName = GetPoseName (currentLine4);
469 if (debug) llOwnerSay("Debug: checking pose name: " + poseName);
470 integer matchFound = FALSE;
471 integer newSyncNamesIndex = 0;
472 //now check this line against every line of new sync names
473 while (!matchFound && newSyncNamesIndex < llGetListLength(newSyncNames))
474 { //loops through the sync poses checking for a match, keeps going until it finishes withou
475 //a result or finds a match
476 string newSyncNamesLine = llList2String(newSyncNames, newSyncNamesIndex);
477 if(debug) llOwnerSay("Debug:Checking:" + currentLine4 + " against " + newSyncNamesLine);
478 if (poseName == newSyncNamesLine)
479 { //come here if a a match has been found, stop the loop
480 if(debug) llOwnerSay("Debug:MatchFound");
481 matchFound = TRUE;
482 }
483 newSyncNamesIndex++;
484 }
485 if (!matchFound)
486 { //loop though the sync cards has ended, no match found, add this item to the singles list
487 //add the data from the same animations and button names to to another list.
488 if (debug) llOwnerSay("Debug: Not Found");
489 string newSinglePosesLine = osGetNotecardLine("Poses Sitter" + (string)posesCardIndex, lineIndex);
490 string newSinglePosesDataLine = osGetNotecardLine("DataPoses Sitter" + (string)posesCardIndex, lineIndex);
491 newSinglePoses += newSinglePosesLine;
492 newSinglePosesData += newSinglePosesDataLine;
493 }
494 }
495 }
496 if (debug)
497 {
498 DebugOwnerSayListContents("newSinglePoses", newSinglePoses);
499 DebugOwnerSayListContents("newSinglePosesData", newSinglePosesData);
500 }
501 //now turn the two new lists above into a menu card for PMAC
502 integer newSinglePosesIndex;
503 list newSinglesMenu; //list to hold the new singles menu
504 for (newSinglePosesIndex = 0; newSinglePosesIndex < llGetListLength(newSinglePoses); newSinglePosesIndex++)
505 { //loops through each of the new singles poses entries, makes the PMAC line and adds to the list ready for writing
506 string lineFromPoses = llList2String(newSinglePoses, newSinglePosesIndex);
507 string lineFromData = llList2String(newSinglePosesData, newSinglePosesIndex);
508 if (debug) llOwnerSay("Debug:LineFromPoses: " + lineFromPoses);
509 if (debug) llOwnerSay("Debug:LineFromPosesData: " + lineFromData);
510 string buttonname = GetPoseName (lineFromPoses);
511 if (debug) llOwnerSay("Debug:ButtonName: " + buttonname);
512 string animName = GetAnimName (lineFromPoses);
513 string position = PosFromPositionsLine(lineFromData);
514 string rot = RotFromPositionsLine (lineFromData); //this is already a rotation just reusing a method.
515 string newEntry = buttonname + "|NO COM|" + animName + "|" + position + "|" + rot;
516 if(debug) llOwnerSay("Debug:AddedToSingleMenu: " + newEntry);
517 newSinglesMenu += newEntry;
518 }
519 if (debug) DebugOwnerSayListContents("new singels menu", newSinglesMenu);
520 //everything added, write the notecard.
521 WriteNotecard(".menu001A Singles", newSinglesMenu);
522 }
523
524 RemovePosesAndPoseDataFromSitters()
525 {
526 //now the poses have bene converted to syncs or written to their own PMAC menu
527 //remove them from the SITTER cards so they can be processed as just sync's
528 list sitterCards = GetSpecificNotecardCards ("Sitter");
529 integer sitterCardIndex;
530 for (sitterCardIndex = 0; sitterCardIndex < llGetListLength(sitterCards); sitterCardIndex++)
531 { //loop through each sitter card, inside each one remove any pose related lines
532 string cardName = llList2String(sitterCards, sitterCardIndex);
533 list sitterWithNoPoses = GetSitterSyncsAndMenus(cardName);
534 if (debug) DebugOwnerSayListContents("newSitter" + (string)sitterCardIndex, sitterWithNoPoses);
535 WriteNotecard(cardName, sitterWithNoPoses);
536 }
537 }
538
539 list SitterWithNoEmptyMenus (string cardName)
540 { //loop through the card name provided, create a new list which contains
541 //non of the menus which only make up a menu structure, keep the ones which
542 //contain animation buttons.
543 list newList;
544 integer lineIndex;
545 integer cardLength = osGetNumberOfNotecardLines(cardName);
546 for (lineIndex = 0; lineIndex < cardLength; lineIndex++)
547 { //loops through each line of the notecard
548 string thisLine = osGetNotecardLine(cardName, lineIndex);
549 string testMenu = llGetSubString(thisLine, 0, 3);
550 string testBraces = llGetSubString(thisLine, 0, 0);
551 string testPoseName;
552 if (testMenu == "MENU")
553 { //come here only if the line starts with MENU
554 if (debug) llOwnerSay("Debug: Menu Line Found");
555 string nextLine = osGetNotecardLine(cardName, lineIndex + 1);
556 string nextLineMenuTest = llGetSubString(nextLine, 0, 3);
557 if (nextLineMenuTest != "MENU")
558 { //if the next line is not also MENU add this line
559 newList += thisLine;
560 }
561 }
562 else if (testBraces = "{")
563 { //keep everything which is not a Menu line
564 newList += thisLine;
565 }
566 }
567 return newList;
568 }
569
570 RemoveEmptyMenusFromSitterCards()
571 { //removes all the menu structure, preseving just the ones which directly deliver animation buttons
572 list sitterCards = GetSpecificNotecardCards ("Sitter");
573 integer sitterCardIndex;
574 for (sitterCardIndex = 0; sitterCardIndex < llGetListLength(sitterCards); sitterCardIndex++)
575 {
576 string cardName = llList2String(sitterCards, sitterCardIndex);
577 list SitterNoEmptyMenus = SitterWithNoEmptyMenus(cardName);
578 if (debug) DebugOwnerSayListContents("newSitter" + (string)sitterCardIndex, SitterNoEmptyMenus);
579 WriteNotecard(cardName, SitterNoEmptyMenus);
580 }
581 }
582
583 RemoveTempCards()
584 { //loops though the inventory removing any temp notecards created during the conversion
585 list testStrings = ["DataPoses Sitter", "FixedRotations", "Poses Sitter", "PoseToSyncSitter", "Data_Sitter", "Menu_Sitter", "MenuData_Sitter", "Sitter"];
586 list testResults;
587 integer numOfNotecards = llGetInventoryNumber(INVENTORY_NOTECARD);
588 integer notecardIndex;
589 for (notecardIndex = numOfNotecards -1; notecardIndex >=0; notecardIndex--)
590 { //loops through the inventory
591 string notecardName = llGetInventoryName(INVENTORY_NOTECARD, notecardIndex);
592 integer testIndex;
593 for (testIndex = 0; testIndex < llGetListLength(testStrings);testIndex++)
594 { //checks each name against the ones in the list to remove
595 string testString = llList2String(testStrings,testIndex);
596 string testResult = llGetSubString(notecardName, 0, llStringLength(testString)-1);
597 if (testString == testResult)
598 { //when a match is found, remove it.
599 if (debug) llOwnerSay("Debug:RemoveTempCards:Removed: " + notecardName);
600 llRemoveInventory(notecardName);
601 }
602 }
603 }
604 }
605
606 list GetMenuLinePositions(string sitterCard)
607 { //loops through the sitter card, making list of all line positions containing MENU lines
608 integer sitterCardLength = osGetNumberOfNotecardLines(sitterCard);
609 integer lineIndex;
610 list menuLinePositions;
611 integer dataStartLine;
612 for(lineIndex = 0; lineIndex < sitterCardLength; lineIndex++)
613 { //loops through each line of the sittercard
614 string currentLine = osGetNotecardLine(sitterCard, lineIndex);
615 string menuTest = "MENU";
616 string testResult = llGetSubString(currentLine, 0, llStringLength(menuTest)-1);
617 if (menuTest == testResult)
618 { //add this line number to the list
619 menuLinePositions += lineIndex;
620 }
621 }
622 if (debug) llOwnerSay("Debug:GetMenuLinePositions:List: " + llList2CSV(menuLinePositions));
623 return menuLinePositions;
624 }
625
626 GenerateMenuCardsForSyncs()
627 { //goes through each sitter card making invidiual menu notecards for every sitter
628 list sitterCards = GetSpecificNotecardCards ("Sitter");
629 integer sitterCardIndex;
630 for (sitterCardIndex = 0; sitterCardIndex < llGetListLength(sitterCards); sitterCardIndex++)
631 { //loops through each sitter card
632 string sitterCardName = llList2String(sitterCards, sitterCardIndex);
633 list menuLinePositions = GetMenuLinePositions(sitterCardName);
634 list newMenuCardLines;
635 integer menuIndex;
636
637 for (menuIndex = 0; menuIndex < llGetListLength(menuLinePositions); menuIndex++)
638 { //loops through each menu entry for this sitter
639 newMenuCardLines = [];
640 integer menuStartLine = llList2Integer(menuLinePositions, menuIndex) +1; //+1 avoids adding the actual menu line which is no longer required
641 integer menuEndLine;
642 if(menuIndex != llGetListLength(menuLinePositions)-1)
643 { //if its not the last entry, the end point is the start of the next menu
644 menuEndLine = llList2Integer(menuLinePositions, menuIndex+1);
645 }
646 else
647 { //if this is the last menu, set the end to the end of the notecard
648 menuEndLine = osGetNumberOfNotecardLines(sitterCardName)-1; //-1 to ensure we stop at the bottom of the card
649 }
650 integer menuLineIndex;
651 for (menuLineIndex = menuStartLine; menuLineIndex < menuEndLine; menuLineIndex++)
652 { //add each line that forms part of this menu to the new menu card
653 newMenuCardLines;
654 string currentLine = osGetNotecardLine(sitterCardName, menuLineIndex);
655 integer isData = llSubStringIndex(currentLine, "}");
656 if (isData == -1)
657 {
658 newMenuCardLines += currentLine;
659 }
660 }
661 string menuName = MenuNameFromMenuLine(osGetNotecardLine(sitterCardName,menuStartLine-1)) ; //-1 to get the actual menu line
662 string newCardName = "Menu_Sitter_" + (string)sitterCardIndex + "_" + menuName;
663 WriteNotecard(newCardName, newMenuCardLines);
664 }
665 }
666 }
667
668 string FindMatchingDataLine(string buttonName, string sitterNumber)
669 { //loops through the Sitter card for the sitter number provided
670 //looking for the button name provided inside the pos/rot lines
671 //if one is found, return it
672 string dataLine;
673 string sitterCardName = "Sitter" + sitterNumber;
674 integer cardLength = osGetNumberOfNotecardLines(sitterCardName);
675 integer lineIndex = cardLength-1;
676 integer matchFound = FALSE;
677 while (!matchFound && lineIndex >= 0)
678 { //start from the bottom and loop until a match is found, positions are always at the bottom of the card
679 string currentLine = osGetNotecardLine(sitterCardName, lineIndex);
680 integer isPosRot = llSubStringIndex(currentLine, "}");
681 if (isPosRot)
682 { //only look at pos/rot lines
683 string lineName = NameFromPositionsLine(currentLine);
684 if (lineName == buttonName)
685 { //if a match is found add it to the list
686 dataLine = currentLine;
687 matchFound = TRUE;
688 }
689 }
690 lineIndex--;
691 }
692 return dataLine;
693 }
694
695 GenerateDataCardsForSyncs()
696 { //loops through all the temp menu cards, for each one it loops through every
697 //line and then retrieves the matching pos/rot line in the appropriate sitter card
698 //using this to make a dedicated pos/rot DATA card for the menu being processed.
699 list menuCards = GetSpecificNotecardCards ("Menu_");
700 integer menuCardIndex;
701 list dataLines;
702 for (menuCardIndex = 0; menuCardIndex < llGetListLength(menuCards); menuCardIndex++)
703 {
704 dataLines = []; //clear this to make a new one each time
705 string cardName = llList2String(menuCards, menuCardIndex);
706 string sitterNumber = GetSitterNumberFromMenuCardName(cardName);
707 string menuName = GetMenuNameFromMenuCardName(cardName);
708 integer cardLength = osGetNumberOfNotecardLines(cardName);
709 integer cardLineIndex;
710 for (cardLineIndex = 0; cardLineIndex < cardLength; cardLineIndex++)
711 { //loops through the current menu card line by line
712 string cardLine = osGetNotecardLine(cardName, cardLineIndex);
713 string buttonname = GetPoseName (cardLine);
714 string dataLine = FindMatchingDataLine(buttonname, sitterNumber);
715 dataLines += dataLine;
716 }
717 string newCardName = "Data_Sitter_" + sitterNumber + "_" + menuName ;
718 WriteNotecard(newCardName, dataLines);
719 }
720 }
721
722 list GetCombinedSitter0MenuData(string menuCardName, string dataCardName)
723 { //takes the supplied names, retrieves the data from both and combines it line by line.
724 //the returned list will make a MenuData temp notecard.
725 list combinedMenuDataCard;
726 integer menuCardLength = osGetNumberOfNotecardLines(menuCardName);
727 integer dataCardLength = osGetNumberOfNotecardLines(dataCardName);
728 integer menuCardLineIndex;
729 integer dataCardLineIndex;
730 for (menuCardLineIndex = 0; menuCardLineIndex < menuCardLength; menuCardLineIndex++)
731 { //loops through each line of the menu card
732 string menuCardLine = osGetNotecardLine(menuCardName, menuCardLineIndex);
733 string menuButtonName = GetPoseName (menuCardLine);
734 string animName = GetAnimName (menuCardLine);
735 integer dataSitter0CardIndex = 0;
736 integer matchFound = FALSE;
737 while (!matchFound && dataSitter0CardIndex < dataCardLength)
738 {
739 string dataCardLine = osGetNotecardLine(dataCardName, dataSitter0CardIndex);
740 string dataButtonName = NameFromPositionsLine(dataCardLine);
741 if (menuButtonName == dataButtonName)
742 {
743 matchFound = TRUE;
744 string dataPos = PosFromPositionsLine(dataCardLine);
745 string dataRot = RotFromPositionsLine (dataCardLine);
746 string toAdd = menuButtonName + "|NO COM|" + animName + "|" + dataPos + "|" + dataRot;
747 combinedMenuDataCard += toAdd;
748 }
749 dataSitter0CardIndex++;
750 }
751 }
752 return combinedMenuDataCard;
753 }
754
755 CombineSitter0MenuAndDataCards()
756 { //gets a list of all Menu cards and all Data cards then passes them in
757 //pairs to the combine method.
758 list menuSitter0Cards = GetSpecificNotecardCards ("Menu_Sitter_0");
759 list dataDitter0Cards = GetSpecificNotecardCards ("Data_Sitter_0");
760 integer menuSitter0CardIndex;
761 for (menuSitter0CardIndex = 0; menuSitter0CardIndex < llGetListLength(menuSitter0Cards); menuSitter0CardIndex++)
762 {
763 string sitter0MenuCardName = llList2String(menuSitter0Cards, menuSitter0CardIndex);
764 string sitter0DataCardName = llList2String(dataDitter0Cards, menuSitter0CardIndex);
765 string menuName = GetMenuNameFromMenuCardName(sitter0MenuCardName);
766 list combinedSitter0MenuData = GetCombinedSitter0MenuData(sitter0MenuCardName, sitter0DataCardName);
767 WriteNotecard("MenuData_Sitter_0_" + menuName, combinedSitter0MenuData);
768 if (debug) DebugOwnerSayListContents("sitter0MenuData_" + menuName, combinedSitter0MenuData);
769 }
770 }
771
772 list GetRelatedMenuSitterCards(string menuName)
773 { //finds all temp menu cards related to the supplied name and returns the list
774 list menuSitterCards = GetSpecificNotecardCards ("Menu_Sitter");
775 list relatedMenuCards;
776 integer menuCardIndex;
777 for (menuCardIndex = 0; menuCardIndex < llGetListLength(menuSitterCards); menuCardIndex++)
778 { //start loop at 0 incase there is only 1 entry, but ignore the first first loop as we do not want sitter 0
779 string currentCardName = llList2String(menuSitterCards, menuCardIndex);
780 string currentMenuName = GetMenuNameFromMenuCardName(currentCardName);
781 string sitterNumber = GetSitterNumberFromMenuCardName(currentCardName);
782 if (currentMenuName == menuName && sitterNumber != "0")
783 { //ignore sitter 0 since it is the one we are working from, don't duplicate it.
784 relatedMenuCards += currentCardName;
785 }
786 }
787 return relatedMenuCards;
788 }
789
790 string GetAnimNameFromRelatedMenuCard(string relatedMenuCardName, string buttonName)
791 { //All card entries can be out of order, so search through every line until a match is found and return the information.
792 string animName = "";
793 integer cardLength = osGetNumberOfNotecardLines(relatedMenuCardName);
794 integer cardIndex = 0;
795 integer matchFound = FALSE;
796 while (!matchFound && cardIndex < cardLength)
797 {
798 string cardLine = osGetNotecardLine(relatedMenuCardName, cardIndex);
799 string poseName = GetPoseName (cardLine);
800 if (poseName == buttonName)
801 {
802 animName = GetAnimName (cardLine);
803 matchFound = TRUE;
804 }
805 cardIndex++;
806 }
807 return animName;
808 }
809
810 string GetPosRotFromRelatedDataCard(string relatedDataCardName, string buttonName)
811 { //All card entries can be out of order, so search through every line until a match is found and return the information.
812 string posRotData = "";
813 integer cardLength = osGetNumberOfNotecardLines(relatedDataCardName);
814 integer cardIndex = 0;
815 integer matchFound = FALSE;
816 while (!matchFound && cardIndex < cardLength)
817 {
818 string cardLine = osGetNotecardLine(relatedDataCardName, cardIndex);
819 string poseName = NameFromPositionsLine(cardLine);
820 if (poseName == buttonName)
821 {
822 string pos = PosFromPositionsLine(cardLine);
823 string rot = RotFromPositionsLine (cardLine);
824 posRotData = pos + "|" + rot;
825 matchFound = TRUE;
826 }
827 cardIndex++;
828 }
829 return posRotData;
830 }
831
832 CombineMenuDataCardWithRelatedCards(string menuDataCard, string menuName, list relatedMenuCards)
833 { //take every line in the menuData card, find its corresponding line in each related card and combine the information.
834 //then add the combined line to a list, at the end return the list.
835 list pmcaMenuCard;
836 integer cardLength = osGetNumberOfNotecardLines(menuDataCard);
837 integer cardLineIndex;
838 for (cardLineIndex = 0; cardLineIndex < cardLength; cardLineIndex++)
839 {
840 string currentLine = osGetNotecardLine(menuDataCard, cardLineIndex);
841 string buttonName = GetButtonNameFromPmacLine(currentLine);
842 integer relatedCardsIndex;
843 string newLine = currentLine;
844 for (relatedCardsIndex = 0; relatedCardsIndex < llGetListLength(relatedMenuCards); relatedCardsIndex++)
845 {
846 string relatedMenuCardName = llList2String(relatedMenuCards, relatedCardsIndex);
847 string relatedCardSitter = GetSitterNumberFromMenuCardName(relatedMenuCardName);
848 string relatedDataCardName = "Data_Sitter_" + relatedCardSitter + "_" + menuName;
849 string animName = GetAnimNameFromRelatedMenuCard(relatedMenuCardName, buttonName);
850 string posRot = GetPosRotFromRelatedDataCard(relatedDataCardName, buttonName);
851 string extraToAdd = "|" + animName + "|" + posRot;
852 newLine += extraToAdd;
853 }
854 pmcaMenuCard += newLine;
855 }
856 string pmacMenuCardName = ".menu" + "022A " + menuName;
857 WriteNotecard(pmacMenuCardName, pmcaMenuCard);
858 }
859
860 CombineMenuAndDataCards()
861 { //loop through each of the MenuData cards, find the related cards and pass them one by one to the
862 //combine card method.
863 menuCardNumber = 2;
864 CombineSitter0MenuAndDataCards();
865 list menuDataSitter0Cards = GetSpecificNotecardCards ("MenuData_Sitter_0");
866 integer cardIndex;
867 for (cardIndex = 0; cardIndex < llGetListLength(menuDataSitter0Cards); cardIndex++)
868 {
869 string currentCardName = llList2String(menuDataSitter0Cards, cardIndex);
870 string menuName = GetMenuNameFromMenuCardName(currentCardName);
871 list releatedMenuSitterCards = GetRelatedMenuSitterCards(menuName);
872 if (debug) llOwnerSay("Debug:CombineMenuAndDataCards:ProcessingMenu: " + menuName);
873 if (debug) DebugOwnerSayListContents(menuName + " related cards: ", releatedMenuSitterCards);
874 CombineMenuDataCardWithRelatedCards(currentCardName, menuName, releatedMenuSitterCards);
875 }
876 }
877
878 default
879 {
880 state_entry()
881 {
882 if (llGetInventoryType("AVpos") != INVENTORY_NOTECARD)
883 {
884 llOwnerSay("AVpos card not found, aborting");
885 }
886 else
887 {
888 llOwnerSay("Conversion Started");
889 ConvertRotationsAndFixOffset();
890 SplitIntoSitters();
891 llOwnerSay("Sorting singles poses");
892 FixAndCombineSinglePoses();
893 RemovePosesAndPoseDataFromSitters();
894 llOwnerSay("Preparing to convert SYNC's");
895 RemoveEmptyMenusFromSitterCards();
896 llOwnerSay("Creating Temp Menu cards");
897 GenerateMenuCardsForSyncs();
898 llOwnerSay("Creating Temp Position/Rotation cards");
899 GenerateDataCardsForSyncs();
900 llOwnerSay("Creating PMAC menu cards");
901 CombineMenuAndDataCards();
902 llOwnerSay("Clearing up temporary notecards");
903 RemoveTempCards();
904 llOwnerSay("Finished! You should find your new PMAC menu cards inside");
905 }
906
907 }
908 }
Syntax Highlighting
GeShi syntax highlighting is enabled on this wiki. <be>
When using the tabs described in the link, change the language part to "lsl". Eg.
syntaxhighlight lang="lsl" line
inside angled brackets <>