BVB Source Codes

CRYENGINE Show ICryMannequinTagDefs.h Source code

Return Download CRYENGINE: download ICryMannequinTagDefs.h Source code - Download CRYENGINE Source code - Type:.h
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. //
  4. ////////////////////////////////////////////////////////////////////////////
  5. #ifndef __I_CRY_MANNEQUIN_TAG_DEFS_H__
  6. #define __I_CRY_MANNEQUIN_TAG_DEFS_H__
  7.  
  8. #ifdef CRYACTION_EXPORTS
  9.         #define CRYMANNEQUIN_API DLL_EXPORT
  10. #else
  11.         #define CRYMANNEQUIN_API DLL_IMPORT
  12. #endif
  13.  
  14. static const uint32 TAGSTATE_MAX_BYTES = 12;
  15.  
  16. enum ETagStateFull
  17. {
  18.         TAG_STATE_FULL = 0xff
  19. };
  20.  
  21. enum ETagStateEmpty
  22. {
  23.         TAG_STATE_EMPTY = 0x00
  24. };
  25.  
  26. struct STagMask
  27. {
  28.         STagMask()
  29.                 : byte(0)
  30.                 , mask(0)
  31.         {
  32.         }
  33.  
  34.         uint8 byte;
  35.         uint8 mask;
  36. };
  37.  
  38. struct STagStateBase
  39. {
  40.         STagStateBase(uint8* memory, uint32 size)
  41.                 : state(memory)
  42.                 , length(size)
  43.         {
  44.         }
  45.  
  46.         STagStateBase& operator=(const STagStateBase& source)
  47.         {
  48.                 CRY_ASSERT(source.length <= length);
  49.  
  50.                 memcpy(state, source.state, source.length);
  51.  
  52.                 return *this;
  53.         }
  54.  
  55.         bool operator==(const STagStateBase& comp) const
  56.         {
  57.                 for (uint32 i = 0; i < length; i++)
  58.                 {
  59.                         if (state[i] != comp.state[i])
  60.                         {
  61.                                 return false;
  62.                         }
  63.                 }
  64.                 return true;
  65.         }
  66.  
  67.         bool operator!=(const STagStateBase& comp) const
  68.         {
  69.                 for (uint32 i = 0; i < length; i++)
  70.                 {
  71.                         if (state[i] != comp.state[i])
  72.                         {
  73.                                 return true;
  74.                         }
  75.                 }
  76.                 return false;
  77.         }
  78.  
  79.         STagStateBase& operator&=(const STagStateBase& comp)
  80.         {
  81.                 for (uint32 i = 0; i < length; i++)
  82.                 {
  83.                         state[i] &= comp.state[i];
  84.                 }
  85.                 return *this;
  86.         }
  87.  
  88.         STagStateBase& operator|=(const STagStateBase& comp)
  89.         {
  90.                 for (uint32 i = 0; i < length; i++)
  91.                 {
  92.                         state[i] |= comp.state[i];
  93.                 }
  94.                 return *this;
  95.         }
  96.  
  97.         uint8 operator&(const STagMask& mask) const
  98.         {
  99.                 CRY_ASSERT(mask.byte < length);
  100.  
  101.                 return (state[mask.byte] & mask.mask);
  102.         }
  103.  
  104.         uint8 operator|(const STagMask& mask) const
  105.         {
  106.                 CRY_ASSERT(mask.byte < length);
  107.  
  108.                 return (state[mask.byte] | mask.mask);
  109.         }
  110.  
  111.         ILINE bool IsNull() const
  112.         {
  113.                 return (state == NULL);
  114.         }
  115.  
  116.         ILINE void Set(const STagStateBase& source)
  117.         {
  118.                 CRY_ASSERT(source.length <= length);
  119.  
  120.                 memcpy(state, source.state, source.length);
  121.         }
  122.  
  123.         ILINE void Clear()
  124.         {
  125.                 memset(state, 0, length);
  126.         }
  127.  
  128.         ILINE void Set(const STagMask& mask, bool set)
  129.         {
  130.                 CRY_ASSERT(mask.byte < length);
  131.  
  132.                 if (set)
  133.                 {
  134.                         state[mask.byte] |= mask.mask;
  135.                 }
  136.                 else
  137.                 {
  138.                         state[mask.byte] &= ~mask.mask;
  139.                 }
  140.         }
  141.  
  142.         ILINE bool Contains(const STagStateBase& data, const STagStateBase& mask) const
  143.         {
  144.                 CRY_ASSERT(length >= data.length);
  145.                 CRY_ASSERT(mask.length >= data.length);
  146.  
  147.                 bool ret = true;
  148.  
  149.                 const uint8* statePtr = state;
  150.                 const uint8* maskPtr = mask.state;
  151.                 const uint8* dataPtr = data.state;
  152.                 const uint8* endPtr = statePtr + data.length;
  153.  
  154.                 for (; statePtr != endPtr; statePtr++, maskPtr++, dataPtr++)
  155.                 {
  156.                         ret = ret && ((*statePtr & *maskPtr) == *dataPtr);
  157.                 }
  158.  
  159.                 return ret;
  160.         }
  161.  
  162.         ILINE bool Contains(const STagStateBase& data, const STagStateBase& mask, const uint32 compLength) const
  163.         {
  164.                 CRY_ASSERT(compLength <= length);
  165.                 CRY_ASSERT(compLength <= data.length);
  166.                 CRY_ASSERT(compLength <= data.length);
  167.  
  168.                 bool ret = true;
  169.  
  170.                 const uint8* statePtr = state;
  171.                 const uint8* maskPtr = mask.state;
  172.                 const uint8* dataPtr = data.state;
  173.                 const uint8* endPtr = statePtr + compLength;
  174.  
  175.                 for (; statePtr != endPtr; statePtr++, maskPtr++, dataPtr++)
  176.                 {
  177.                         ret = ret && ((*statePtr & *maskPtr) == *dataPtr);
  178.                 }
  179.  
  180.                 return ret;
  181.         }
  182.  
  183.         void SetDifference(const STagStateBase& a, const STagStateBase& b)
  184.         {
  185.                 CRY_ASSERT(length >= a.length);
  186.                 CRY_ASSERT(a.length == b.length);
  187.  
  188.                 uint8* statePtr = state;
  189.                 const uint8* aStatePtr = a.state;
  190.                 const uint8* bStatePtr = b.state;
  191.                 const uint8* endPtr = statePtr + a.length;
  192.  
  193.                 for (; statePtr != endPtr; statePtr++, aStatePtr++, bStatePtr++)
  194.                 {
  195.                         * statePtr = *aStatePtr & ~(*bStatePtr);
  196.                 }
  197.         }
  198.  
  199.         ILINE bool IsSet(const STagMask& mask) const
  200.         {
  201.                 CRY_ASSERT(mask.byte < length);
  202.  
  203.                 return (mask.mask != 0) && ((state[mask.byte] & mask.mask) == mask.mask);
  204.         }
  205.  
  206.         ILINE bool AreAnySet(const STagMask& mask) const
  207.         {
  208.                 CRY_ASSERT(mask.byte < length);
  209.  
  210.                 return (mask.mask != 0) && ((state[mask.byte] & mask.mask) != 0);
  211.         }
  212.  
  213.         ILINE bool IsSet(const STagMask& groupMask, const STagMask& tagMask) const
  214.         {
  215.                 CRY_ASSERT(groupMask.byte < length);
  216.                 CRY_ASSERT(groupMask.byte == tagMask.byte);
  217.  
  218.                 return (tagMask.mask != 0) && ((state[groupMask.byte] & groupMask.mask) == tagMask.mask);
  219.         }
  220.  
  221.         ILINE bool IsSame(const STagStateBase& a, const STagMask& mask) const
  222.         {
  223.                 CRY_ASSERT(mask.byte < length);
  224.                 CRY_ASSERT(mask.byte < a.length);
  225.  
  226.                 return (state[mask.byte] & mask.mask) == (a.state[mask.byte] & mask.mask);
  227.         }
  228.  
  229.         uint8* state;
  230.         uint32 length;
  231. };
  232.  
  233. template<uint32 NUM_BYTES>
  234. struct STagState
  235. {
  236.         STagState()
  237.         {
  238.         }
  239.  
  240.         ILINE STagState(ETagStateFull pattern)
  241.         {
  242.                 memset(state, TAG_STATE_FULL, NUM_BYTES);
  243.         }
  244.         ILINE STagState(ETagStateEmpty pattern)
  245.         {
  246.                 memset(state, TAG_STATE_EMPTY, NUM_BYTES);
  247.         }
  248.  
  249.         STagState(const STagStateBase& copyFrom)
  250.         {
  251.                 CRY_ASSERT(copyFrom.length <= NUM_BYTES);
  252.                 memcpy(state, copyFrom.state, (std::min)(copyFrom.length, NUM_BYTES));
  253.                 memset(state + copyFrom.length, TAG_STATE_EMPTY, NUM_BYTES - copyFrom.length);
  254.         }
  255.  
  256.         ILINE operator STagStateBase()
  257.         {
  258.                 return STagStateBase(state, NUM_BYTES);
  259.         }
  260.  
  261.         ILINE operator const STagStateBase() const
  262.         {
  263.                 //--- Deliberate const case here, the structure as a whole is const
  264.                 return STagStateBase(const_cast<uint8*>(state), NUM_BYTES);
  265.         }
  266.  
  267.         template<typename T>
  268.         void SetFromInteger(const T& value)
  269.         {
  270.                 static_assert(sizeof(T) == NUM_BYTES, "Invalid type size!");
  271.  
  272. #ifdef NEED_ENDIAN_SWAP
  273.                 const uint8* pIn = ((const uint8*)&value) + NUM_BYTES;
  274.                 for (uint32 i = 0; i < NUM_BYTES; i++)
  275.                 {
  276.                         state[i] = *(--pIn);
  277.                 }
  278. #else // (!NEED_ENDIAN_SWAP)
  279.                 memcpy(state, &value, NUM_BYTES);
  280. #endif // (!NEED_ENDIAN_SWAP)
  281.         }
  282.  
  283.         template<typename T>
  284.         void GetToInteger(T& value) const
  285.         {
  286.                 static_assert(sizeof(T) == NUM_BYTES, "Invalid type size!");
  287.                 GetToInteger(value, sizeof(T) * 8);
  288.         }
  289.  
  290.         template<typename T>
  291.         void GetToInteger(T& value, uint32 numBits) const
  292.         {
  293.                 CRY_ASSERT_MESSAGE(numBits <= sizeof(T) * 8, "value is not large enough to accommodate the number of bits stored in the TagState");
  294.                 uint32 minSize = (sizeof(T) <= NUM_BYTES ? sizeof(T) : NUM_BYTES);
  295. #ifdef NEED_ENDIAN_SWAP
  296.                 uint8* pOut = ((uint8*)&value) + sizeof(T);
  297.                 for (uint32 i = 0; i < minSize; i++)
  298.                 {
  299.                         *(--pOut) = state[i];
  300.                 }
  301.                 if (sizeof(T) > NUM_BYTES)
  302.                 {
  303.                         memset(&value, 0, sizeof(T) - NUM_BYTES);
  304.                 }
  305. #else // (!NEED_ENDIAN_SWAP)
  306.                 memcpy(&value, state, minSize);
  307.                 if (sizeof(T) > NUM_BYTES)
  308.                 {
  309.                         memset(((uint8*)&value) + NUM_BYTES, 0, sizeof(T) - NUM_BYTES);
  310.                 }
  311. #endif // (!NEED_ENDIAN_SWAP)
  312.         }
  313.  
  314.         bool operator==(const STagState<NUM_BYTES>& comp) const
  315.         {
  316.                 for (uint32 i = 0; i < NUM_BYTES; i++)
  317.                 {
  318.                         if (state[i] != comp.state[i])
  319.                         {
  320.                                 return false;
  321.                         }
  322.                 }
  323.                 return true;
  324.         }
  325.  
  326.         bool operator!=(const STagState<NUM_BYTES>& comp) const
  327.         {
  328.                 for (uint32 i = 0; i < NUM_BYTES; i++)
  329.                 {
  330.                         if (state[i] != comp.state[i])
  331.                         {
  332.                                 return true;
  333.                         }
  334.                 }
  335.                 return false;
  336.         }
  337.  
  338.         STagState<NUM_BYTES> operator&(const STagState<NUM_BYTES>& comp) const
  339.         {
  340.                 STagState ret;
  341.  
  342.                 for (uint32 i = 0; i < NUM_BYTES; i++)
  343.                 {
  344.                         ret.state[i] = state[i] & comp.state[i];
  345.                 }
  346.                 return ret;
  347.         }
  348.  
  349.         STagState<NUM_BYTES> operator|(const STagState<NUM_BYTES>& comp) const
  350.         {
  351.                 STagState ret;
  352.  
  353.                 for (uint32 i = 0; i < NUM_BYTES; i++)
  354.                 {
  355.                         ret.state[i] = state[i] | comp.state[i];
  356.                 }
  357.                 return ret;
  358.         }
  359.  
  360.         ILINE bool IsEmpty() const
  361.         {
  362.                 bool ret = true;
  363.                 for (uint32 i = 0; i < NUM_BYTES; i++)
  364.                 {
  365.                         ret = ret && (state[i] == 0);
  366.                 }
  367.  
  368.                 return ret;
  369.         }
  370.  
  371.         ILINE void Clear()
  372.         {
  373.                 memset(state, 0, NUM_BYTES);
  374.         }
  375.  
  376.         ILINE void Set(const STagMask& mask, bool set)
  377.         {
  378.                 CRY_ASSERT(mask.byte < NUM_BYTES);
  379.  
  380.                 if (set)
  381.                 {
  382.                         state[mask.byte] |= mask.mask;
  383.                 }
  384.                 else
  385.                 {
  386.                         state[mask.byte] &= ~mask.mask;
  387.                 }
  388.         }
  389.  
  390.         ILINE bool IsSet(const STagMask& mask) const
  391.         {
  392.                 CRY_ASSERT(mask.byte < NUM_BYTES);
  393.  
  394.                 return ((state[mask.byte] & mask.mask) == mask.mask);
  395.         }
  396.  
  397.         ILINE bool AreAnySet(const STagMask& mask) const
  398.         {
  399.                 CRY_ASSERT(mask.byte < NUM_BYTES);
  400.  
  401.                 return (state[mask.byte] & mask.mask) != 0;
  402.         }
  403.  
  404.         ILINE bool IsSet(const STagMask& groupMask, const STagMask& tagMask) const
  405.         {
  406.                 CRY_ASSERT(groupMask.byte < NUM_BYTES);
  407.                 CRY_ASSERT(groupMask.byte == tagMask.byte);
  408.  
  409.                 return (state[groupMask.byte] & groupMask.mask) == tagMask.mask;
  410.         }
  411.  
  412.         void Serialize(TSerialize serialize)
  413.         {
  414.                 for (int i = 0; i < NUM_BYTES; ++i)
  415.                 {
  416.                         serialize.Value("stateBytes", state[i], 'ui8');
  417.                 }
  418.         }
  419.  
  420. private:
  421.  
  422.         uint8 state[NUM_BYTES];
  423. };
  424.  
  425. typedef STagState<TAGSTATE_MAX_BYTES> TagState;
  426.  
  427. enum ETagDefinitionFlags
  428. {
  429.         eTDF_Tags = 1,
  430. };
  431.  
  432. class CTagDefinition
  433. {
  434. public:
  435.  
  436.         struct SPriorityCount
  437.         {
  438.                 int priority;
  439.                 int count;
  440.         };
  441.  
  442.         CTagDefinition()
  443.                 : m_hasMasks(false)
  444.         {
  445.         }
  446.  
  447.         // copy constructor used in TagDef editor
  448.         CTagDefinition(const CTagDefinition& rhs)
  449.                 : m_filename(rhs.m_filename)
  450.                 , m_tags(rhs.m_tags)
  451.                 , m_tagGroups(rhs.m_tagGroups)
  452.                 , m_defData(rhs.m_defData)
  453.                 , m_priorityTallies(rhs.m_priorityTallies)
  454.                 , m_hasMasks(rhs.m_hasMasks)
  455.         {
  456.         }
  457.  
  458.         CTagDefinition& operator=(const CTagDefinition& rhs)
  459.         {
  460.                 m_filename = rhs.m_filename;
  461.                 m_tags = rhs.m_tags;
  462.                 m_tagGroups = rhs.m_tagGroups;
  463.                 m_defData = rhs.m_defData;
  464.                 m_priorityTallies = rhs.m_priorityTallies;
  465.                 m_hasMasks = rhs.m_hasMasks;
  466.  
  467.                 return *this;
  468.         }
  469.  
  470.         explicit CTagDefinition(const char* filename)
  471.                 : m_hasMasks(false)
  472.         {
  473.                 SetFilename(filename);
  474.         }
  475.  
  476.         struct STagDefData
  477.         {
  478.                 DynArray<STagMask> tagMasks;
  479.                 DynArray<STagMask> groupMasks;
  480.                 uint32             numBits;
  481.  
  482.                 ILINE uint32       GetNumBytes() const
  483.                 {
  484.                         return (numBits + 7) >> 3;
  485.                 }
  486.  
  487.                 ILINE TagState GenerateMask(const STagStateBase& tagState) const
  488.                 {
  489.                         TagState ret;
  490.                         STagStateBase editRet(ret);
  491.                         editRet = tagState;
  492.                         const TagGroupID numGroups = (TagGroupID)groupMasks.size();
  493.                         for (TagGroupID i = 0; i < numGroups; i++)
  494.                         {
  495.                                 const STagMask& groupMask = groupMasks[i];
  496.                                 if (groupMask.mask)
  497.                                 {
  498.                                         editRet.Set(groupMask, tagState.AreAnySet(groupMask));
  499.                                 }
  500.                         }
  501.  
  502.                         return ret;
  503.                 }
  504.  
  505.                 ILINE bool Contains(const STagStateBase& compParent, const STagStateBase& compChild, const STagStateBase& comparisonMask) const
  506.                 {
  507.                         return compParent.Contains(compChild, comparisonMask, GetNumBytes());
  508.                 }
  509.  
  510.                 ILINE bool Contains(const STagStateBase& compParent, const STagStateBase& compChild) const
  511.                 {
  512.                         if (!compParent.Contains(compChild, compChild, GetNumBytes()))
  513.                         {
  514.                                 //--- Trivial rejection
  515.                                 return false;
  516.                         }
  517.                         else
  518.                         {
  519.                                 TagState comparisonMask = GenerateMask(compChild);
  520.  
  521.                                 return compParent.Contains(compChild, comparisonMask, GetNumBytes());
  522.                         }
  523.                 }
  524.         };
  525.  
  526.         struct STagGroup
  527.         {
  528.                 STagGroup(const char* szGroupName)
  529.                 {
  530.                         m_name.SetByString(szGroupName);
  531.                 }
  532.  
  533.                 STagRef m_name;
  534.         };
  535.  
  536.         struct STag
  537.         {
  538.                 STag(const char* szTag, uint32 priority, int groupID)
  539.                 {
  540.                         m_name.SetByString(szTag);
  541.                         m_priority = priority;
  542.                         m_groupID = groupID;
  543.                         m_pTagDefinition = NULL;
  544.                 }
  545.  
  546.                 uint32                m_priority;
  547.                 TagGroupID            m_groupID;
  548.                 const CTagDefinition* m_pTagDefinition;
  549.                 STagRef               m_name;
  550.         };
  551.  
  552.         ILINE bool IsValidTagID(TagID tagID) const
  553.         {
  554.                 return (tagID >= 0) && (tagID < (TagID)m_tags.size());
  555.         }
  556.  
  557.         ILINE bool IsValidTagGroupID(TagGroupID groupID) const
  558.         {
  559.                 return (groupID >= 0) && (groupID < (TagGroupID)m_tagGroups.size());
  560.         }
  561.  
  562.         TagID GetNum() const
  563.         {
  564.                 return (TagID)m_tags.size();
  565.         }
  566.  
  567.         uint32 GetPriority(TagID tagID) const
  568.         {
  569.                 if (!IsValidTagID(tagID))
  570.                         return 0;
  571.  
  572.                 return m_tags[tagID].m_priority;
  573.         }
  574.  
  575.         void SetPriority(TagID tagID, uint32 priority)
  576.         {
  577.                 if (!IsValidTagID(tagID))
  578.                         return;
  579.  
  580.                 m_tags[tagID].m_priority = priority;
  581.         }
  582.  
  583.         void Clear()
  584.         {
  585.                 m_tags.clear();
  586.                 m_tagGroups.clear();
  587.         }
  588.  
  589.         ILINE bool HasMasks() const
  590.         {
  591.                 return m_hasMasks;
  592.         }
  593.  
  594.         const CTagDefinition* GetSubTagDefinition(TagID tagID) const
  595.         {
  596.                 if (!IsValidTagID(tagID))
  597.                         return NULL;
  598.  
  599.                 return m_tags[tagID].m_pTagDefinition;
  600.         }
  601.  
  602.         void SetSubTagDefinition(TagID tagID, const CTagDefinition* pTagDef)
  603.         {
  604.                 if (IsValidTagID(tagID))
  605.                 {
  606.                         m_tags[tagID].m_pTagDefinition = pTagDef;
  607.                 }
  608.         }
  609.  
  610.         TagID AddTag(const char* szTag, const char* szGroup = NULL, uint32 priority = 0)
  611.         {
  612.                 const bool tagExistsAlready = (Find(szTag) != TAG_ID_INVALID);
  613.                 if (tagExistsAlready)
  614.                         return TAG_ID_INVALID;
  615.  
  616.                 TagGroupID groupID = GROUP_ID_NONE;
  617.                 if (szGroup)
  618.                         groupID = AddGroup(szGroup);
  619.  
  620.                 m_tags.push_back(STag(szTag, priority, groupID));
  621.  
  622.                 return (TagID)m_tags.size() - 1;
  623.         }
  624.  
  625.         void RemoveTag(TagID tagID)
  626.         {
  627.                 m_tags.erase(m_tags.begin() + tagID);
  628.         }
  629.  
  630.         TagGroupID AddGroup(const char* szGroup)
  631.         {
  632.                 TagGroupID groupID = FindGroup(szGroup);
  633.  
  634.                 if (groupID == GROUP_ID_NONE)
  635.                 {
  636.                         groupID = m_tagGroups.size();
  637.                         m_tagGroups.push_back(STagGroup(szGroup));
  638.                 }
  639.  
  640.                 return groupID;
  641.         }
  642.  
  643.         void RemoveGroup(TagGroupID groupID)
  644.         {
  645.                 m_tagGroups.erase(m_tagGroups.begin() + groupID);
  646.  
  647.                 // Adjust GroupID reference in the tags
  648.                 DynArray<STag>::iterator itEnd = m_tags.end();
  649.                 for (DynArray<STag>::iterator it = m_tags.begin(); it != itEnd; ++it)
  650.                 {
  651.                         STag& tag = *it;
  652.                         if (tag.m_groupID == groupID)
  653.                                 tag.m_groupID = GROUP_ID_NONE;
  654.                         else if (tag.m_groupID > groupID)
  655.                                 tag.m_groupID--;
  656.                 }
  657.         }
  658.  
  659.         bool AssignBits()
  660.         {
  661.                 const bool allAssigned = AssignBits(m_defData);
  662.                 CalculatePriorityTallies();
  663.  
  664.                 m_hasMasks = true;
  665.  
  666.                 return allAssigned;
  667.         }
  668.  
  669.         //-----------------------------------------------------------------------------
  670.         // Assign bits
  671.         //-----------------------------------------------------------------------------
  672.         // Assigns bits for the tags & groups.
  673.         // - Shares memory between groups and ensures that the groups do not straddle byte boundaries for simple masking.
  674.         // - [optional] Pass in a usedTags mask to filter which tags are assigned bits
  675.         //   (this requires internal tags to be setup first!)
  676.         // - Returns false if not all tags could be assigned because of size constraints, true otherwise
  677.         //-----------------------------------------------------------------------------
  678.         bool AssignBits(STagDefData& tagDefData, const STagStateBase& usedTags = STagStateBase(0, 0)) const
  679.         {
  680.                 DynArray<STagMask>& tagMasks = tagDefData.tagMasks;
  681.                 DynArray<STagMask>& groupMasks = tagDefData.groupMasks;
  682.  
  683.                 const TagID numTags = (TagID)m_tags.size();
  684.                 const TagGroupID numGroups = (TagGroupID)m_tagGroups.size();
  685.  
  686.                 tagMasks.resize(numTags, STagMask());
  687.                 groupMasks.resize(numGroups, STagMask());
  688.  
  689.                 TagID tagsMapped = 0;
  690.                 TagID totalTagsToMap = numTags;
  691.                 uint32 totalBits = 0;
  692.  
  693.                 for (TagID i = 0; (i < numTags); i++)
  694.                 {
  695.                         tagMasks[i].mask = 0;
  696.                 }
  697.                 for (TagGroupID i = 0; (i < numGroups); i++)
  698.                 {
  699.                         groupMasks[i].mask = 0;
  700.                 }
  701.  
  702.                 if (!usedTags.IsNull())
  703.                 {
  704.                         totalTagsToMap = 0;
  705.  
  706.                         for (TagID i = 0; (i < numTags); i++)
  707.                         {
  708.                                 if (usedTags.IsSet(m_defData.tagMasks[i]))
  709.                                 {
  710.                                         totalTagsToMap++;
  711.                                 }
  712.                         }
  713.                 }
  714.  
  715.                 for (uint32 curByte = 0; (curByte < TAGSTATE_MAX_BYTES) && (tagsMapped < totalTagsToMap); curByte++)
  716.                 {
  717.                         uint8 curBit = 0;
  718.  
  719.                         for (TagGroupID g = 0; (g < numGroups) && (curBit < 8); g++)
  720.                         {
  721.                                 uint32 numTagsInGroup = 0;
  722.  
  723.                                 if ((groupMasks[g].mask == 0)
  724.                                     && (usedTags.IsNull() || usedTags.AreAnySet(m_defData.groupMasks[g])))
  725.                                 {
  726.                                         for (TagID i = 0; i < numTags; i++)
  727.                                         {
  728.                                                 const STag& tag = m_tags[i];
  729.                                                 if (tag.m_groupID == g)
  730.                                                 {
  731.                                                         numTagsInGroup++;
  732.                                                 }
  733.                                         }
  734.  
  735.                                         uint32 numBits = 32 - countLeadingZeros32(numTagsInGroup);
  736.                                         if (numBits <= (uint32)(8 - curBit))
  737.                                         {
  738.                                                 groupMasks[g].byte = curByte;
  739.                                                 groupMasks[g].mask = 0;
  740.  
  741.                                                 numTagsInGroup = 0;
  742.                                                 for (TagID i = 0; i < numTags; i++)
  743.                                                 {
  744.                                                         const STag& tag = m_tags[i];
  745.                                                         if (tag.m_groupID == g)
  746.                                                         {
  747.                                                                 numTagsInGroup++;
  748.                                                                 tagMasks[i].byte = curByte;
  749.                                                                 tagMasks[i].mask = numTagsInGroup << curBit;
  750.                                                         }
  751.                                                 }
  752.  
  753.                                                 for (uint32 i = 0, bit = 1 << curBit; i < numBits; i++, bit <<= 1)
  754.                                                 {
  755.                                                         groupMasks[g].mask |= bit;
  756.                                                 }
  757.                                                 curBit += numBits;
  758.                                                 tagsMapped += numTagsInGroup;
  759.                                         }
  760.                                 }
  761.                         }
  762.  
  763.                         for (TagID i = 0; (i < numTags) && (curBit < 8); i++)
  764.                         {
  765.                                 const STag& tag = m_tags[i];
  766.  
  767.                                 if ((tagMasks[i].mask == 0)
  768.                                     && (tag.m_groupID == GROUP_ID_NONE)
  769.                                     && (usedTags.IsNull() || usedTags.IsSet(m_defData.tagMasks[i])))
  770.                                 {
  771.                                         tagMasks[i].byte = curByte;
  772.                                         tagMasks[i].mask = (1 << curBit);
  773.                                         curBit++;
  774.                                         tagsMapped++;
  775.                                 }
  776.                         }
  777.  
  778.                         if (tagsMapped < totalTagsToMap)
  779.                                 totalBits += 8;
  780.                         else
  781.                                 totalBits += curBit;
  782.                 }
  783.  
  784.                 tagDefData.numBits = totalBits;
  785.  
  786.                 const bool allAssigned = totalTagsToMap == tagsMapped;
  787.                 return allAssigned;
  788.         }
  789.  
  790.         //---------------------------------------------------------------------------------------------------------------
  791.         // Maps the original tag state via the modified tag def (allows remapping of indices when a tag is deleted)
  792.         //---------------------------------------------------------------------------------------------------------------
  793.         bool MapTagState(const STagStateBase& originalTags, STagStateBase mappedTags, CTagDefinition& modifiedTagDef) const
  794.         {
  795.                 const uint32 numTags = m_tags.size();
  796.                 bool allMapped = true;
  797.                 mappedTags.Clear();
  798.  
  799.                 for (uint32 tagIndex = 0; tagIndex < numTags; ++tagIndex)
  800.                 {
  801.                         if (IsSet(originalTags, tagIndex))
  802.                         {
  803.                                 uint32 mappedTagID = modifiedTagDef.Find(GetTagCRC(tagIndex));
  804.                                 if (mappedTagID != TAG_ID_INVALID)
  805.                                 {
  806.                                         if (tagIndex != mappedTagID)
  807.                                         {
  808.                                                 //CryLog("[TAGDEF]: MapTagState() (%s): mapped tag %i [%s] to %i [%s]", m_filename, tagIndex, GetTagName(tagIndex), mappedTagID, modifiedTagDef.GetTagName(mappedTagID));
  809.                                         }
  810.                                         modifiedTagDef.Set(mappedTags, mappedTagID, true);
  811.                                 }
  812.                                 else
  813.                                 {
  814.                                         //CryLog("[TAGDEF]: MapTagState() (%s): Cannot map tag %i [%s] - will be erased", m_filename, tagIndex, GetTagName(tagIndex));
  815.                                         allMapped = false;
  816.                                 }
  817.                         }
  818.                 }
  819.  
  820.                 return allMapped;
  821.         }
  822.  
  823.         //---------------------------------------------------------------------------------------------------------------
  824.         // Checks to see if a given tag mask can be represented by an input set of tag definition data
  825.         //---------------------------------------------------------------------------------------------------------------
  826.         bool CanRepresent(const STagStateBase& sourceTags, const STagDefData& data) const
  827.         {
  828.                 const uint32 numTags = m_tags.size();
  829.  
  830.                 for (uint32 i = 0; i < numTags; i++)
  831.                 {
  832.                         if (IsSet(sourceTags, i) && (data.tagMasks[i].mask == 0))
  833.                         {
  834.                                 return false;
  835.                         }
  836.                 }
  837.  
  838.                 return true;
  839.         }
  840.  
  841.         //---------------------------------------------------------------------------------------------------------------
  842.         // Converts a tag state from the default format to the format specified by the input STagDefData, dropping
  843.         // unmapped tags and shrinking down the memory footprint
  844.         //---------------------------------------------------------------------------------------------------------------
  845.         void CompressTagState(STagStateBase targetTags, const STagStateBase& sourceTags, const STagDefData& data) const
  846.         {
  847.                 const uint32 numTags = m_tags.size();
  848.                 targetTags.Clear();
  849.  
  850.                 if (!data.tagMasks.empty())
  851.                 {
  852.                         const STagMask* pTagMaskDest = &data.tagMasks[0];
  853.                         for (uint32 i = 0; i < numTags; i++)
  854.                         {
  855.                                 if (pTagMaskDest->mask != 0)
  856.                                 {
  857.                                         TagGroupID groupID = m_tags[i].m_groupID;
  858.                                         if (groupID != GROUP_ID_NONE)
  859.                                         {
  860.                                                 if (sourceTags.IsSet(m_defData.groupMasks[groupID], m_defData.tagMasks[i]))
  861.                                                 {
  862.                                                         targetTags.Set(*pTagMaskDest, true);
  863.                                                 }
  864.                                         }
  865.                                         else
  866.                                         {
  867.                                                 if (sourceTags.IsSet(m_defData.tagMasks[i]))
  868.                                                 {
  869.                                                         targetTags.Set(*pTagMaskDest, true);
  870.                                                 }
  871.                                         }
  872.                                 }
  873.  
  874.                                 pTagMaskDest++;
  875.                         }
  876.                 }
  877.         }
  878.  
  879.         //---------------------------------------------------------------------------------------------------------------
  880.         // Converts a tag state from the format specified by the input STagDefData to the default format,
  881.         // expanding the memory footprint to the full uncompressed size
  882.         //---------------------------------------------------------------------------------------------------------------
  883.         void UncompressTagState(STagStateBase targetTags, const STagStateBase& sourceTags, const STagDefData& data) const
  884.         {
  885.                 const uint32 numTags = m_tags.size();
  886.                 targetTags.Clear();
  887.  
  888.                 if (!data.tagMasks.empty())
  889.                 {
  890.                         const STagMask* pTagMaskDest = &data.tagMasks[0];
  891.                         for (uint32 i = 0; i < numTags; i++)
  892.                         {
  893.                                 if (pTagMaskDest->mask != 0)
  894.                                 {
  895.                                         TagGroupID groupID = m_tags[i].m_groupID;
  896.                                         if (groupID != GROUP_ID_NONE)
  897.                                         {
  898.                                                 if (sourceTags.IsSet(data.groupMasks[groupID], *pTagMaskDest))
  899.                                                 {
  900.                                                         targetTags.Set(m_defData.tagMasks[i], true);
  901.                                                 }
  902.                                         }
  903.                                         else
  904.                                         {
  905.                                                 if (sourceTags.IsSet(*pTagMaskDest))
  906.                                                 {
  907.                                                         targetTags.Set(m_defData.tagMasks[i], true);
  908.                                                 }
  909.                                         }
  910.                                 }
  911.  
  912.                                 pTagMaskDest++;
  913.                         }
  914.                 }
  915.         }
  916.  
  917.         TagGroupID GetGroupID(TagID tagID) const
  918.         {
  919.                 if (!IsValidTagID(tagID))
  920.                         return GROUP_ID_NONE;
  921.  
  922.                 return m_tags[tagID].m_groupID;
  923.         }
  924.  
  925.         TagGroupID GetNumGroups() const
  926.         {
  927.                 return (TagGroupID)m_tagGroups.size();
  928.         }
  929.  
  930.         uint32 GetGroupCRC(TagGroupID groupID) const
  931.         {
  932.                 CRY_ASSERT(IsValidTagGroupID(groupID));
  933.                 if (!IsValidTagGroupID(groupID))
  934.                         return 0;
  935.  
  936.                 return m_tagGroups[groupID].m_name.crc;
  937.         }
  938.  
  939. #if STORE_TAG_STRINGS
  940.  
  941.         const char* GetGroupName(TagGroupID groupID) const
  942.         {
  943.                 CRY_ASSERT(IsValidTagGroupID(groupID));
  944.                 if (!IsValidTagGroupID(groupID))
  945.                         return "<invalid>";
  946.  
  947.                 return m_tagGroups[groupID].m_name.c_str();
  948.         }
  949.  
  950.         void SetGroupName(TagGroupID groupID, const char* szGroup)
  951.         {
  952.                 CRY_ASSERT(IsValidTagGroupID(groupID));
  953.                 if (!IsValidTagGroupID(groupID))
  954.                         return;
  955.  
  956.                 m_tagGroups[groupID].m_name.SetByString(szGroup);
  957.         }
  958.  
  959. #endif //STORE_TAG_STRINGS
  960.  
  961.         TagID Find(const char* szTag) const
  962.         {
  963.                 if (szTag)
  964.                 {
  965.                         uint32 crc = MannGenCRC(szTag);
  966.  
  967.                         return Find(crc);
  968.                 }
  969.                 else
  970.                 {
  971.                         return TAG_ID_INVALID;
  972.                 }
  973.         }
  974.  
  975.         TagID Find(uint32 crc) const
  976.         {
  977.                 // TODO: Use hash/map
  978.                 TagID numTags = (TagID)m_tags.size();
  979.                 for (TagID i = 0; i < numTags; i++)
  980.                 {
  981.                         if (m_tags[i].m_name.crc == crc)
  982.                         {
  983.                                 return i;
  984.                         }
  985.                 }
  986.  
  987.                 return TAG_ID_INVALID;
  988.         }
  989.  
  990.         TagGroupID FindGroup(const char* szTag) const
  991.         {
  992.                 uint32 crc = MannGenCRC(szTag);
  993.  
  994.                 return FindGroup(crc);
  995.         }
  996.  
  997.         TagGroupID FindGroup(uint32 crc) const
  998.         {
  999.                 // TODO: Use hash/map
  1000.                 TagGroupID numGroups = (TagGroupID)m_tagGroups.size();
  1001.                 for (TagGroupID i = 0; i < numGroups; i++)
  1002.                 {
  1003.                         if (m_tagGroups[i].m_name.crc == crc)
  1004.                         {
  1005.                                 return i;
  1006.                         }
  1007.                 }
  1008.  
  1009.                 return GROUP_ID_NONE;
  1010.         }
  1011.  
  1012.         void SetFilename(const char* filename)
  1013.         {
  1014.                 m_filename = filename;
  1015.         }
  1016.         const char* GetFilename() const
  1017.         {
  1018.                 return m_filename.c_str();
  1019.         }
  1020.  
  1021.         uint32 GetTagCRC(TagID tagID) const
  1022.         {
  1023.                 if (!IsValidTagID(tagID))
  1024.                         return 0;
  1025.  
  1026.                 return m_tags[tagID].m_name.crc;
  1027.         }
  1028.  
  1029.         const char* GetTagName(TagID tagID) const
  1030.         {
  1031.                 if (!IsValidTagID(tagID))
  1032.                         return "<invalid>";
  1033.  
  1034.                 return m_tags[tagID].m_name.c_str();
  1035.         }
  1036.  
  1037.         void SetTagName(TagID tagID, const char* szTag)
  1038.         {
  1039.                 if (!IsValidTagID(tagID))
  1040.                         return;
  1041.  
  1042.                 m_tags[tagID].m_name.SetByString(szTag);
  1043.         }
  1044.  
  1045.         void SetTagGroup(TagID tagID, TagGroupID groupID)
  1046.         {
  1047.                 if (!IsValidTagID(tagID))
  1048.                         return;
  1049.  
  1050.                 m_tags[tagID].m_groupID = groupID;
  1051.         }
  1052.  
  1053.         template<typename T>
  1054.         bool TagListToIntegerFlags(const char* tagList, T& tagStateInteger) const
  1055.         {
  1056.                 STagState<sizeof(T)> tagState;
  1057.  
  1058.                 bool ret = TagListToFlags(tagList, tagState);
  1059.  
  1060.                 tagState.GetToInteger(tagStateInteger);
  1061.  
  1062.                 return ret;
  1063.         }
  1064.  
  1065.         bool TagListToFlags(const char* tagList, STagStateBase tagState, bool append = false, bool verbose = true) const
  1066.         {
  1067.                 bool success = true;
  1068.                 if (!append)
  1069.                 {
  1070.                         tagState.Clear();
  1071.                 }
  1072.  
  1073.                 if (tagList && (tagList[0] != '\0'))
  1074.                 {
  1075.                         const char* cur = tagList;
  1076.                         const char* nxt = strstr(cur, "+");
  1077.                         char tagBuffer[128];
  1078.                         while (nxt)
  1079.                         {
  1080.                                 cry_strcpy(tagBuffer, cur, (size_t)(nxt - cur));
  1081.                                 int tag = Find(tagBuffer);
  1082.                                 if (tag < 0)
  1083.                                 {
  1084.                                         if (verbose)
  1085.                                         {
  1086.                                                 CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_ERROR, "[TagListToFlags] Invalid tag '%s'", tagBuffer);
  1087.                                         }
  1088.                                         success = false;
  1089.                                 }
  1090.                                 else
  1091.                                 {
  1092.                                         tagState.Set(m_defData.tagMasks[tag], true);
  1093.                                 }
  1094.  
  1095.                                 cur = nxt + 1;
  1096.                                 nxt = strstr(nxt + 1, "+");
  1097.                         }
  1098.  
  1099.                         cry_strcpy(tagBuffer, cur);
  1100.                         TagID tag = Find(tagBuffer);
  1101.                         if (tag == TAG_ID_INVALID)
  1102.                         {
  1103.                                 if (verbose)
  1104.                                 {
  1105.                                         CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_ERROR, "[TagListToFlags] Invalid tag '%s'", tagBuffer);
  1106.                                 }
  1107.                                 success = false;
  1108.                         }
  1109.                         else
  1110.                         {
  1111.                                 tagState.Set(m_defData.tagMasks[tag], true);
  1112.                         }
  1113.                 }
  1114.  
  1115.                 return success;
  1116.         }
  1117.  
  1118.         template<typename T>
  1119.         bool IsGroupSet(const T& state, const TagGroupID groupID) const
  1120.         {
  1121.                 CRY_ASSERT(IsValidTagGroupID(groupID));
  1122.                 if (!IsValidTagGroupID(groupID))
  1123.                         return false;
  1124.  
  1125.                 return state.AreAnySet(m_defData.groupMasks[groupID]);
  1126.         }
  1127.  
  1128.         TagID GetTagInGroup(const STagStateBase& state, const TagGroupID& groupID) const
  1129.         {
  1130.                 CRY_ASSERT(IsValidTagGroupID(groupID));
  1131.                 if (!IsValidTagGroupID(groupID))
  1132.                         return TAG_ID_INVALID;
  1133.  
  1134.                 const uint8 groupMask = state & m_defData.groupMasks[groupID];
  1135.                 const TagID numTags = m_tags.size();
  1136.                 for (TagID itTags = 0; itTags < numTags; ++itTags)
  1137.                 {
  1138.                         const STag& tag = m_tags[itTags];
  1139.                         const STagMask& tagMask = m_defData.tagMasks[itTags];
  1140.                         if ((tag.m_groupID == groupID) && (groupMask == tagMask.mask))
  1141.                         {
  1142.                                 return itTags;
  1143.                         }
  1144.                 }
  1145.                 return TAG_ID_INVALID;
  1146.         }
  1147.  
  1148.         void SetGroup(STagStateBase state, const TagGroupID groupID, const TagID tagID) const
  1149.         {
  1150.                 CRY_ASSERT(IsValidTagGroupID(groupID));
  1151.                 if (!IsValidTagGroupID(groupID))
  1152.                         return;
  1153.  
  1154.                 const STagMask& groupMask = m_defData.groupMasks[groupID];
  1155.                 state.Set(groupMask, false);
  1156.  
  1157.                 if (IsValidTagID(tagID))
  1158.                 {
  1159.                         const STag& tag = m_tags[tagID];
  1160.                         CRY_ASSERT(tag.m_groupID == groupID);
  1161.                         if (tag.m_groupID != groupID)
  1162.                                 return;
  1163.  
  1164.                         state.Set(m_defData.tagMasks[tagID], true);
  1165.                 }
  1166.         }
  1167.  
  1168.         template<typename T>
  1169.         void ClearGroup(T& state, const TagGroupID groupID) const
  1170.         {
  1171.                 CRY_ASSERT(IsValidTagGroupID(groupID));
  1172.                 if (!IsValidTagGroupID(groupID))
  1173.                         return;
  1174.  
  1175.                 state.Set(m_defData.groupMasks[groupID], false);
  1176.         }
  1177.  
  1178.         template<typename T>
  1179.         bool IsSet(const T& state, const TagID tagID) const
  1180.         {
  1181.                 if (!IsValidTagID(tagID))
  1182.                         return false;
  1183.  
  1184.                 return IsSetInternal(state, tagID);
  1185.         }
  1186.  
  1187.         template<typename T>
  1188.         void Set(T& state, const TagID tagID, bool set) const
  1189.         {
  1190.                 if (!IsValidTagID(tagID))
  1191.                         return;
  1192.  
  1193.                 const STag& tag = m_tags[tagID];
  1194.                 const STagMask& tagMask = m_defData.tagMasks[tagID];
  1195.  
  1196.                 if (tag.m_groupID != GROUP_ID_NONE)
  1197.                 {
  1198.                         const STagMask& groupMask = m_defData.groupMasks[tag.m_groupID];
  1199.  
  1200.                         const bool isSet = state.IsSet(groupMask, tagMask);
  1201.  
  1202.                         if (isSet != set)
  1203.                         {
  1204.                                 state.Set(groupMask, false);
  1205.  
  1206.                                 if (set)
  1207.                                 {
  1208.                                         state.Set(tagMask, true);
  1209.                                 }
  1210.                         }
  1211.                 }
  1212.                 else
  1213.                 {
  1214.                         state.Set(tagMask, set);
  1215.                 }
  1216.         }
  1217.  
  1218.         //-----------------------------------------------------------------
  1219.         // Returns a tagState which has set bits for all the tags
  1220.         // that are also set in the passed in tagDef
  1221.         //-----------------------------------------------------------------
  1222.         TagState GetSharedTags(const CTagDefinition& tagDef) const
  1223.         {
  1224.                 const TagGroupID numGroups = (TagGroupID)m_tagGroups.size();
  1225.                 TagState ret;
  1226.                 ret.Clear();
  1227.                 for (TagGroupID i = 0; i < numGroups; i++)
  1228.                 {
  1229.                         if (tagDef.FindGroup(m_tagGroups[i].m_name.crc) != GROUP_ID_NONE)
  1230.                         {
  1231.                                 ret.Set(m_defData.groupMasks[i], true);
  1232.                         }
  1233.                 }
  1234.  
  1235.                 const uint32 numTags = GetNum();
  1236.                 for (uint32 i = 0; i < numTags; i++)
  1237.                 {
  1238.                         if ((m_tags[i].m_groupID == GROUP_ID_NONE) && (tagDef.Find(m_tags[i].m_name.crc) != TAG_ID_INVALID))
  1239.                         {
  1240.                                 ret.Set(m_defData.tagMasks[i], true);
  1241.                         }
  1242.                 }
  1243.  
  1244.                 return ret;
  1245.         }
  1246.  
  1247.         // Returns the union of the tags in a and b.
  1248.         // When a and b contain different tags within the same tag group,
  1249.         // b gets precedence.
  1250.         TagState GetUnion(const STagStateBase& a, const STagStateBase& b) const
  1251.         {
  1252.                 TagState ret = a;
  1253.                 STagStateBase retBase = ret;
  1254.  
  1255.                 const TagGroupID numGroups = (TagGroupID)m_tagGroups.size();
  1256.                 for (TagGroupID i = 0; i < numGroups; i++)
  1257.                 {
  1258.                         const STagMask& groupMask = m_defData.groupMasks[i];
  1259.                         const bool aSet = a.AreAnySet(groupMask);
  1260.                         const bool bSet = b.AreAnySet(groupMask);
  1261.                         if (aSet && bSet)
  1262.                         {
  1263.                                 retBase.Set(groupMask, false);
  1264.                         }
  1265.                 }
  1266.  
  1267.                 retBase |= b;
  1268.  
  1269.                 return ret;
  1270.         }
  1271.  
  1272.         TagState GetIntersection(const STagStateBase& a, const STagStateBase& b) const
  1273.         {
  1274.                 TagState ret = a;
  1275.                 STagStateBase retBase = ret;
  1276.  
  1277.                 const TagGroupID numGroups = (TagGroupID)m_tagGroups.size();
  1278.                 for (TagGroupID i = 0; i < numGroups; i++)
  1279.                 {
  1280.                         const STagMask& groupMask = m_defData.groupMasks[i];
  1281.                         if ((a & groupMask) != (b & groupMask))
  1282.                                 retBase.Set(groupMask, false);
  1283.                 }
  1284.  
  1285.                 retBase &= b;
  1286.  
  1287.                 return ret;
  1288.         }
  1289.  
  1290.         // Returns a - b (all tags set in a which are not set in b)
  1291.         //
  1292.         // Set wipeOverlappedGroups to clear any groups that have a tag set in b.
  1293.         TagState GetDifference(const STagStateBase& a, const STagStateBase& b, const bool wipeOverlappedGroups = false) const
  1294.         {
  1295.                 TagState clearMaskB;
  1296.                 if (wipeOverlappedGroups)
  1297.                 {
  1298.                         clearMaskB = m_defData.GenerateMask(b);
  1299.                 }
  1300.                 else
  1301.                 {
  1302.                         const TagGroupID numGroups = (TagGroupID)m_tagGroups.size();
  1303.                         clearMaskB = b;
  1304.                         for (TagGroupID i = 0; i < numGroups; i++)
  1305.                         {
  1306.                                 const STagMask& groupMask = m_defData.groupMasks[i];
  1307.                                 if (!a.IsSame(b, groupMask))
  1308.                                 {
  1309.                                         clearMaskB.Set(groupMask, false);
  1310.                                 }
  1311.                         }
  1312.                 }
  1313.  
  1314.                 TagState ret;
  1315.                 STagStateBase retBase = ret;
  1316.                 retBase.SetDifference(a, clearMaskB);
  1317.  
  1318.                 return ret;
  1319.         }
  1320.  
  1321.         ILINE TagState GenerateMask(const STagStateBase& tagState, const STagDefData& defData) const
  1322.         {
  1323.                 return defData.GenerateMask(tagState);
  1324.         }
  1325.  
  1326.         ILINE TagState GenerateMask(const STagStateBase& tagState) const
  1327.         {
  1328.                 return m_defData.GenerateMask(tagState);
  1329.         }
  1330.  
  1331.         ILINE bool Contains(const STagStateBase& compParent, const STagStateBase& compChild, const STagStateBase& comparisonMask) const
  1332.         {
  1333.                 return compParent.Contains(compChild, comparisonMask);
  1334.         }
  1335.  
  1336.         ILINE bool Contains(const STagStateBase& compParent, const STagStateBase& compChild) const
  1337.         {
  1338.                 if (!compParent.Contains(compChild, compChild))
  1339.                 {
  1340.                         //--- Trivial rejection
  1341.                         return false;
  1342.                 }
  1343.                 else
  1344.                 {
  1345.                         TagState comparisonMask = GenerateMask(compChild);
  1346.  
  1347.                         return compParent.Contains(compChild, comparisonMask);//((compParent & comparisonMask) == compChild);
  1348.                 }
  1349.         }
  1350.  
  1351.         ILINE bool Contains(const STagStateBase& compParent, const STagStateBase& compChild, const STagDefData& defData) const
  1352.         {
  1353.                 if (!compParent.Contains(compChild, compChild))
  1354.                 {
  1355.                         //--- Trivial rejection
  1356.                         return false;
  1357.                 }
  1358.                 else
  1359.                 {
  1360.                         TagState comparisonMask = GenerateMask(compChild, defData);
  1361.  
  1362.                         return compParent.Contains(compChild, comparisonMask);
  1363.                 }
  1364.         }
  1365.  
  1366.         uint32 RateTagState(const STagStateBase& tagState, const DynArray<SPriorityCount>* pPriorityTallies = NULL) const
  1367.         {
  1368.                 if (pPriorityTallies == NULL)
  1369.                 {
  1370.                         pPriorityTallies = &m_priorityTallies;
  1371.                 }
  1372.                 const uint32 numPriorities = pPriorityTallies->size();
  1373.  
  1374.                 uint32 score = 0;
  1375.                 const uint32 numTags = GetNum();
  1376.                 for (uint32 i = 0; i < numTags; i++)
  1377.                 {
  1378.                         if (IsSetInternal(tagState, i))
  1379.                         {
  1380.                                 int priority = m_tags[i].m_priority;
  1381.                                 uint32 priorityTally = 1;
  1382.                                 for (uint32 p = 0; (p < numPriorities); p++)
  1383.                                 {
  1384.                                         const SPriorityCount& priorityCount = m_priorityTallies[p];
  1385.  
  1386.                                         if (priority > priorityCount.priority)
  1387.                                         {
  1388.                                                 uint32 newTally = priorityTally * (priorityCount.count + 1);
  1389.                                                 //                                              CRY_ASSERT_MESSAGE(newTally >= priorityTally, "TagState rating overflow - too many distinct priority levels!");
  1390.                                                 priorityTally = newTally;
  1391.                                         }
  1392.                                         else
  1393.                                         {
  1394.                                                 break;
  1395.                                         }
  1396.                                 }
  1397.  
  1398.                                 score += priorityTally;
  1399.                         }
  1400.                 }
  1401.  
  1402.                 return score;
  1403.         }
  1404.  
  1405.         template<typename T, size_t N>
  1406.         void IntegerFlagsToTagList(const T& tagStateInteger, CryStackStringT<char, N>& tagList) const
  1407.         {
  1408.                 STagState<sizeof(T)> tagState;
  1409.                 tagState.SetFromInteger(tagStateInteger);
  1410.  
  1411.                 FlagsToTagList(tagState, tagList);
  1412.         }
  1413.  
  1414.         template<size_t N>
  1415.         void FlagsToTagList(const STagStateBase& tagState, CryStackStringT<char, N>& tagList) const
  1416.         {
  1417.                 const TagID numTags = GetNum();
  1418.                 bool isFirst = true;
  1419.  
  1420.                 tagList.clear();
  1421.                 for (TagID i = 0; i < numTags; i++)
  1422.                 {
  1423.                         if (m_defData.tagMasks[i].mask && IsSetInternal(tagState, i))
  1424.                         {
  1425.                                 const char* tagName = GetTagName(i);
  1426.                                 if (!isFirst)
  1427.                                 {
  1428.                                         tagList += '+';
  1429.                                 }
  1430.                                 isFirst = false;
  1431.                                 tagList += tagName;
  1432.                         }
  1433.                 }
  1434.         }
  1435.  
  1436.         ILINE uint32 GetNumBits() const
  1437.         {
  1438.                 return m_defData.numBits;
  1439.         }
  1440.  
  1441.         ILINE uint32 GetNumBytes() const
  1442.         {
  1443.                 return m_defData.GetNumBytes();
  1444.         }
  1445.  
  1446.         ILINE bool HasTooManyBits() const
  1447.         {
  1448.                 return m_defData.numBits > (sizeof(TagState) << 3);
  1449.         }
  1450.  
  1451.         ILINE const STagDefData& GetDefData() const
  1452.         {
  1453.                 return m_defData;
  1454.         }
  1455.  
  1456.         void CombinePriorities(const CTagDefinition& tagDef, DynArray<SPriorityCount>& combinedPriorities) const
  1457.         {
  1458.                 const uint32 numPriorities1 = m_priorityTallies.size();
  1459.                 const uint32 numPriorities2 = tagDef.m_priorityTallies.size();
  1460.  
  1461.                 std::set<int> combPrioritySet;
  1462.  
  1463.                 for (uint32 i = 0; i < numPriorities1; i++)
  1464.                 {
  1465.                         combPrioritySet.insert(m_priorityTallies[i].priority);
  1466.                 }
  1467.                 for (uint32 i = 0; i < numPriorities2; i++)
  1468.                 {
  1469.                         combPrioritySet.insert(tagDef.m_priorityTallies[i].priority);
  1470.                 }
  1471.  
  1472.                 const uint32 numCombinedPriorities = combPrioritySet.size();
  1473.                 combinedPriorities.resize(numCombinedPriorities);
  1474.                 std::set<int>::iterator iter = combPrioritySet.begin();
  1475.                 for (uint32 i = 0; i < numCombinedPriorities; ++i, ++iter)
  1476.                 {
  1477.                         const int priority = *iter;
  1478.                         SPriorityCount& priorityCount = combinedPriorities[i];
  1479.  
  1480.                         priorityCount.priority = priority;
  1481.                         priorityCount.count = 0;
  1482.  
  1483.                         for (uint32 p = 0; p < numPriorities1; p++)
  1484.                         {
  1485.                                 if (m_priorityTallies[p].priority == priority)
  1486.                                 {
  1487.                                         priorityCount.count += m_priorityTallies[p].count;
  1488.                                         break;
  1489.                                 }
  1490.                         }
  1491.                         for (uint32 p = 0; p < numPriorities2; p++)
  1492.                         {
  1493.                                 if (tagDef.m_priorityTallies[p].priority == priority)
  1494.                                 {
  1495.                                         priorityCount.count += tagDef.m_priorityTallies[p].count;
  1496.                                         break;
  1497.                                 }
  1498.                         }
  1499.                 }
  1500.         }
  1501.  
  1502. private:
  1503.  
  1504.         template<typename T>
  1505.         bool IsSetInternal(const T& state, const TagID tagID) const
  1506.         {
  1507.                 const STag& tag = m_tags[tagID];
  1508.                 if ((tag.m_groupID != GROUP_ID_NONE))
  1509.                 {
  1510.                         return state.IsSet(m_defData.groupMasks[tag.m_groupID], m_defData.tagMasks[tagID]);
  1511.                 }
  1512.                 else
  1513.                 {
  1514.                         return state.IsSet(m_defData.tagMasks[tagID]);
  1515.                 }
  1516.         }
  1517.  
  1518.         void CalculatePriorityTallies()
  1519.         {
  1520.                 std::set<int> priorities;
  1521.                 const int numTags = m_tags.size();
  1522.                 for (TagID tagID = 0; tagID < numTags; tagID++)
  1523.                 {
  1524.                         const STag& tag = m_tags[tagID];
  1525.                         priorities.insert(tag.m_priority);
  1526.                 }
  1527.  
  1528.                 const uint32 numPriorities = priorities.size();
  1529.                 m_priorityTallies.resize(numPriorities);
  1530.                 std::set<int>::iterator iter = priorities.begin();
  1531.                 for (uint32 i = 0; i < numPriorities; ++i, ++iter)
  1532.                 {
  1533.                         const int priority = *iter;
  1534.                         SPriorityCount& priorityCount = m_priorityTallies[i];
  1535.  
  1536.                         priorityCount.priority = priority;
  1537.                         priorityCount.count = 0;
  1538.  
  1539.                         for (TagID tagID = 0; tagID < numTags; tagID++)
  1540.                         {
  1541.                                 const STag& tag = m_tags[tagID];
  1542.                                 if (tag.m_priority == priority)
  1543.                                 {
  1544.                                         priorityCount.count++;
  1545.                                 }
  1546.                         }
  1547.                 }
  1548.         }
  1549.  
  1550.         string                   m_filename;
  1551.         DynArray<STag>           m_tags;
  1552.         DynArray<STagGroup>      m_tagGroups;
  1553.         STagDefData              m_defData;
  1554.         DynArray<SPriorityCount> m_priorityTallies;
  1555.         bool                     m_hasMasks;
  1556. };
  1557.  
  1558. struct SFragTagState
  1559. {
  1560.         explicit SFragTagState(const TagState& _globalTags = TagState(TAG_STATE_EMPTY), const TagState& _fragmentTags = TagState(TAG_STATE_EMPTY))
  1561.                 :
  1562.                 globalTags(_globalTags),
  1563.                 fragmentTags(_fragmentTags)
  1564.         {
  1565.         }
  1566.  
  1567.         bool operator==(const SFragTagState& fragTagState) const
  1568.         {
  1569.                 return (globalTags == fragTagState.globalTags) && (fragmentTags == fragTagState.fragmentTags);
  1570.         }
  1571.         bool operator!=(const SFragTagState& fragTagState) const
  1572.         {
  1573.                 return (globalTags != fragTagState.globalTags) || (fragmentTags != fragTagState.fragmentTags);
  1574.         }
  1575.  
  1576.         TagState globalTags;
  1577.         TagState fragmentTags;
  1578. };
  1579.  
  1580. class CTagState
  1581. {
  1582. public:
  1583.         CTagState(const CTagDefinition& defs, TagState state = TAG_STATE_EMPTY)
  1584.                 :
  1585.                 m_defs(defs),
  1586.                 m_state(state)
  1587.         {
  1588. #ifndef _RELEASE
  1589.                 const size_t maxSupportedBits = sizeof(TagState) * 8;
  1590.                 const size_t definitionBits = defs.GetNumBits();
  1591.                 if (maxSupportedBits < definitionBits)
  1592.                 {
  1593.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "!Number of bits required for tag definition '%s' (%" PRISIZE_T " bits) is greater than %" PRISIZE_T " bits. To fix this, group mutually exclusive tags together, remove unnecessary tags or increase the size of TagState.", defs.GetFilename(), definitionBits, maxSupportedBits);
  1594.                 }
  1595. #endif
  1596.         }
  1597.  
  1598.         void Clear()
  1599.         {
  1600.                 m_state = TAG_STATE_EMPTY;
  1601.         }
  1602.  
  1603.         void SetByCRC(uint32 CRC, bool enable)
  1604.         {
  1605.                 const TagID id = m_defs.Find(CRC);
  1606.                 if (m_defs.IsValidTagID(id))
  1607.                 {
  1608.                         Set(id, enable);
  1609.                 }
  1610.         }
  1611.  
  1612.         void Set(TagID id, bool enable)
  1613.         {
  1614.                 m_defs.Set(m_state, id, enable);
  1615.         }
  1616.  
  1617.         void SetGroup(TagGroupID groupID, TagID tagID)
  1618.         {
  1619.                 m_defs.SetGroup(m_state, groupID, tagID);
  1620.         }
  1621.  
  1622.         void ClearGroup(TagGroupID groupID)
  1623.         {
  1624.                 m_defs.ClearGroup(m_state, groupID);
  1625.         }
  1626.  
  1627.         ILINE bool IsSet(TagID tagID) const
  1628.         {
  1629.                 return m_defs.IsSet(m_state, tagID);
  1630.         }
  1631.  
  1632.         ILINE bool IsGroupSet(TagGroupID tagGroupID) const
  1633.         {
  1634.                 return m_defs.IsGroupSet(m_state, tagGroupID);
  1635.         }
  1636.  
  1637.         ILINE bool Contains(const TagState& comp) const
  1638.         {
  1639.                 return m_defs.Contains(m_state, comp);
  1640.         }
  1641.         ILINE bool Contains(const CTagState& comp) const
  1642.         {
  1643.                 return m_defs.Contains(m_state, comp.m_state);
  1644.         }
  1645.  
  1646.         const TagState& GetMask() const
  1647.         {
  1648.                 return m_state;
  1649.         }
  1650.  
  1651.         const CTagDefinition& GetDef() const
  1652.         {
  1653.                 return m_defs;
  1654.         }
  1655.  
  1656.         CTagState& operator=(const TagState& tagState)
  1657.         {
  1658.                 m_state = tagState;
  1659.                 return *this;
  1660.         }
  1661.  
  1662. private:
  1663.  
  1664.         const CTagDefinition& m_defs;
  1665.         TagState              m_state;
  1666.  
  1667. };
  1668.  
  1669. //--- Just expose this??
  1670. template<typename T>
  1671. class TOptimisedTagSortedList
  1672. {
  1673. public:
  1674.  
  1675.         friend class CAnimationDatabaseManager;
  1676.         friend class CAnimationDatabase;
  1677.         template<typename TFRIEND> friend class TTagSortedList;
  1678.  
  1679.         TOptimisedTagSortedList(uint32 size, uint32 stride)
  1680.                 :
  1681.                 m_pTagDef(NULL),
  1682.                 m_pFragTagDef(NULL),
  1683.                 m_pDefData(NULL),
  1684.                 m_pFragDefData(NULL),
  1685.                 m_size(size),
  1686.                 m_keySize(stride)
  1687.         {
  1688.                 m_keys = new uint8[size * stride];
  1689.                 m_values = new T[size];
  1690.         }
  1691.  
  1692.         ~TOptimisedTagSortedList()
  1693.         {
  1694.                 delete[] m_keys;
  1695.                 delete[] m_values;
  1696.                 delete m_pDefData;
  1697.         }
  1698.  
  1699.         ILINE uint32 Size() const
  1700.         {
  1701.                 return m_size;
  1702.         }
  1703.         ILINE uint32 GetKeySize() const
  1704.         {
  1705.                 return m_keySize;
  1706.         }
  1707.  
  1708.         void GetKey(SFragTagState& fragTagState, uint32 idx) const
  1709.         {
  1710.                 CRY_ASSERT(idx < m_size);
  1711.  
  1712.                 if (idx < m_size)
  1713.                 {
  1714.                         const uint32 numBytesGlobal = m_pDefData->GetNumBytes();
  1715.                         const uint32 numBytesFrag = m_pFragDefData ? m_pFragDefData->GetNumBytes() : 0;
  1716.  
  1717.                         m_pTagDef->UncompressTagState(fragTagState.globalTags, STagStateBase(m_keys + (idx * m_keySize), numBytesGlobal), *m_pDefData);
  1718.                         fragTagState.fragmentTags = STagStateBase(m_keys + (idx * m_keySize) + numBytesGlobal, numBytesFrag);
  1719.                 }
  1720.         }
  1721.  
  1722.         const T* Get(uint32 idx) const
  1723.         {
  1724.                 const uint32 numEntries = m_size;
  1725.                 CRY_ASSERT(idx < numEntries);
  1726.  
  1727.                 if (idx < numEntries)
  1728.                 {
  1729.                         return &m_values[idx];
  1730.                 }
  1731.  
  1732.                 return NULL;
  1733.         }
  1734.  
  1735.         int FindIdx(const SFragTagState& fragTags) const
  1736.         {
  1737.                 const uint32 numEntries = m_size;
  1738.                 const uint32 numBytesGlobal = m_pDefData->GetNumBytes();
  1739.                 const uint32 numBytesFrag = m_pFragDefData ? m_pFragDefData->GetNumBytes() : 0;
  1740.  
  1741.                 TagState compressedGlobalTags;
  1742.                 m_pTagDef->CompressTagState(compressedGlobalTags, fragTags.globalTags, *m_pDefData);
  1743.  
  1744.                 STagStateBase globalTags(m_keys, numBytesGlobal);
  1745.                 STagStateBase fragmentTags(m_keys + numBytesGlobal, numBytesFrag);
  1746.  
  1747.                 for (uint32 i = 0; i < numEntries; i++)
  1748.                 {
  1749.                         if ((globalTags == compressedGlobalTags)
  1750.                             && (fragmentTags == fragTags.fragmentTags))
  1751.                         {
  1752.                                 return i;
  1753.                         }
  1754.  
  1755.                         globalTags.state += m_keySize;
  1756.                         fragmentTags.state += m_keySize;
  1757.                 }
  1758.  
  1759.                 return -1;
  1760.         }
  1761.  
  1762.         const T* Find(const SFragTagState& fragTags) const
  1763.         {
  1764.                 int idx = FindIdx(fragTags);
  1765.  
  1766.                 if (idx >= 0)
  1767.                 {
  1768.                         return &m_values[idx];
  1769.                 }
  1770.  
  1771.                 return NULL;
  1772.         }
  1773.  
  1774.         T* Find(const SFragTagState& fragTags)
  1775.         {
  1776.                 int idx = FindIdx(fragTags);
  1777.  
  1778.                 if (idx >= 0)
  1779.                 {
  1780.                         return &m_values[idx];
  1781.                 }
  1782.  
  1783.                 return NULL;
  1784.         }
  1785.  
  1786.         const T& GetDefault() const
  1787.         {
  1788.                 const uint32 size = m_size;
  1789.                 if (size == 0)
  1790.                 {
  1791.                         CryFatalError("[TTagSortedList] No default in list, this should not happen");
  1792.                 }
  1793.  
  1794.                 return m_values[size - 1];
  1795.         }
  1796.  
  1797.         const T* GetBestMatch(const SFragTagState& fragTags, SFragTagState* pFragTagsMatched = NULL, uint32* pTagSetIdx = NULL) const
  1798.         {
  1799.                 const uint32 numEntries = m_size;
  1800.                 const uint32 numBytesGlobal = m_pDefData->GetNumBytes();
  1801.                 const uint32 numBytesFrag = m_pFragDefData ? m_pFragDefData->GetNumBytes() : NULL;
  1802.  
  1803.                 TagState compressedGlobalTags;
  1804.                 m_pTagDef->CompressTagState(compressedGlobalTags, fragTags.globalTags, *m_pDefData);
  1805.  
  1806.                 STagStateBase globalTags(m_keys, numBytesGlobal);
  1807.                 STagStateBase fragmentTags(m_keys + numBytesGlobal, numBytesFrag);
  1808.  
  1809.                 for (uint32 i = 0; i < numEntries; i++)
  1810.                 {
  1811.                         if (m_pDefData->Contains(compressedGlobalTags, globalTags)
  1812.                             && (!m_pFragDefData || m_pFragDefData->Contains(fragTags.fragmentTags, fragmentTags)))
  1813.                         {
  1814.                                 if (pFragTagsMatched)
  1815.                                 {
  1816.                                         m_pTagDef->UncompressTagState(pFragTagsMatched->globalTags, globalTags, *m_pDefData);
  1817.                                         pFragTagsMatched->fragmentTags = fragmentTags;
  1818.                                 }
  1819.                                 if (pTagSetIdx)
  1820.                                 {
  1821.                                         *pTagSetIdx = i;
  1822.                                 }
  1823.  
  1824.                                 return &m_values[i];
  1825.                         }
  1826.  
  1827.                         globalTags.state += m_keySize;
  1828.                         fragmentTags.state += m_keySize;
  1829.                 }
  1830.  
  1831.                 return NULL;
  1832.         }
  1833.  
  1834.         const T* GetBestMatch(const SFragTagState& fragTags, const STagStateBase& requiredTagState, SFragTagState* pFragTagsMatched = NULL, uint32* pTagSetIdx = NULL) const
  1835.         {
  1836.                 if (m_pTagDef->CanRepresent(requiredTagState, *m_pDefData))
  1837.                 {
  1838.                         const uint32 numEntries = m_size;
  1839.                         const uint32 numBytesGlobal = m_pDefData->GetNumBytes();
  1840.                         const uint32 numBytesFrag = m_pFragDefData ? m_pFragDefData->GetNumBytes() : 0;
  1841.  
  1842.                         TagState compressedGlobalTags, compressedReqTags;
  1843.                         m_pTagDef->CompressTagState(compressedGlobalTags, fragTags.globalTags, *m_pDefData);
  1844.                         m_pTagDef->CompressTagState(compressedReqTags, requiredTagState, *m_pDefData);
  1845.  
  1846.                         STagStateBase globalTags(m_keys, numBytesGlobal);
  1847.                         STagStateBase fragmentTags(m_keys + numBytesGlobal, numBytesFrag);
  1848.  
  1849.                         const TagState requiredComparisonMask = m_pDefData->GenerateMask(compressedReqTags);
  1850.  
  1851.                         for (uint32 i = 0; i < numEntries; i++)
  1852.                         {
  1853.                                 if (m_pDefData->Contains(globalTags, compressedReqTags, requiredComparisonMask)
  1854.                                     && m_pDefData->Contains(compressedGlobalTags, globalTags)
  1855.                                     && (!m_pFragDefData || m_pFragDefData->Contains(fragTags.fragmentTags, fragmentTags)))
  1856.                                 {
  1857.                                         if (pFragTagsMatched)
  1858.                                         {
  1859.                                                 m_pTagDef->UncompressTagState(pFragTagsMatched->globalTags, globalTags, *m_pDefData);
  1860.                                                 pFragTagsMatched->fragmentTags = fragmentTags;
  1861.                                         }
  1862.                                         if (pTagSetIdx)
  1863.                                         {
  1864.                                                 *pTagSetIdx = i;
  1865.                                         }
  1866.  
  1867.                                         return &m_values[i];
  1868.                                 }
  1869.  
  1870.                                 globalTags.state += m_keySize;
  1871.                                 fragmentTags.state += m_keySize;
  1872.                         }
  1873.                 }
  1874.  
  1875.                 return NULL;
  1876.         }
  1877.  
  1878.         ILINE const CTagDefinition::STagDefData* GetDefData() const
  1879.         {
  1880.                 return m_pDefData;
  1881.         }
  1882.         ILINE const CTagDefinition::STagDefData* GetFragDefData() const
  1883.         {
  1884.                 return m_pFragDefData;
  1885.         }
  1886.  
  1887. private:
  1888.  
  1889.         const CTagDefinition*              m_pTagDef;
  1890.         const CTagDefinition*              m_pFragTagDef;
  1891.         const CTagDefinition::STagDefData* m_pDefData;
  1892.         const CTagDefinition::STagDefData* m_pFragDefData;
  1893.  
  1894.         uint8*                             m_keys;
  1895.         T* m_values;
  1896.         uint32                             m_size;
  1897.         uint32                             m_keySize;
  1898. };
  1899.  
  1900. template<typename T>
  1901. class TTagSortedList
  1902. {
  1903. public:
  1904.  
  1905.         friend class CAnimationDatabaseManager;
  1906.         friend class CAnimationDatabase;
  1907.  
  1908.         struct SSortStruct
  1909.         {
  1910.                 uint32 priority;
  1911.                 uint16 originalIdx;
  1912.  
  1913.                 bool operator<(const SSortStruct& compare) const
  1914.                 {
  1915.                         return priority > compare.priority;
  1916.                 }
  1917.         };
  1918.  
  1919.         TTagSortedList<T>()
  1920.         {
  1921.         }
  1922.  
  1923.         ~TTagSortedList<T>()
  1924.         {
  1925.         }
  1926.  
  1927.         T& Insert(const SFragTagState& fragTags, const T& data)
  1928.         {
  1929.                 const uint32 numEntries = m_keys.size();
  1930.                 for (uint32 i = 0; i < numEntries; i++)
  1931.                 {
  1932.                         if (m_keys[i] == fragTags)
  1933.                         {
  1934.                                 m_values[i] = data;
  1935.                                 return m_values[i];
  1936.                         }
  1937.                 }
  1938.  
  1939.                 Resize(numEntries + 1);
  1940.                 m_keys[numEntries] = fragTags;
  1941.                 m_values[numEntries] = data;
  1942.                 return m_values[numEntries];
  1943.         }
  1944.  
  1945.         void Erase(uint32 idx)
  1946.         {
  1947.                 const uint32 numEntries = m_keys.size();
  1948.                 CRY_ASSERT(idx < numEntries);
  1949.  
  1950.                 if (idx < numEntries)
  1951.                 {
  1952.                         m_keys.erase(m_keys.begin() + idx);
  1953.                         m_values.erase(m_values.begin() + idx);
  1954.                 }
  1955.         }
  1956.  
  1957.         void Resize(const uint32 newSize)
  1958.         {
  1959.                 if (newSize != m_keys.size())
  1960.                 {
  1961.                         m_keys.resize(newSize);
  1962.                         m_values.resize(newSize);
  1963.                 }
  1964.         }
  1965.  
  1966.         uint32 Size() const
  1967.         {
  1968.                 return m_keys.size();
  1969.         }
  1970.  
  1971.         const T* Get(uint32 idx) const
  1972.         {
  1973.                 const uint32 numEntries = m_keys.size();
  1974.                 CRY_ASSERT(idx < numEntries);
  1975.  
  1976.                 if (idx < numEntries)
  1977.                 {
  1978.                         return &m_values[idx];
  1979.                 }
  1980.  
  1981.                 return NULL;
  1982.         }
  1983.  
  1984.         int FindIdx(const SFragTagState& fragTags) const
  1985.         {
  1986.                 const uint32 numEntries = m_keys.size();
  1987.                 for (uint32 i = 0; i < numEntries; i++)
  1988.                 {
  1989.                         if (m_keys[i] == fragTags)
  1990.                         {
  1991.                                 return i;
  1992.                         }
  1993.                 }
  1994.  
  1995.                 return -1;
  1996.         }
  1997.  
  1998.         const T* Find(const SFragTagState& fragTags) const
  1999.         {
  2000.                 int idx = FindIdx(fragTags);
  2001.  
  2002.                 if (idx >= 0)
  2003.                 {
  2004.                         return &m_values[idx];
  2005.                 }
  2006.  
  2007.                 return NULL;
  2008.         }
  2009.  
  2010.         T* Find(const SFragTagState& fragTags)
  2011.         {
  2012.                 int idx = FindIdx(fragTags);
  2013.  
  2014.                 if (idx >= 0)
  2015.                 {
  2016.                         return &m_values[idx];
  2017.                 }
  2018.  
  2019.                 return NULL;
  2020.         }
  2021.  
  2022.         void Sort(const CTagDefinition& tagDefs, const CTagDefinition* pFragTagDefs)
  2023.         {
  2024.                 DynArray<CTagDefinition::SPriorityCount>* pCombinedPriorities = NULL;
  2025.  
  2026.                 if (pFragTagDefs)
  2027.                 {
  2028.                         pCombinedPriorities = new DynArray<CTagDefinition::SPriorityCount>();
  2029.                         tagDefs.CombinePriorities(*pFragTagDefs, *pCombinedPriorities);
  2030.                 }
  2031.  
  2032.                 const uint32 size = m_keys.size();
  2033.                 SSortStruct* pSortKeys = new SSortStruct[size];
  2034.                 for (uint32 i = 0; i < size; i++)
  2035.                 {
  2036.                         pSortKeys[i].priority = tagDefs.RateTagState(m_keys[i].globalTags, pCombinedPriorities);
  2037.                         pSortKeys[i].originalIdx = i;
  2038.                 }
  2039.                 if (pFragTagDefs)
  2040.                 {
  2041.                         for (uint32 i = 0; i < size; i++)
  2042.                         {
  2043.                                 pSortKeys[i].priority += pFragTagDefs->RateTagState(m_keys[i].fragmentTags, pCombinedPriorities);
  2044.                         }
  2045.                 }
  2046.  
  2047.                 delete(pCombinedPriorities);
  2048.  
  2049.                 std::stable_sort(pSortKeys, pSortKeys + size);
  2050.  
  2051.                 for (uint32 i = 0; i < size; i++)
  2052.                 {
  2053.                         const uint32 originalIdx = pSortKeys[i].originalIdx;
  2054.                         if (originalIdx != i)
  2055.                         {
  2056.                                 SFragTagState bufferedTS = m_keys[i];
  2057.                                 T bufferedValue = m_values[i];
  2058.                                 m_keys[i] = m_keys[originalIdx];
  2059.                                 m_values[i] = m_values[originalIdx];
  2060.                                 m_keys[originalIdx] = bufferedTS;
  2061.                                 m_values[originalIdx] = bufferedValue;
  2062.  
  2063.                                 for (uint32 k = i + 1; k < size; k++)
  2064.                                 {
  2065.                                         if (pSortKeys[k].originalIdx == i)
  2066.                                         {
  2067.                                                 pSortKeys[k].originalIdx = originalIdx;
  2068.                                                 break;
  2069.                                         }
  2070.                                 }
  2071.                         }
  2072.                 }
  2073.  
  2074.                 delete[] pSortKeys;
  2075.         }
  2076.  
  2077.         TOptimisedTagSortedList<T>* Compress(const CTagDefinition& tagDef, const CTagDefinition* pFragTagDef = NULL) const
  2078.         {
  2079.                 const uint32 size = m_keys.size();
  2080.  
  2081.                 //--- Assess usage
  2082.                 SFragTagState usedTags;
  2083.                 QueryUsedTags(usedTags, &tagDef, NULL);
  2084.  
  2085.                 //--- Generate buffers
  2086.                 CTagDefinition::STagDefData* pTagDefData = new CTagDefinition::STagDefData();
  2087.                 TagState tagStateFilter(usedTags.globalTags);
  2088.                 tagDef.AssignBits(*pTagDefData, tagStateFilter);
  2089.                 const CTagDefinition::STagDefData* pFragData = (pFragTagDef ? &pFragTagDef->GetDefData() : NULL);
  2090.  
  2091.                 const uint32 bytesGlobal = pTagDefData->GetNumBytes();
  2092.                 const uint32 bytesFrag = (pFragData ? pFragData->GetNumBytes() : 0);
  2093.                 const uint32 bytesTotal = bytesGlobal + bytesFrag;
  2094.  
  2095.                 //--- Create & initialise new optimised DB
  2096.                 TOptimisedTagSortedList<T>* pOptimisedList = new TOptimisedTagSortedList<T>(size, bytesTotal);
  2097.                 pOptimisedList->m_pTagDef = &tagDef;
  2098.                 pOptimisedList->m_pDefData = pTagDefData;
  2099.                 pOptimisedList->m_pFragTagDef = pFragTagDef;
  2100.                 pOptimisedList->m_pFragDefData = pFragData;
  2101.  
  2102.                 STagStateBase globalKeys = STagStateBase(pOptimisedList->m_keys, bytesGlobal);
  2103.                 uint8* keyBuffer = pOptimisedList->m_keys;
  2104.                 T* valueBuffer = pOptimisedList->m_values;
  2105.  
  2106.                 //--- Assign the globalTags & data
  2107.                 for (uint32 i = 0; i < size; i++)
  2108.                 {
  2109.                         tagDef.CompressTagState(globalKeys, m_keys[i].globalTags, *pTagDefData);
  2110.                         valueBuffer[i] = m_values[i];
  2111.                         globalKeys.state += bytesTotal;
  2112.                 }
  2113.  
  2114.                 //--- Now optionally assign the fragTags
  2115.                 if (pFragTagDef)
  2116.                 {
  2117.                         STagStateBase fragKeys = STagStateBase(pOptimisedList->m_keys + bytesGlobal, bytesFrag);
  2118.  
  2119.                         for (uint32 i = 0; i < size; i++)
  2120.                         {
  2121.                                 pFragTagDef->CompressTagState(fragKeys, m_keys[i].fragmentTags, *pFragData);
  2122.                                 fragKeys.state += bytesTotal;
  2123.                         }
  2124.                 }
  2125.  
  2126.                 return pOptimisedList;
  2127.         }
  2128.  
  2129.         const T& GetDefault() const
  2130.         {
  2131.                 const uint32 size = m_keys.size();
  2132.                 if (size == 0)
  2133.                 {
  2134.                         CryFatalError("[TTagSortedList] No default in list, this should not happen");
  2135.                 }
  2136.  
  2137.                 return m_values[size - 1];
  2138.         }
  2139.  
  2140.         const T* GetBestMatch(const SFragTagState& fragTags, const CTagDefinition* pGlobalTagDef, const CTagDefinition* pFragTagDef, SFragTagState* pMatchedFragTags = NULL, uint32* pTagSetIdx = NULL) const
  2141.         {
  2142.                 STagStateBase tagGlobal((const STagStateBase)(fragTags.globalTags));
  2143.                 STagStateBase tagFragment((const STagStateBase)(fragTags.fragmentTags));
  2144.  
  2145.                 const uint32 numEntries = m_keys.size();
  2146.                 for (uint32 i = 0; i < numEntries; i++)
  2147.                 {
  2148.                         const SFragTagState& fragTagState = m_keys[i];
  2149.  
  2150.                         if (pGlobalTagDef->Contains(fragTags.globalTags, fragTagState.globalTags)
  2151.                             && (!pFragTagDef || pFragTagDef->Contains(fragTags.fragmentTags, fragTagState.fragmentTags)))
  2152.                         {
  2153.                                 if (pMatchedFragTags)
  2154.                                 {
  2155.                                         *pMatchedFragTags = fragTagState;
  2156.                                 }
  2157.                                 if (pTagSetIdx)
  2158.                                 {
  2159.                                         *pTagSetIdx = i;
  2160.                                 }
  2161.                                 return &m_values[i];
  2162.                         }
  2163.                 }
  2164.  
  2165.                 if (pTagSetIdx)
  2166.                 {
  2167.                         *pTagSetIdx = TAG_SET_IDX_INVALID;
  2168.                 }
  2169.                 return NULL;
  2170.         }
  2171.  
  2172.         const T* GetBestMatch(const SFragTagState& fragTags, const TagState& requiredTagState, const CTagDefinition* pGlobalTagDef, const CTagDefinition* pFragTagDef, SFragTagState* pMatchedFragTags = NULL) const
  2173.         {
  2174.                 TagState requiredComparisonMask = pGlobalTagDef->GenerateMask(requiredTagState);
  2175.  
  2176.                 const uint32 numEntries = m_keys.size();
  2177.                 for (uint32 i = 0; i < numEntries; i++)
  2178.                 {
  2179.                         const SFragTagState& fragTagState = m_keys[i];
  2180.  
  2181.                         if (pGlobalTagDef->Contains(fragTagState.globalTags, requiredTagState, requiredComparisonMask)
  2182.                             && pGlobalTagDef->Contains(fragTags.globalTags, fragTagState.globalTags)
  2183.                             && (!pFragTagDef || pFragTagDef->Contains(fragTags.fragmentTags, fragTagState.fragmentTags)))
  2184.                         {
  2185.                                 if (pMatchedFragTags)
  2186.                                 {
  2187.                                         *pMatchedFragTags = fragTagState;
  2188.                                 }
  2189.                                 return &m_values[i];
  2190.                         }
  2191.                 }
  2192.  
  2193.                 return NULL;
  2194.         }
  2195.  
  2196.         void QueryUsedTags(SFragTagState& usedTags, const CTagDefinition* pGlobalTagDef, const CTagDefinition* pFragTagDef) const
  2197.         {
  2198.                 usedTags.globalTags.Clear();
  2199.                 usedTags.fragmentTags.Clear();
  2200.  
  2201.                 const uint32 numEntries = m_keys.size();
  2202.  
  2203.                 for (uint32 t = 0; t < numEntries; t++)
  2204.                 {
  2205.                         const SFragTagState& tagState = m_keys[t];
  2206.  
  2207.                         usedTags.globalTags = pGlobalTagDef->GetUnion(usedTags.globalTags, tagState.globalTags);
  2208.                         if (pFragTagDef)
  2209.                         {
  2210.                                 usedTags.fragmentTags = pFragTagDef->GetUnion(usedTags.fragmentTags, tagState.fragmentTags);
  2211.                         }
  2212.                 }
  2213.  
  2214.                 //--- Expand to include whole group in mask
  2215.                 usedTags.globalTags = pGlobalTagDef->GenerateMask(usedTags.globalTags);
  2216.                 if (pFragTagDef)
  2217.                 {
  2218.                         usedTags.fragmentTags = pFragTagDef->GenerateMask(usedTags.fragmentTags);
  2219.                 }
  2220.         }
  2221.  
  2222.         void QueryUsedTags(SFragTagState& usedTags, const SFragTagState& filter, const CTagDefinition* pGlobalTagDef, const CTagDefinition* pFragTagDef) const
  2223.         {
  2224.                 usedTags.globalTags.Clear();
  2225.                 usedTags.fragmentTags.Clear();
  2226.  
  2227.                 const uint32 numEntries = m_keys.size();
  2228.  
  2229.                 TagState filterGroupMaskGlobal = pGlobalTagDef->GenerateMask(filter.globalTags);
  2230.                 TagState filterGroupMaskFrag;
  2231.                 if (pFragTagDef)
  2232.                 {
  2233.                         filterGroupMaskFrag = pFragTagDef->GenerateMask(filter.fragmentTags);
  2234.                 }
  2235.                 else
  2236.                 {
  2237.                         filterGroupMaskFrag.Clear();
  2238.                 }
  2239.  
  2240.                 //--- The best pure match is the last one we should consider
  2241.                 uint32 matchID;
  2242.                 if (!GetBestMatch(filter, pGlobalTagDef, pFragTagDef, NULL, &matchID))
  2243.                 {
  2244.                         matchID = numEntries;
  2245.                 }
  2246.  
  2247.                 for (uint32 t = 0; t < matchID; t++)
  2248.                 {
  2249.                         const SFragTagState& tagState = m_keys[t];
  2250.  
  2251.                         const TagState groupMaskGlobal = pGlobalTagDef->GenerateMask(tagState.globalTags);
  2252.                         const TagState combinedGlobal(filterGroupMaskGlobal & groupMaskGlobal);
  2253.                         const TagState filterTagsAdjusted(filter.globalTags & combinedGlobal);
  2254.                         const TagState tagsAdjusted(tagState.globalTags & combinedGlobal);
  2255.  
  2256.                         bool valid = false;
  2257.                         if (filterTagsAdjusted == tagsAdjusted)
  2258.                         {
  2259.                                 if (pFragTagDef)
  2260.                                 {
  2261.                                         const TagState groupMaskFrag = pFragTagDef->GenerateMask(tagState.fragmentTags);
  2262.                                         const TagState combinedFrag(filterGroupMaskFrag & groupMaskFrag);
  2263.                                         const TagState filterFragTagAdjusted(filter.fragmentTags & combinedFrag);
  2264.                                         const TagState fragTagsAdjusted(tagState.fragmentTags & combinedFrag);
  2265.  
  2266.                                         valid = (filterFragTagAdjusted == fragTagsAdjusted);
  2267.                                 }
  2268.                                 else
  2269.                                 {
  2270.                                         valid = true;
  2271.                                 }
  2272.                         }
  2273.  
  2274.                         if (valid)
  2275.                         {
  2276.                                 usedTags.globalTags = pGlobalTagDef->GetUnion(usedTags.globalTags, tagState.globalTags);
  2277.                                 if (pFragTagDef)
  2278.                                 {
  2279.                                         usedTags.fragmentTags = pFragTagDef->GetUnion(usedTags.fragmentTags, tagState.fragmentTags);
  2280.                                 }
  2281.                         }
  2282.                 }
  2283.  
  2284.                 //--- Expand to include whole group in mask
  2285.                 usedTags.globalTags = pGlobalTagDef->GenerateMask(usedTags.globalTags);
  2286.                 if (pFragTagDef)
  2287.                 {
  2288.                         usedTags.fragmentTags = pFragTagDef->GenerateMask(usedTags.fragmentTags);
  2289.                 }
  2290.         }
  2291.  
  2292. private:
  2293.  
  2294.         DynArray<SFragTagState> m_keys;
  2295.         DynArray<T>             m_values;
  2296. };
  2297.  
  2298. #endif //__I_CRY_MANNEQUIN_TAG_DEFS_H__
  2299.  
downloadICryMannequinTagDefs.h Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top