Tags in CryMannequin are used to label Fragments with a series of keywords. Each of these labels or keywords is what we call a Tag. We specify a set of Tags in what we call a TagDefinition, and we use TagStates to indicate which Tags of a specific TagDefintion are enabled or disabled. We also encode the global state of a character with a TagState.
For example, a character that is crouched and equipped with the Scar rifle could have the following tag combination active: Crouch+Rifle+Scar. Crouch, Rifle and Scar would each be a Tag. These Tags would be part of a TagDefinition that might have a lot of other Tags, among which likely a Tag for all the possible character stances (eg. Crouch, Stand, Prone), weapon classes (eg. Rifle, Pistol) and weapons (eg. Scar, Scarab, Hammer), but for the character's TagState only the Crouch, Rifle and Scar Tags are active at this moment.
The separation between TagDefinitions and TagStates allows to store TagStates in a much leaner and efficient manner, since many TagStates will be referring to a common TagDefinition.
The most common usage will be performing operations on TagStates, such as activating or deactivating single Tags, and using TagStates to query for the best matching Fragment to play.
In TagDefinitions we store the structure that provides information on the Tags that form part of a set.
Each Tag must have a unique name within a TagDefinition.
Tags can have priorities associated to them. Tag priorities are used mainly for ranking TagStates.
Tags can be assigned to a group. Tags that are grouped together will be mutually exclusive, so we will not be able to have a TagState indicating that both of them are active at the same time.
Even if Tags are part of different groups, they cannot be given the same name when they are part of the same TagDefinition.
Tags can optionally specify a Sub TagDefinition. This is mainly used by FragmentIds to specify what is the TagDefinition for their FragmentTags.
Tags in a TagDefinition are assigned a sequential and unique TagId (starting from 0 and unique within its TagDefinition) that can be used to more efficiently perform operations instead of always using the name of the Tag.
It is possible to store TagDefinitions in xml files and load them throught the Animation Database Manager.
// Example of how to load a tag definition stored in an xml file.
IMannequin& mannequinInterface = pGameFramework->GetMannequinInterface();
IAnimationDatabaseManager& animationDatabaseManager = pMannequinInterface->GetAnimationDatabaseManager();
const CTagDefinition* pTagDefinition = animationDatabaseManager.LoadTagDefs( "Animations/Mannequin/ADB/ExampleTagDefinition.xml" );
Version 2 of the TagDefinitions xml structure allows for a hierarchical structure: TagDefinition files can include other TagDefinition files. During loading, Tags from inherited TagDefinitions are merged into the main TagDefinition.
TagDefinitions can also be created directly through code, although this is a lot less common.
// Example of how to create a tag definition from code
CTagDefinition example;
example.AddTag("Aiming");
example.AddTag("Crouch", "StanceGroup");
example.AddTag("Stand", "StanceGroup");
example.AssignBits();
TagStates are a helper structure to hold information on which Tags of a TagDefinition are active.
TagStates currently know which tags are active by encoding the whole state in 64 bits, in a fashion resembling bit flags. Therefore, the number of Tags that we can have in a TagDefinition for the usage with TagStates is limited.
By having tags grouped together we can have more than 64 tags. Since such tags are marked as mutually exclusive, the number of bits needed to specify which the single Tag from a group that is active is less than the amount of tags in the group.
In case where the 64 bits limit and the grouping is not enough, the 64 bit storage limit can be increased in the TagState declaration in ICryMannequin.h.