Thursday, 19 March 2015

PMAC tutorial: adding/removing an animation

I'll be doing a few PMAC "tutorials" this week to help builders get up to speed with my newly released PMAC system. Today we'll look at the most common operation of all: adding or removing an animation from an existing group.

I start with a bit of a technical overview of the structural differences between the two systems, but a user who simply wants to add or remove a single animation from an existing system can skip down to the relevant section. It doesn't hurt to have something of an idea how the system works overall, though, so at some point I suggest you come back and read the first section.

Basic PMAC structure


It helps to first understand a bit about the structure of PMAC animation handling and how it relates to the way MLP does it.

In both systems you select the animation to play via a dialog menu. Animations are collect in sets, which PMAC calls "groups". You select a group from the menu, then the animation within that group that you want to play. Associated with each animation is the necessary data to play it for each avatar: the name of the animation and the position and rotation the avi's location relative to the root object.
Structurally, both systems require the menu system to be defined.

A basic MLP system uses one or more MENU notecard which contains data about the animations used, how many people the set is designed for, etc. Then there's a separate notecard with the position data. A single MLP MENU notecard can actually contain the data for multiple groups of animations, assuming it's correctly formatted. At system start-up, all of this information from all notecards is read into memory, parsed, and assembled into lists. It does this using LSL methods (reading the notecards line by line using dataserver events). The net effect for a larger set-up is very slow initialization and a very large amount of memory being consumed storing all that data. During use, it is continually necessary to search and assemble that data in to sub-lists, increasing script cycle use, slowing operation, and further bloating memory.

PMAC uses a similar overall philosophy but requires one separate notecard for each different group. The notecard contains all the information for each animation in that group and is specially formatted to allow PMAC to read the entire card in a single OSSL command and requires virtually no parsing. PMAC leverages this capability to allow it to only load one group of data at a time while maintaining a separate list of available groups, and menus are generated by on-demand strided list calls. This drastically reduces the memory used by the system, makes system start-up extremely fast, and is actually quicker during operation than MLP's assembly method.

MLP Groups contain additional parameters that are defined in the header of each group declaration, indication how many people this group is for (1, 2, 3...up to 6) and who has permission to load it (everyone, only the owner, or only someone who belongs to the same group as the object and has that group tag active). MLP also indicates poseball colours, etc that PMAC doesn't require because it's a no-poseball system. PMAC does the same thing, except those two pieces of data are contained within the notecard's name because that information it only accessed on the fly.

The order that groups appear in a MLP menu is determined by the order they're encountered while MLP parses the assorted notecards. In PMAC the order determined purely by the order the menu cards appear in inventory, so the naming format used for this is designed to allow you to easily set the sort order.

In PMAC an animation group notecard has a name that looks like this:

.menusspr nameWhere:
  • The card name must begin with .menu (dot menu)...I chose to include the dot at the start of the name to help keep the cards near the very top of the object's inventory list.
  • Immediately following this (with no spaces in between) are two additional characters "ss" which can be any valid character -- number or letter -- and will determine the sort order of the menu cards in inventory, hence also the order they appear in your dialog menu.
  • Immediately following this (again with no spaces in between) is a single numerical digit indicating how many people this group is for. PMAC can handle 1 to 9 simultaneous users.
  • Immediately following this (yet again with no space) is a letter indicating any restrictions for use: supplying "A" here allows the group to be allowed for all users. A "G" restricts it only to users who have the same active group tag as the object, and "O" restricts the menu to be loaded only by the owner. PMAC won't even show menu names to people who lack sufficient permission to load them.
  • Then a space, and then finally the name you want to have appear for the dialog button. The name has to be unique (no other menu name can be the same even if the prefix part is different) and should be kept short enough to fit on a dialog button (usually around 10 characters depending on the font being used in the user's viewer).
Inside the notecard is all of the data required for the animations you want assigned to this group.


In PMAC an animation defines one "pose" and hence one button on the menu. Each pose is a separate line and needs a unique name, any additional commands that should be sent to optional add-on scripts, and then the animation and location data needed for each position. Here's a typical notecard line for a two-person massage animation:

Massage|NO COM|ma1_m|<0.069,0.241,0.74>|<0.0,0.0,0.707107,0.707107>|ma1_f|<0.072,0.0,0.836>|<0.0,0.0,0.707107,0.707107>

In PMAC the correct formatting of this data is critical because part of the time- and load-saving of the script is achieved by assuming that notecards are correctly formatted internally. While this lack of error-checking may seem a somewhat rash decision, it has a huge impact on speed and for 99% of users there will never be a need to edit a group notecard at all: they'll make all adjustments using PMAC's built-in position editing ability and store the change directly from dialog (and PMAC flawlessly dumps the data to notecard in exactly the format it wants to read it back in).

An animation line format is:

button name|commands|position 1 animation name|position 1 position|position 1 rotation|....(the animation name, position and rotation for each additional position)

Of particular importance:
  • The pipe symbol ( | ) is used as the data separator for each field within a line
  • NO SPACES!!!! Do not add extra spaces before or after a pipe symbol, This can cause issues. This include being sure there are no trailing spaces at the end of a line. Spaces within an button name is fine. Spaces within an animation name are fine as long as the animation name in inventory has the exact same space. Single spaces after the commas within vectors and rotations are fine...anything that a script can typically read successfully.
  • The button name needs to be unique for this card and should be short enough to fit on a dialog button (ideally 10 character although you could use up to 25)
  • If you're using add-ons, the commands to send to add-on scripts go in the next field (see the PMAC documentation for this). If you aren't, "NO_COM" indicates no commands.
  • Positions are vectors and MUST use the comma as the decimal separator.
  • Unlike MLP, PMAC rotations are actual rotations (<x,y,z,s>) which speeds up operation by not having to convert euler rotations into quaternions for each pose change. The decimal separator has to be a comma for these too.

Deleting an Animation

To delete an existing animation (pose):
  1. Open the notecard for the group that the animation belongs to.
  2. Find that specific animation in the notecard.
  3. Delete the entire line (being careful not to leave a blank line)
  4. Save the notecard.
  5. Reset the PMAC core script.
That's it.

Of course there has to be at least one animation remaining in the notecard, otherwise just delete the whole card and reset.

Adding a New Animation

To add a new animation (pose) is slightly more involved:
  1. Decide which existing group you want to add the new animation to and find that group's menu notecard in inventory. If you want to create a whole new menu group you'll need to add a new notecard with the correct group name formatting (see Groups above).
  2. Open the card
  3. Add a new line to the card -- it can be at the end or insert it between existing lines...the order that animations appear in the card is the order they'll display in the dialog.
  4. Supply a short button name followed immediately by the pipe symbol |
  5. In almost all cases you'll follow that with NO_COM for the commands, then another pipe symbol.
  6. Now for each position you need to supply the inventory animation name (spelling, capitalization, punctuation must be identical!) and a position and rotation, all separated by pipe symbols. In most cases you won't know the position or rotation so I typically start with a position of <0.5,0.0,0.0> for position 1 and <-0.5,0.0,0.0> for position 2 so the will start with a bit of spacing between them; and for the rotations I supply <0.0,0.0,0.0,0.0> for both. Do not use the script constants ZERO_VECTOR or ZERO_ROTATION because they're read in as strings and won't work.
  7. Save the updated card.
  8. Add the animations to the inventory of the PMAC object if you haven't already done so.
  9. Reset the PMAC core script.
  10. Now hop on the bed/sofa/chair/blanket and the new animation will be there for you to use. You'll probably need to enter edit mode to make adjustments to the position and rotation (unless you happened to know their perfect values in advance) and then store from there...PMAC will update your notecard to save the updated data.
And that's all. (See the Animation section above for an example of a correctly formatted line.)