Av-Sitter To PMAC Converter.

From Fire And Ice Grid
Jump to navigation Jump to search


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 <>