BVB Source Codes

CRYENGINE Show AnimationDatabaseManager.cpp Source code

Return Download CRYENGINE: download AnimationDatabaseManager.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. //
  4. ////////////////////////////////////////////////////////////////////////////
  5. #include "StdAfx.h"
  6. #include "AnimationDatabaseManager.h"
  7. #include <CryCore/TypeInfo_impl.h>
  8. #include "Xml/TagDefinitionXml.h"
  9. #include "ProceduralClipConversion.h"
  10. #include "MannequinUtils.h"
  11.  
  12. #include "Mannequin/Serialization.h"
  13. #include <CrySerialization/IArchiveHost.h>
  14. #include <CrySystem/File/IResourceManager.h>
  15.  
  16. const string MANNEQUIN_FOLDER = "Animations/Mannequin/ADB/";
  17.  
  18. CAnimationDatabaseManager* CAnimationDatabaseManager::s_Instance = NULL;
  19.  
  20. static void NormalizeFilename(char (&outFilename)[DEF_PATH_LENGTH], const char* inFilename)
  21. {
  22.         cry_strcpy(outFilename, DEF_PATH_LENGTH, inFilename);
  23.         for (size_t i = 0; outFilename[i]; ++i)
  24.         {
  25.                 if (outFilename[i] == '\\')
  26.                         outFilename[i] = '/';
  27.         }
  28. }
  29.  
  30. static bool IsValidNameIdentifier(const char* const name)
  31. {
  32.         const char* cit = name;
  33.         if (!cit)
  34.         {
  35.                 return false;
  36.         }
  37.  
  38.         if (!isalpha(static_cast<unsigned char>(*cit)) && !(*cit == '_'))
  39.         {
  40.                 return false;
  41.         }
  42.         cit++;
  43.  
  44.         while (*cit)
  45.         {
  46.                 const char c = *cit;
  47.                 if (!isalnum(static_cast<unsigned char>(c)) && !(c == '_'))
  48.                 {
  49.                         return false;
  50.                 }
  51.                 cit++;
  52.         }
  53.  
  54.         return true;
  55. }
  56.  
  57. CAnimationDatabaseLibrary::CAnimationDatabaseLibrary()
  58. {
  59.         const char* ANIM_FLAGS[] =
  60.         {
  61.                 "ManualUpdate",
  62.                 "Loop",
  63.                 "RepeatLast",
  64.                 "TimeWarping",
  65.                 "StartAtKeyTime",
  66.                 "StartAfter",
  67.                 "Idle2Move",
  68.                 "Move2Idle",
  69.                 "AllowRestart",
  70.                 "Sample30Hz",
  71.                 "DisableMultilayer",
  72.                 "ForceSkelUpdate",
  73.                 "TrackView",
  74.                 "RemoveFromFIFO",
  75.                 "FullRootPriority",
  76.                 "ForceTransitionToAnim"
  77.         };
  78.         const int NUM_ANIM_FLAGS = CRY_ARRAY_COUNT(ANIM_FLAGS);
  79.  
  80.         for (int i = 0; i < NUM_ANIM_FLAGS; i++)
  81.         {
  82.                 m_animFlags.AddTag(ANIM_FLAGS[i]);
  83.         }
  84.  
  85.         m_animFlags.AssignBits();
  86.  
  87.         const char* TRANSITION_FLAGS[] =
  88.         {
  89.                 "Cyclic",
  90.                 "CycleLocked",
  91.                 "Outro"
  92.         };
  93.         const int NUM_TRANSITION_FLAGS = CRY_ARRAY_COUNT(TRANSITION_FLAGS);
  94.         for (int i = 0; i < NUM_TRANSITION_FLAGS; i++)
  95.         {
  96.                 m_transitionFlags.AddTag(TRANSITION_FLAGS[i]);
  97.         }
  98.  
  99.         m_transitionFlags.AssignBits();
  100. }
  101.  
  102. CAnimationDatabaseLibrary::~CAnimationDatabaseLibrary()
  103. {
  104. }
  105.  
  106. void CAnimationDatabaseLibrary::Insert(uint32 nCrc, CAnimationDatabase* pDb)
  107. {
  108.         m_databases.insert(std::make_pair(nCrc, pDb));
  109. }
  110.  
  111. CAnimationDatabaseLibrary::THandle CAnimationDatabaseLibrary::LoadResource(const char* name, uint32 nFlags)
  112. {
  113.         THandle ret = TryOpenResource(name, nFlags);
  114.  
  115.         if (!ret)
  116.         {
  117.                 CreateResource(ret, name, nFlags);
  118.                 if (ret)
  119.                         PublishResource(ret);
  120.         }
  121.  
  122.         return ret;
  123. }
  124.  
  125. CAnimationDatabaseLibrary::THandle CAnimationDatabaseLibrary::TryOpenResource(const char* name, uint32 nFlags)
  126. {
  127.         char normalizedFilename[DEF_PATH_LENGTH];
  128.         NormalizeFilename(normalizedFilename, name);
  129.  
  130.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  131.  
  132.         TAnimDatabaseList::const_iterator iter = m_databases.find(crc32);
  133.  
  134.         THandle res = NULL;
  135.         if (iter != m_databases.end())
  136.                 res = iter->second;
  137.  
  138.         return res;
  139. }
  140.  
  141. void CAnimationDatabaseLibrary::CreateResource(THandle& hdlOut, const char* name, uint32 nFlags)
  142. {
  143.         char normalizedFilename[DEF_PATH_LENGTH];
  144.         NormalizeFilename(normalizedFilename, name);
  145.  
  146.         CAnimationDatabase* pDb = new CAnimationDatabase(normalizedFilename);
  147.         XmlNodeRef xml = gEnv->pSystem->GetXmlUtils()->LoadXmlFromFile(normalizedFilename);
  148.         if (!xml || !LoadDatabase(xml, *pDb, true))
  149.         {
  150.                 delete pDb;
  151.                 pDb = NULL;
  152.         }
  153.  
  154.         hdlOut = pDb;
  155. }
  156.  
  157. void CAnimationDatabaseLibrary::PublishResource(THandle& hdl)
  158. {
  159. #ifndef _RELEASE
  160.         if (!hdl)
  161.                 __debugbreak();
  162. #endif
  163.  
  164.         uint32 crc = CCrc32::ComputeLowercase(hdl->GetFilename());
  165.         Insert(crc, const_cast<CAnimationDatabase*>(static_cast<const CAnimationDatabase*>(hdl)));
  166. }
  167.  
  168. CAnimationTagDefLibrary::CAnimationTagDefLibrary()
  169. {
  170. }
  171.  
  172. CAnimationTagDefLibrary::~CAnimationTagDefLibrary()
  173. {
  174. }
  175.  
  176. void CAnimationTagDefLibrary::Insert(uint32 nCrc, CTagDefinition* pDef)
  177. {
  178.         m_tagDefs.insert(std::make_pair(nCrc, pDef));
  179. }
  180.  
  181. CAnimationTagDefLibrary::THandle CAnimationTagDefLibrary::LoadResource(const char* name, uint32 nFlags)
  182. {
  183.         THandle ret = TryOpenResource(name, nFlags);
  184.  
  185.         if (!ret)
  186.         {
  187.                 CreateResource(ret, name, nFlags);
  188.                 if (ret)
  189.                         PublishResource(ret);
  190.         }
  191.  
  192.         return ret;
  193. }
  194.  
  195. CAnimationTagDefLibrary::THandle CAnimationTagDefLibrary::TryOpenResource(const char* name, uint32 nFlags)
  196. {
  197.         THandle res = NULL;
  198.  
  199.         char normalizedFilename[DEF_PATH_LENGTH];
  200.         NormalizeFilename(normalizedFilename, name);
  201.  
  202.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  203.  
  204.         TTagDefList::const_iterator iter = m_tagDefs.find(crc32);
  205.         if (iter != m_tagDefs.end())
  206.                 res = iter->second;
  207.  
  208.         return res;
  209. }
  210.  
  211. void CAnimationTagDefLibrary::CreateResource(THandle& hdlOut, const char* name, uint32 nFlags)
  212. {
  213.         char normalizedFilename[DEF_PATH_LENGTH];
  214.         NormalizeFilename(normalizedFilename, name);
  215.  
  216.         CTagDefinition* pDef = new CTagDefinition(normalizedFilename);
  217.  
  218.         if (!mannequin::LoadTagDefinition(normalizedFilename, *pDef, (nFlags & eTDF_Tags) != 0))
  219.         {
  220.                 delete pDef;
  221.                 pDef = NULL;
  222.         }
  223.  
  224.         hdlOut = pDef;
  225. }
  226.  
  227. void CAnimationTagDefLibrary::PublishResource(THandle& hdlOut)
  228. {
  229. #ifndef _RELEASE
  230.         if (!hdlOut)
  231.                 __debugbreak();
  232. #endif
  233.  
  234.         uint32 crc32 = CCrc32::ComputeLowercase(hdlOut->GetFilename());
  235.         Insert(crc32, const_cast<CTagDefinition*>(hdlOut));
  236. }
  237.  
  238. CAnimationControllerDefLibrary::CAnimationControllerDefLibrary()
  239. {
  240. }
  241.  
  242. CAnimationControllerDefLibrary::~CAnimationControllerDefLibrary()
  243. {
  244. }
  245.  
  246. void CAnimationControllerDefLibrary::Insert(uint32 crc32, SControllerDef* pDef)
  247. {
  248.         m_controllerDefs.insert(std::make_pair(crc32, pDef));
  249. }
  250.  
  251. CAnimationControllerDefLibrary::THandle CAnimationControllerDefLibrary::LoadResource(const char* name, uint32 nFlags)
  252. {
  253.         THandle ret = TryOpenResource(name, nFlags);
  254.  
  255.         if (!ret)
  256.         {
  257.                 CreateResource(ret, name, nFlags);
  258.                 if (ret)
  259.                         PublishResource(ret);
  260.         }
  261.  
  262.         return ret;
  263. }
  264.  
  265. CAnimationControllerDefLibrary::THandle CAnimationControllerDefLibrary::TryOpenResource(const char* name, uint32 nFlags)
  266. {
  267.         THandle res = NULL;
  268.  
  269.         char normalizedFilename[DEF_PATH_LENGTH];
  270.         NormalizeFilename(normalizedFilename, name);
  271.  
  272.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  273.  
  274.         TControllerDefList::const_iterator iter = m_controllerDefs.find(crc32);
  275.  
  276.         if (iter != m_controllerDefs.end())
  277.                 res = iter->second;
  278.  
  279.         return res;
  280. }
  281.  
  282. void CAnimationControllerDefLibrary::CreateResource(THandle& hdlOut, const char* name, uint32 nFlags)
  283. {
  284.         char normalizedFilename[DEF_PATH_LENGTH];
  285.         NormalizeFilename(normalizedFilename, name);
  286.  
  287.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  288.  
  289.         SControllerDef* pDef = NULL;
  290.         XmlNodeRef xml = gEnv->pSystem->GetXmlUtils()->LoadXmlFromFile(normalizedFilename);
  291.         if (xml)
  292.         {
  293.                 pDef = LoadControllerDef(xml, normalizedFilename);
  294.                 if (pDef)
  295.                         pDef->m_filename.SetByString(normalizedFilename);
  296.         }
  297.  
  298.         hdlOut = pDef;
  299. }
  300.  
  301. void CAnimationControllerDefLibrary::PublishResource(THandle& hdl)
  302. {
  303. #ifndef _RELEASE
  304.         if (!hdl)
  305.                 __debugbreak();
  306. #endif
  307.  
  308.         uint32 crc32 = hdl->m_filename.crc;
  309.         Insert(crc32, const_cast<SControllerDef*>(hdl));
  310. }
  311.  
  312. CAnimationDatabaseManager::CAnimationDatabaseManager()
  313.         : m_editorListenerSet(1)
  314. {
  315.         const char* FRAGMENT_FLAGS[] =
  316.         {
  317.                 "Persistent",
  318.                 "AutoReinstall"
  319.         };
  320.         const int NUM_FRAGMENT_FLAGS = CRY_ARRAY_COUNT(FRAGMENT_FLAGS);
  321.         for (int i = 0; i < NUM_FRAGMENT_FLAGS; i++)
  322.         {
  323.                 m_fragmentFlags.AddTag(FRAGMENT_FLAGS[i]);
  324.         }
  325.  
  326.         m_fragmentFlags.AssignBits();
  327. }
  328.  
  329. CAnimationDatabaseManager::~CAnimationDatabaseManager()
  330. {
  331.         UnloadAll();
  332. }
  333.  
  334. const IAnimationDatabase* CAnimationDatabaseManager::FindDatabase(uint32 crcFilename) const
  335. {
  336.         return stl::find_in_map(m_databases, crcFilename, NULL);
  337. }
  338.  
  339. const IAnimationDatabase* CAnimationDatabaseManager::Load(const char* databaseName)
  340. {
  341.         //Don't load if there is no database
  342.         if (databaseName == nullptr || strlen(databaseName) == 0)
  343.         {
  344.                 return nullptr;
  345.         }
  346.  
  347.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Mannequin, 0, "Load ADB: %s", databaseName);
  348.  
  349.         const IAnimationDatabase* pDb = CAnimationDatabaseLibrary::LoadResource(databaseName, 0);
  350.         return pDb;
  351. }
  352.  
  353. IAnimationDatabase* CAnimationDatabaseManager::Create(const char* filename, const char* defFilename)
  354. {
  355.         char normalizedFilename[DEF_PATH_LENGTH];
  356.         NormalizeFilename(normalizedFilename, filename);
  357.  
  358.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Mannequin, 0, "Create ADB: %s", normalizedFilename);
  359.  
  360.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  361.  
  362.         TAnimDatabaseList::const_iterator iter = m_databases.find(crc32);
  363.  
  364.         if (iter != m_databases.end())
  365.         {
  366.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "!Attempting to create ADB file %s which already exists", normalizedFilename);
  367.                 return NULL;
  368.         }
  369.         else
  370.         {
  371.                 char normalizedDefFilename[DEF_PATH_LENGTH];
  372.                 NormalizeFilename(normalizedDefFilename, defFilename);
  373.  
  374.                 const SControllerDef* def = LoadControllerDef(normalizedDefFilename);
  375.  
  376.                 if (def)
  377.                 {
  378.                         CAnimationDatabase* animDB = new CAnimationDatabase();
  379.                         m_databases.insert(std::make_pair(crc32, animDB));
  380.  
  381.                         const uint32 numActions = def->m_fragmentIDs.GetNum();
  382.  
  383.                         animDB->m_filename = normalizedFilename;
  384.                         animDB->m_pFragDef = &def->m_fragmentIDs;
  385.                         animDB->m_pTagDef = &def->m_tags;
  386.                         animDB->m_fragmentList.resize(numActions);
  387.                         for (uint32 i = 0; i < numActions; ++i)
  388.                         {
  389.                                 animDB->m_fragmentList[i] = new CAnimationDatabase::SFragmentEntry();
  390.                         }
  391.  
  392.                         Save(*animDB, normalizedFilename);
  393.  
  394.                         return animDB;
  395.                 }
  396.                 else
  397.                 {
  398.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "!Failed to load def file %s whilst creating ADB file %s", normalizedDefFilename, normalizedFilename);
  399.  
  400.                         return NULL;
  401.                 }
  402.         }
  403. }
  404.  
  405. CTagDefinition* CAnimationDatabaseManager::CreateTagDefinition(const char* filename)
  406. {
  407.         char normalizedFilename[DEF_PATH_LENGTH];
  408.         NormalizeFilename(normalizedFilename, filename);
  409.  
  410.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Mannequin, 0, "Create TagDefinition: %s", normalizedFilename);
  411.  
  412.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  413.  
  414.         CTagDefinition* tagDef = new CTagDefinition(normalizedFilename);
  415.  
  416.         mannequin::SaveTagDefinition(*tagDef);
  417.  
  418.         m_tagDefs.insert(std::make_pair(crc32, tagDef));
  419.  
  420.         return tagDef;
  421. }
  422.  
  423. const SControllerDef* CAnimationDatabaseManager::LoadControllerDef(const char* filename)
  424. {
  425.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Mannequin, 0, "Load ControllerDef: %s", filename);
  426.  
  427.         const SControllerDef* const pDef = CAnimationControllerDefLibrary::LoadResource(filename, 0);
  428.         return pDef;
  429. }
  430.  
  431. const SControllerDef* CAnimationDatabaseManager::FindControllerDef(const uint32 crcFilename) const
  432. {
  433.         return stl::find_in_map(m_controllerDefs, crcFilename, NULL);
  434. }
  435.  
  436. const SControllerDef* CAnimationDatabaseManager::FindControllerDef(const char* filename) const
  437. {
  438.         char normalizedFilename[DEF_PATH_LENGTH];
  439.         NormalizeFilename(normalizedFilename, filename);
  440.  
  441.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  442.  
  443.         return FindControllerDef(crc32);
  444. }
  445.  
  446. const CTagDefinition* CAnimationDatabaseManager::LoadTagDefs(const char* filename, bool isTags)
  447. {
  448.         char normalizedFilename[DEF_PATH_LENGTH];
  449.         NormalizeFilename(normalizedFilename, filename);
  450.  
  451.         MEMSTAT_CONTEXT_FMT(EMemStatContextTypes::MSC_Mannequin, 0, "Load TagDefs: %s", normalizedFilename);
  452.  
  453.         const CTagDefinition* pTagDef = CAnimationTagDefLibrary::LoadResource(filename, isTags ? eTDF_Tags : 0);
  454.         return pTagDef;
  455. }
  456.  
  457. const CTagDefinition* CAnimationDatabaseManager::FindTagDef(const uint32 crcFilename) const
  458. {
  459.         return stl::find_in_map(m_tagDefs, crcFilename, NULL);
  460. }
  461.  
  462. const CTagDefinition* CAnimationDatabaseManager::FindTagDef(const char* filename) const
  463. {
  464.         char normalizedFilename[DEF_PATH_LENGTH];
  465.         NormalizeFilename(normalizedFilename, filename);
  466.  
  467.         uint32 crc32 = CCrc32::ComputeLowercase(normalizedFilename);
  468.  
  469.         return FindTagDef(crc32);
  470. }
  471.  
  472. void CAnimationDatabaseManager::RemoveDataFromParent(CAnimationDatabase* parentADB, const CAnimationDatabase::SSubADB* subADB)
  473. {
  474.         // Clear out fragments that came from subAnimDB
  475.         FragmentID fragID = 0;
  476.         for (CAnimationDatabase::TFragmentList::const_iterator it = parentADB->m_fragmentList.begin(), itEnd = parentADB->m_fragmentList.end(); it != itEnd; ++it, ++fragID)
  477.         {
  478.                 if (CanSaveFragmentID(fragID, *parentADB, subADB))
  479.                 {
  480.                         if (CAnimationDatabase::SFragmentEntry* entry = *it)
  481.                         {
  482.                                 for (int32 k = entry->tagSetList.Size() - 1; k >= 0; k--)
  483.                                 {
  484.                                         bool bDummy;
  485.                                         if (ShouldSaveFragment(fragID, entry->tagSetList.m_keys[k].globalTags, *parentADB, subADB, bDummy))
  486.                                         {
  487.                                                 entry->tagSetList.Erase(k);
  488.                                         }
  489.                                 }
  490.                         }
  491.                 }
  492.         }
  493.  
  494.         // Clear out blends that came from subAnimDB
  495.         for (CAnimationDatabase::TFragmentBlendDatabase::iterator iter = parentADB->m_fragmentBlendDB.begin(), iterEnd = parentADB->m_fragmentBlendDB.end(); iter != iterEnd; ++iter)
  496.         {
  497.                 if (CanSaveFragmentID(iter->first.fragFrom, *parentADB, subADB) && CanSaveFragmentID(iter->first.fragTo, *parentADB, subADB))
  498.                 {
  499.                         for (int32 v = iter->second.variantList.size() - 1; v >= 0; v--)
  500.                         {
  501.                                 CAnimationDatabase::SFragmentBlendVariant& variant = iter->second.variantList[v];
  502.                                 bool bDummy;
  503.                                 if (ShouldSaveTransition(iter->first.fragFrom, iter->first.fragTo, variant.tagsFrom.globalTags, variant.tagsTo.globalTags, *parentADB, subADB, bDummy))
  504.                                 {
  505.                                         for (CAnimationDatabase::TFragmentBlendList::iterator fragIt = variant.blendList.begin(), fragItEnd = variant.blendList.end(); fragIt != fragItEnd; ++fragIt)
  506.                                         {
  507.                                                 delete fragIt->pFragment;
  508.                                         }
  509.                                         iter->second.variantList.erase(iter->second.variantList.begin() + v);
  510.                                 }
  511.                         }
  512.                 }
  513.         }
  514. }
  515.  
  516. void CAnimationDatabaseManager::RevertSubADB(const char* szFilename, CAnimationDatabase* animDB, const CAnimationDatabase::SSubADB& subADB)
  517. {
  518.         // Check the subADBs of animDB
  519.         if (stricmp(szFilename, subADB.filename) == 0)
  520.         {
  521.                 RemoveDataFromParent(animDB, &subADB);
  522.  
  523.                 XmlNodeRef xmlData = GetISystem()->LoadXmlFromFile(subADB.filename);
  524.                 LoadDatabaseData(*animDB, xmlData, animDB->GetFragmentDefs(), animDB->GetTagDefs(), subADB.tags, false);
  525.         }
  526.         for (CAnimationDatabase::TSubADBList::const_iterator adbIt = subADB.subADBs.begin(); adbIt != subADB.subADBs.end(); ++adbIt)
  527.                 RevertSubADB(szFilename, animDB, *adbIt);
  528. }
  529.  
  530. void CAnimationDatabaseManager::RevertDatabase(const char* szFilename)
  531. {
  532.         for (TAnimDatabaseList::const_iterator it = m_databases.begin(), itEnd = m_databases.end(); it != itEnd; ++it)
  533.         {
  534.                 CAnimationDatabase* animDB = it->second;
  535.  
  536.                 animDB->SetAutoSort(false);
  537.  
  538.                 for (CAnimationDatabase::TSubADBList::const_iterator adbIt = animDB->m_subADBs.begin(); adbIt != animDB->m_subADBs.end(); ++adbIt)
  539.                 {
  540.                         const CAnimationDatabase::SSubADB& subADB = *adbIt;
  541.                         RevertSubADB(szFilename, animDB, subADB);
  542.                 }
  543.  
  544.                 // Are we reverting animDB itself?
  545.                 if (stricmp(szFilename, animDB->GetFilename()) == 0)
  546.                 {
  547.                         RemoveDataFromParent(animDB, NULL);
  548.  
  549.                         XmlNodeRef xmlData = GetISystem()->LoadXmlFromFile(animDB->GetFilename());
  550.                         LoadDatabaseData(*animDB, xmlData,
  551.                                          animDB->GetFragmentDefs(), animDB->GetTagDefs(),
  552.                                          TAG_STATE_EMPTY, false);
  553.                 }
  554.  
  555.                 animDB->Sort();
  556.                 animDB->SetAutoSort(true);
  557.         }
  558. }
  559.  
  560. void CAnimationDatabaseManager::ClearDatabase(CAnimationDatabase* pDatabase)
  561. {
  562.         // Clear out the fragment list
  563.         std::for_each(pDatabase->m_fragmentList.begin(), pDatabase->m_fragmentList.end(), stl::container_object_deleter());
  564.         pDatabase->m_fragmentList.clear();
  565.  
  566.         // Clear out the blends
  567.         for (CAnimationDatabase::TFragmentBlendDatabase::iterator blDbIt = pDatabase->m_fragmentBlendDB.begin(), blDbItEnd = pDatabase->m_fragmentBlendDB.end(); blDbIt != blDbItEnd; ++blDbIt)
  568.         {
  569.                 CAnimationDatabase::SFragmentBlendEntry& entry = blDbIt->second;
  570.                 for (CAnimationDatabase::TFragmentVariantList::iterator vrIt = entry.variantList.begin(), vrItEnd = entry.variantList.end(); vrIt != vrItEnd; ++vrIt)
  571.                 {
  572.                         CAnimationDatabase::SFragmentBlendVariant& variant = *vrIt;
  573.                         for (CAnimationDatabase::TFragmentBlendList::iterator fragIt = variant.blendList.begin(), fragItEnd = variant.blendList.end(); fragIt != fragItEnd; ++fragIt)
  574.                         {
  575.                                 delete fragIt->pFragment;
  576.                         }
  577.                 }
  578.         }
  579.         pDatabase->m_fragmentBlendDB.clear();
  580. }
  581.  
  582. void CAnimationDatabaseManager::ReloadDatabase(IAnimationDatabase* pDatabase)
  583. {
  584.         CAnimationDatabase* animDB = (CAnimationDatabase*)pDatabase;
  585.  
  586.         ClearDatabase(animDB);
  587.  
  588.         // Clear out the subADBs
  589.         stl::free_container(animDB->m_subADBs);
  590.  
  591.         // Reload the database and all subDB data
  592.         if (XmlNodeRef xmlData = GetISystem()->LoadXmlFromFile(animDB->m_filename.c_str()))
  593.         {
  594.                 LoadDatabase(xmlData, *animDB, true);
  595.         }
  596.         else
  597.         {
  598.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Could not load xml file '%s'", animDB->m_filename.c_str());
  599.         }
  600. }
  601.  
  602. void CAnimationDatabaseManager::RevertControllerDef(const char* szFilename)
  603. {
  604.         if (SControllerDef* controllerDef = const_cast<SControllerDef*>(FindControllerDef(szFilename)))
  605.         {
  606.                 ReloadControllerDef(controllerDef);
  607.         }
  608. }
  609.  
  610. void CAnimationDatabaseManager::ReloadControllerDef(SControllerDef* pControllerDef)
  611. {
  612.         TDefPathString defFilename = pControllerDef->m_filename;
  613.  
  614.         if (XmlNodeRef xmlData = GetISystem()->LoadXmlFromFile(defFilename.c_str()))
  615.         {
  616.                 if (SControllerDef* newControllerDef = CAnimationControllerDefLibrary::LoadControllerDef(xmlData, defFilename.c_str()))
  617.                 {
  618.                         new(pControllerDef) SControllerDef(*newControllerDef);
  619.                         pControllerDef->m_filename = defFilename;
  620.                         delete newControllerDef;
  621.                 }
  622.                 else
  623.                 {
  624.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Error in reloading xml file %s", defFilename.c_str());
  625.                 }
  626.         }
  627.         else
  628.         {
  629.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Could not load xml file %s", defFilename.c_str());
  630.         }
  631. }
  632.  
  633. void CAnimationDatabaseManager::RevertTagDef(const char* szFilename)
  634. {
  635.         if (CTagDefinition* tagDef = const_cast<CTagDefinition*>(FindTagDef(szFilename)))
  636.         {
  637.                 ReloadTagDefinition(tagDef);
  638.         }
  639. }
  640.  
  641. void CAnimationDatabaseManager::ReloadTagDefinition(CTagDefinition* pTagDefinition)
  642. {
  643.         assert(pTagDefinition);
  644.         pTagDefinition->Clear();
  645.  
  646.         const char* const filename = pTagDefinition->GetFilename();
  647.         mannequin::LoadTagDefinition(filename, *pTagDefinition, pTagDefinition->HasMasks());
  648.  
  649.         NotifyListenersTagDefinitionChanged(*pTagDefinition);
  650. }
  651.  
  652. void CAnimationDatabaseManager::ReloadAll()
  653. {
  654.         for (TTagDefList::const_iterator iter = m_tagDefs.begin(), iterEnd = m_tagDefs.end(); iter != iterEnd; ++iter)
  655.         {
  656.                 CTagDefinition* tagDef = iter->second;
  657.                 ReloadTagDefinition(tagDef);
  658.         }
  659.  
  660.         for (TControllerDefList::iterator iter = m_controllerDefs.begin(), iterEnd = m_controllerDefs.end(); iter != iterEnd; ++iter)
  661.         {
  662.                 SControllerDef* controllerDef = iter->second;
  663.                 ReloadControllerDef(controllerDef);
  664.         }
  665.  
  666.         for (TAnimDatabaseList::const_iterator iter = m_databases.begin(), iterEnd = m_databases.end(); iter != iterEnd; ++iter)
  667.         {
  668.                 CAnimationDatabase* animDB = iter->second;
  669.                 ReloadDatabase(animDB);
  670.         }
  671. }
  672.  
  673. void CAnimationDatabaseManager::UnloadAll()
  674. {
  675.         for (TAnimDatabaseList::iterator it = m_databases.begin(), itEnd = m_databases.end(); it != itEnd; ++it)
  676.                 delete it->second;
  677.         for (TControllerDefList::iterator it = m_controllerDefs.begin(), itEnd = m_controllerDefs.end(); it != itEnd; ++it)
  678.                 delete it->second;
  679.         for (TTagDefList::iterator it = m_tagDefs.begin(), itEnd = m_tagDefs.end(); it != itEnd; ++it)
  680.                 delete it->second;
  681.  
  682.         m_databases.clear();
  683.         m_controllerDefs.clear();
  684.         m_tagDefs.clear();
  685.  
  686.         mannequin::OnDatabaseManagerUnload();
  687. }
  688.  
  689. void CAnimationDatabaseManager::GetAffectedFragmentsString(const CTagDefinition* pQueryTagDef, TagID tagID, char* buffer, int bufferSize)
  690. {
  691.         string filename;
  692.         string temp;
  693.         string matchingFragments;
  694.         uint pos = 0;
  695.  
  696.         for (TAnimDatabaseList::const_iterator iter = m_databases.begin(); iter != m_databases.end(); ++iter)
  697.         {
  698.                 CAnimationDatabase* pCurrentDatabase = iter->second;
  699.                 const CTagDefinition& fragmentDefs = pCurrentDatabase->GetFragmentDefs();
  700.                 bool isGlobalTag = (&pCurrentDatabase->GetTagDefs() == pQueryTagDef);
  701.                 bool filenameAdded = false;
  702.  
  703.                 filename = pCurrentDatabase->GetFilename();
  704.                 filename = filename.substr(MANNEQUIN_FOLDER.length());
  705.  
  706.                 const uint32 numFragmentDefs = fragmentDefs.GetNum();
  707.                 for (uint32 fragIndex = 0; fragIndex < numFragmentDefs; ++fragIndex)
  708.                 {
  709.                         if (isGlobalTag || (fragmentDefs.GetSubTagDefinition(fragIndex) == pQueryTagDef))
  710.                         {
  711.                                 const uint32 numTagSets = pCurrentDatabase->GetTotalTagSets(fragIndex);
  712.                                 for (uint32 tagSetIndex = 0; tagSetIndex < numTagSets; ++tagSetIndex)
  713.                                 {
  714.                                         SFragTagState tagState;
  715.                                         uint32 numOptions = pCurrentDatabase->GetTagSetInfo(fragIndex, tagSetIndex, tagState);
  716.                                         if (isGlobalTag)
  717.                                         {
  718.                                                 if (pQueryTagDef->IsSet(tagState.globalTags, tagID))
  719.                                                 {
  720.                                                         if (!filenameAdded)
  721.                                                         {
  722.                                                                 matchingFragments.TrimRight(',');
  723.                                                                 temp.Format("\n[%s]:", filename.c_str());
  724.                                                                 matchingFragments += temp;
  725.                                                                 filenameAdded = true;
  726.                                                         }
  727.                                                         CryStackStringT<char, 128> sGlobalTags;
  728.                                                         pCurrentDatabase->GetTagDefs().FlagsToTagList(tagState.globalTags, sGlobalTags);
  729.                                                         temp.Format(" %s (%s),", fragmentDefs.GetTagName(fragIndex), sGlobalTags.c_str());
  730.                                                         matchingFragments += temp;
  731.                                                 }
  732.                                         }
  733.                                         else
  734.                                         {
  735.                                                 if (pQueryTagDef->IsSet(tagState.fragmentTags, tagID))
  736.                                                 {
  737.                                                         if (!filenameAdded)
  738.                                                         {
  739.                                                                 matchingFragments.TrimRight(',');
  740.                                                                 temp.Format("\n[%s]:", filename.c_str());
  741.                                                                 matchingFragments += temp;
  742.                                                                 filenameAdded = true;
  743.                                                         }
  744.                                                         CryStackStringT<char, 128> sFragmentTags;
  745.                                                         fragmentDefs.GetSubTagDefinition(fragIndex)->FlagsToTagList(tagState.fragmentTags, sFragmentTags);
  746.                                                         temp.Format(" %s (%s),", fragmentDefs.GetTagName(fragIndex), sFragmentTags.c_str());
  747.                                                         matchingFragments += temp;
  748.                                                 }
  749.                                         }
  750.                                 }
  751.                         }
  752.  
  753.                         if (pos != matchingFragments.length())
  754.                         {
  755.                                 // Log the fragments so there's a record
  756.                                 CryLog("[TAGDEF]: affected fragments: %s", matchingFragments.Mid(pos, matchingFragments.length() - 1).c_str());
  757.                                 pos = matchingFragments.length();
  758.                         }
  759.                 }
  760.         }
  761.  
  762.         if (!matchingFragments.empty())
  763.         {
  764.                 matchingFragments.TrimRight(',');
  765.         }
  766.         else
  767.         {
  768.                 matchingFragments = "\nno fragments";
  769.         }
  770.  
  771.         cry_strcpy(buffer, bufferSize, matchingFragments.c_str());
  772.         if (matchingFragments.length() + 1 > bufferSize)
  773.         {
  774.                 // In case the string is truncated
  775.                 memcpy(buffer + bufferSize - 4, "...", 4);
  776.         }
  777. }
  778.  
  779. void CAnimationDatabaseManager::ApplyTagDefChanges(const CTagDefinition* pOriginal, CTagDefinition* pModified)
  780. {
  781.         string filename;
  782.  
  783.         for (TAnimDatabaseList::const_iterator iter = m_databases.begin(); iter != m_databases.end(); ++iter)
  784.         {
  785.                 CAnimationDatabase* pCurrentDatabase = iter->second;
  786.                 bool isGlobalTag = (&pCurrentDatabase->GetTagDefs() == pOriginal);
  787.  
  788.                 if (isGlobalTag)
  789.                 {
  790.                         const int32 numSubADBs = pCurrentDatabase->m_subADBs.size();
  791.                         TagState modified;
  792.  
  793.                         for (int subADBIndex = numSubADBs - 1; subADBIndex >= 0; --subADBIndex)
  794.                         {
  795.                                 CAnimationDatabase::SSubADB& subADB = pCurrentDatabase->m_subADBs[subADBIndex];
  796.                                 if (pOriginal->MapTagState(subADB.tags, modified, *pModified))
  797.                                 {
  798.                                         subADB.tags = modified;
  799.                                         subADB.comparisonMask = pModified->GenerateMask(modified);
  800.  
  801.                                         if (subADB.pTagDef == pOriginal)
  802.                                         {
  803.                                                 subADB.knownTags = TAG_STATE_FULL;
  804.                                         }
  805.                                         else
  806.                                         {
  807.                                                 subADB.knownTags = pModified->GetSharedTags(*subADB.pTagDef);
  808.                                         }
  809.                                 }
  810.                                 else
  811.                                 {
  812.                                         RemoveDataFromParent(pCurrentDatabase, &pCurrentDatabase->m_subADBs[subADBIndex]);
  813.                                         pCurrentDatabase->m_subADBs.erase(pCurrentDatabase->m_subADBs.begin() + subADBIndex);
  814.                                 }
  815.                         }
  816.                 }
  817.         }
  818.  
  819.         STagDefinitionImportsInfo& originalImports = mannequin::GetDefaultImportsInfo(pOriginal->GetFilename());
  820.         originalImports.MapTags(*pOriginal, *pModified);
  821.  
  822.         // Do the save
  823.         *(const_cast<CTagDefinition*>(pOriginal)) = *pModified;
  824. }
  825.  
  826. void CAnimationDatabaseManager::RenameTag(const CTagDefinition* pOriginal, int32 tagCRC, const char* newName)
  827. {
  828.         STagDefinitionImportsInfo& originalImports = mannequin::GetDefaultImportsInfo(pOriginal->GetFilename());
  829.  
  830.         // Determine which import (if any) contains the tag to rename
  831.         TagID id = pOriginal->FindGroup(tagCRC);
  832.         const STagDefinitionImportsInfo& root = originalImports.Find(id);
  833.         //CryLog("[TAGDEF]: root is %s", root.GetFilename());
  834.  
  835.         // For each tagdef we know about...
  836.         for (TTagDefList::iterator it = m_tagDefs.begin(); it != m_tagDefs.end(); ++it)
  837.         {
  838.                 std::vector<const STagDefinitionImportsInfo*> tagDefImportsInfo;
  839.                 STagDefinitionImportsInfo& tagDefImports = mannequin::GetDefaultImportsInfo(it->second->GetFilename());
  840.                 tagDefImports.FlattenImportsInfo(tagDefImportsInfo);
  841.  
  842.                 // ...check if it imports the root...
  843.                 bool importsRoot = false;
  844.                 for (uint32 index = 0, size = tagDefImportsInfo.size(); index < size; ++index)
  845.                 {
  846.                         if (stricmp(root.GetFilename(), tagDefImportsInfo[index]->GetFilename()) == 0)
  847.                         {
  848.                                 importsRoot = true;
  849.                                 break;
  850.                         }
  851.                 }
  852.  
  853.                 // ...and if it does, rename all occurrences of the tag in the import "chain"
  854.                 if (importsRoot)
  855.                 {
  856.                         for (uint32 index = 0, size = tagDefImportsInfo.size(); index < size; ++index)
  857.                         {
  858.                                 const STagDefinitionImportsInfo* pImportsInfo = tagDefImportsInfo[index];
  859.                                 CTagDefinition* pTagDef = stl::find_in_map(m_tagDefs, CCrc32::ComputeLowercase(pImportsInfo->GetFilename()), NULL);
  860.                                 id = TAG_ID_INVALID;
  861.                                 if (pTagDef != NULL)
  862.                                 {
  863.                                         id = pTagDef->Find(tagCRC);
  864.                                 }
  865.                                 if (id != TAG_ID_INVALID)
  866.                                 {
  867.                                         //CryLog("[TAGDEF]: tag %p [%s]:[%s]->[%s]", pTagDef, pImportsInfo->GetFilename(), pTagDef->GetTagName(id), newName);
  868.                                         pTagDef->SetTagName(id, newName);
  869.                                 }
  870.                         }
  871.                 }
  872.         }
  873. };
  874.  
  875. void CAnimationDatabaseManager::RenameTagGroup(const CTagDefinition* pOriginal, int32 tagGroupCRC, const char* newName)
  876. {
  877.         STagDefinitionImportsInfo& originalImports = mannequin::GetDefaultImportsInfo(pOriginal->GetFilename());
  878.  
  879.         // Determine which import (if any) contains the group to rename
  880.         TagGroupID id = pOriginal->FindGroup(tagGroupCRC);
  881.         const STagDefinitionImportsInfo& root = originalImports.Find(id);
  882.         //CryLog("[TAGDEF]: root is %s", root.GetFilename());
  883.  
  884.         // For each tagdef we know about...
  885.         for (TTagDefList::iterator it = m_tagDefs.begin(); it != m_tagDefs.end(); ++it)
  886.         {
  887.                 std::vector<const STagDefinitionImportsInfo*> tagDefImportsInfo;
  888.                 STagDefinitionImportsInfo& tagDefImports = mannequin::GetDefaultImportsInfo(it->second->GetFilename());
  889.                 tagDefImports.FlattenImportsInfo(tagDefImportsInfo);
  890.  
  891.                 // ...check if it imports the root...
  892.                 bool importsRoot = false;
  893.                 for (uint32 index = 0, size = tagDefImportsInfo.size(); index < size; ++index)
  894.                 {
  895.                         if (stricmp(root.GetFilename(), tagDefImportsInfo[index]->GetFilename()) == 0)
  896.                         {
  897.                                 importsRoot = true;
  898.                                 break;
  899.                         }
  900.                 }
  901.  
  902.                 // ...and if it does, rename all occurrences of the group in the import "chain"
  903.                 if (importsRoot)
  904.                 {
  905.                         for (uint32 index = 0, size = tagDefImportsInfo.size(); index < size; ++index)
  906.                         {
  907.                                 const STagDefinitionImportsInfo* pImportsInfo = tagDefImportsInfo[index];
  908.                                 CTagDefinition* pTagDef = stl::find_in_map(m_tagDefs, CCrc32::ComputeLowercase(pImportsInfo->GetFilename()), NULL);
  909.                                 id = GROUP_ID_NONE;
  910.                                 if (pTagDef != NULL)
  911.                                 {
  912.                                         id = pTagDef->FindGroup(tagGroupCRC);
  913.                                 }
  914.                                 if (id != GROUP_ID_NONE)
  915.                                 {
  916.                                         //CryLog("[TAGDEF]: group %p [%s]:[%s]->[%s]", pTagDef, pImportsInfo->GetFilename(), pTagDef->GetGroupName(id), newName);
  917.                                         pTagDef->SetGroupName(id, newName);
  918.                                 }
  919.                         }
  920.                 }
  921.         }
  922. };
  923.  
  924. void CAnimationDatabaseManager::GetIncludedTagDefs(const CTagDefinition* pQueriedTagDef, DynArray<CTagDefinition*>& outputTagDefs) const
  925. {
  926.         outputTagDefs.clear();
  927.  
  928.         if (!pQueriedTagDef)
  929.         {
  930.                 return;
  931.         }
  932.  
  933.         const STagDefinitionImportsInfo& queriedImportsInfo = mannequin::GetDefaultImportsInfo(pQueriedTagDef->GetFilename());
  934.         std::vector<const STagDefinitionImportsInfo*> flatImportsInfoList;
  935.         queriedImportsInfo.FlattenImportsInfo(flatImportsInfoList);
  936.  
  937.         for (uint32 importIndex = 0, size = flatImportsInfoList.size(); importIndex < size; ++importIndex)
  938.         {
  939.                 const STagDefinitionImportsInfo* pImportsInfo = flatImportsInfoList[importIndex];
  940.                 assert(pImportsInfo);
  941.                 CTagDefinition* pFoundTagDef = stl::find_in_map(m_tagDefs, CCrc32::ComputeLowercase(pImportsInfo->GetFilename()), NULL);
  942.  
  943.                 if (pFoundTagDef && (pFoundTagDef != pQueriedTagDef))
  944.                 {
  945.                         outputTagDefs.push_back(pFoundTagDef);
  946.                 }
  947.         }
  948. }
  949.  
  950. void CAnimationDatabaseManager::SaveSubADB(const CAnimationDatabase& animDB, const CAnimationDatabase::SSubADB& subAnimDB, const TFragmentSaveList& vFragSaveList, const TFragmentBlendSaveDatabase& mBlendSaveDatabase) const
  951. {
  952.         XmlNodeRef xmlSubNode = SaveDatabase(animDB, &subAnimDB, vFragSaveList, mBlendSaveDatabase);
  953.         xmlSubNode->saveToFile(subAnimDB.filename.c_str());
  954.  
  955.         for (CAnimationDatabase::TSubADBList::const_iterator itSubADB = subAnimDB.subADBs.begin(); itSubADB != subAnimDB.subADBs.end(); ++itSubADB)
  956.                 SaveSubADB(animDB, *itSubADB, vFragSaveList, mBlendSaveDatabase);
  957. }
  958.  
  959. void CAnimationDatabaseManager::Save(const IAnimationDatabase& iAnimDB, const char* databaseName) const
  960. {
  961.         CAnimationDatabase& animDB = (CAnimationDatabase&)iAnimDB;
  962.         TFragmentSaveList vFragSaveList;
  963.         TFragmentBlendSaveDatabase mBlendSaveDatabase;
  964.  
  965.         XmlNodeRef xmlNode = SaveDatabase(animDB, NULL, vFragSaveList, mBlendSaveDatabase);
  966.         xmlNode->saveToFile(databaseName);
  967.  
  968.         for (CAnimationDatabase::TSubADBList::const_iterator itSubADB = animDB.m_subADBs.begin(); itSubADB != animDB.m_subADBs.end(); ++itSubADB)
  969.                 SaveSubADB(animDB, *itSubADB, vFragSaveList, mBlendSaveDatabase);
  970. }
  971.  
  972. //--- Helper functions
  973.  
  974. void CAnimationDatabaseLibrary::AnimEntryToXML(XmlNodeRef outXmlAnimEntry, const SAnimationEntry& animEntry, const char* name) const
  975. {
  976.         outXmlAnimEntry->setAttr("name", animEntry.animRef.c_str());
  977.         if (animEntry.flags)
  978.         {
  979.                 CryStackStringT<char, 1024> sFlags;
  980.                 m_animFlags.IntegerFlagsToTagList(animEntry.flags, sFlags);
  981.                 outXmlAnimEntry->setAttr("flags", sFlags.c_str());
  982.         }
  983.         if (animEntry.playbackSpeed != 1.0f)
  984.         {
  985.                 outXmlAnimEntry->setAttr("speed", animEntry.playbackSpeed);
  986.         }
  987.         if (animEntry.playbackWeight != 1.0f)
  988.         {
  989.                 outXmlAnimEntry->setAttr("weight", animEntry.playbackWeight);
  990.         }
  991.         if (animEntry.weightList != 0)
  992.         {
  993.                 outXmlAnimEntry->setAttr("weightList", animEntry.weightList);
  994.         }
  995.         char channelName[10];
  996.         cry_strcpy(channelName, "channel0");
  997.         for (uint32 i = 0; i < MANN_NUMBER_BLEND_CHANNELS; i++)
  998.         {
  999.                 if (animEntry.blendChannels[i] != 0.0f)
  1000.                 {
  1001.                         channelName[7] = '0' + i;
  1002.                         outXmlAnimEntry->setAttr(channelName, animEntry.blendChannels[i]);
  1003.                 }
  1004.         }
  1005. }
  1006.  
  1007. bool CAnimationDatabaseLibrary::XMLToAnimEntry(SAnimationEntry& animEntry, XmlNodeRef root) const
  1008. {
  1009.         bool success = true;
  1010.         animEntry.animRef.SetByString(root->getAttr("name"));
  1011.         success = success && m_animFlags.TagListToIntegerFlags(root->getAttr("flags"), animEntry.flags);
  1012.         animEntry.playbackSpeed = 1.0f;
  1013.         root->getAttr("speed", animEntry.playbackSpeed);
  1014.         animEntry.playbackWeight = 1.0f;
  1015.         root->getAttr("weight", animEntry.playbackWeight);
  1016.         root->getAttr("weightList", animEntry.weightList);
  1017.  
  1018.         char channelName[10];
  1019.         cry_strcpy(channelName, "channel0");
  1020.         for (uint32 i = 0; i < MANN_NUMBER_BLEND_CHANNELS; i++)
  1021.         {
  1022.                 channelName[7] = '0' + i;
  1023.                 root->getAttr(channelName, animEntry.blendChannels[i]);
  1024.         }
  1025.         return success;
  1026. }
  1027.  
  1028. void CAnimationDatabaseLibrary::BlendToXML(XmlNodeRef outXmlBlend, const SAnimBlend& animBlend, const char* name) const
  1029. {
  1030.         outXmlBlend->setAttr("ExitTime", animBlend.exitTime);
  1031.         outXmlBlend->setAttr("StartTime", animBlend.startTime);
  1032.         outXmlBlend->setAttr("Duration", animBlend.duration);
  1033.  
  1034.         if (animBlend.flags)
  1035.         {
  1036.                 CryStackStringT<char, 1024> sFlags;
  1037.                 m_animFlags.IntegerFlagsToTagList(animBlend.flags, sFlags);
  1038.                 outXmlBlend->setAttr("flags", sFlags.c_str());
  1039.         }
  1040.  
  1041.         if (animBlend.terminal)
  1042.         {
  1043.                 outXmlBlend->setAttr("terminal", true);
  1044.         }
  1045. }
  1046.  
  1047. void CAnimationDatabaseLibrary::XMLToBlend(SAnimBlend& animBlend, XmlNodeRef xmlBlend) const
  1048. {
  1049.         xmlBlend->getAttr("ExitTime", animBlend.exitTime);
  1050.         xmlBlend->getAttr("StartTime", animBlend.startTime);
  1051.         xmlBlend->getAttr("Duration", animBlend.duration);
  1052.         m_animFlags.TagListToIntegerFlags(xmlBlend->getAttr("flags"), animBlend.flags);
  1053.         xmlBlend->getAttr("terminal", animBlend.terminal);
  1054. }
  1055.  
  1056. void CAnimationDatabaseLibrary::ProceduralToXml(XmlNodeRef pOutNode, const SProceduralEntry& proceduralEntry) const
  1057. {
  1058.         const bool isNoneType = proceduralEntry.IsNoneType();
  1059.         const char* const typeName = isNoneType ? "" : mannequin::FindProcClipTypeName(proceduralEntry.typeNameHash);
  1060.  
  1061.         if (!typeName)
  1062.         {
  1063.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Unable to create xml node for procedural entry: Type '%u' is unknown!", proceduralEntry.typeNameHash.ToUInt32());
  1064.                 return;
  1065.         }
  1066.  
  1067.         pOutNode->setAttr("type", typeName);
  1068.  
  1069.         if (proceduralEntry.pProceduralParams)
  1070.         {
  1071.                 XmlNodeRef pXmlProceduralParams = Serialization::SaveXmlNode(*proceduralEntry.pProceduralParams, "ProceduralParams");
  1072.                 if (pXmlProceduralParams)
  1073.                 {
  1074.                         pOutNode->addChild(pXmlProceduralParams);
  1075.                 }
  1076.                 else
  1077.                 {
  1078.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Unable to create 'ProceduralParams' node for procedural entry parameters for clip with type name '%s'", typeName);
  1079.                 }
  1080.         }
  1081. }
  1082.  
  1083. bool CAnimationDatabaseLibrary::XmlToProcedural(XmlNodeRef pInNode, SProceduralEntry& outProceduralEntry) const
  1084. {
  1085.         CRY_ASSERT(gEnv && gEnv->pGameFramework);
  1086.         const IProceduralClipFactory& proceduralClipFactory = gEnv->pGameFramework->GetMannequinInterface().GetProceduralClipFactory();
  1087.  
  1088.         const char* const typeName = pInNode->getAttr("type");
  1089.         const char* const safeTypeName = typeName ? typeName : "";
  1090.  
  1091.         const IProceduralClipFactory::THash typeNameHash(safeTypeName);
  1092.  
  1093.         outProceduralEntry.typeNameHash = IProceduralClipFactory::THash();
  1094.         const bool isNoneType = typeNameHash.IsEmpty();
  1095.         if (!isNoneType)
  1096.         {
  1097.                 outProceduralEntry.pProceduralParams = proceduralClipFactory.CreateProceduralClipParams(typeNameHash);
  1098.                 if (!outProceduralEntry.pProceduralParams)
  1099.                 {
  1100.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Could not create procedural clip parameters for procedural clip with type name '%s' and hash '%u' at line '%d'.", safeTypeName, typeNameHash.ToUInt32(), pInNode->getLine());
  1101.                         return false;
  1102.                 }
  1103.  
  1104.                 XmlNodeRef pXmlProceduralParams = pInNode->findChild("ProceduralParams");
  1105.  
  1106.                 {
  1107.                         // Old procedural clip format conversion. Remove this whole block when support for old format is not desired anymore.
  1108.                         if (!pXmlProceduralParams)
  1109.                         {
  1110.                                 CProcClipConversionHelper helper;
  1111.                                 pXmlProceduralParams = helper.Convert(pInNode);
  1112.                                 if (pXmlProceduralParams)
  1113.                                 {
  1114.                                         CryLogAlways("Converted old format procedural clip with type name '%s' at line '%d'.", safeTypeName, pInNode->getLine());
  1115.                                 }
  1116.                                 else
  1117.                                 {
  1118.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Failed to convert old format procedural clip with type name '%s' at line '%d'.", safeTypeName, pInNode->getLine());
  1119.                                         return false;
  1120.                                 }
  1121.                         }
  1122.                 }
  1123.  
  1124.                 if (!pXmlProceduralParams)
  1125.                 {
  1126.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Failed loading procedural parameters for clip with type name '%s' at line '%d': Unable to find 'ProceduralParams' xml node.", safeTypeName, pInNode->getLine());
  1127.                         return false;
  1128.                 }
  1129.                 if (!Serialization::LoadXmlNode(*outProceduralEntry.pProceduralParams, pXmlProceduralParams))
  1130.                 {
  1131.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Failed loading procedural parameters for clip with type name '%s' at line '%d': Unable to create Xml Input Archive for serialization.", safeTypeName, pInNode->getLine());
  1132.                         return false;
  1133.                 }
  1134.         }
  1135.  
  1136.         outProceduralEntry.typeNameHash = typeNameHash;
  1137.         return true;
  1138. }
  1139.  
  1140. void CAnimationDatabaseLibrary::FragmentToXML(XmlNodeRef outXmlFrag, const CFragment* fragment, bool transition) const
  1141. {
  1142.         const uint32 numLayers = fragment->m_animLayers.size();
  1143.         for (uint32 i = 0; i < numLayers; ++i)
  1144.         {
  1145.                 const TAnimClipSequence& sequence = fragment->m_animLayers[i];
  1146.  
  1147.                 XmlNodeRef xmlAnimLayer = outXmlFrag->createNode("AnimLayer");
  1148.                 outXmlFrag->addChild(xmlAnimLayer);
  1149.  
  1150.                 const uint32 numClips = sequence.size();
  1151.                 for (uint32 c = 0; c < numClips; c++)
  1152.                 {
  1153.                         const SAnimClip& animClip = sequence[c];
  1154.  
  1155.                         XmlNodeRef xmlBlend = xmlAnimLayer->createNode("Blend");
  1156.                         BlendToXML(xmlBlend, animClip.blend, "Blend");
  1157.                         xmlAnimLayer->addChild(xmlBlend);
  1158.  
  1159.                         const bool blendOnly = transition && (c == numClips - 1);
  1160.                         if (!blendOnly)
  1161.                         {
  1162.                                 XmlNodeRef xmlClip = xmlAnimLayer->createNode("Animation");
  1163.                                 AnimEntryToXML(xmlClip, animClip.animation, "Animation");
  1164.                                 xmlAnimLayer->addChild(xmlClip);
  1165.                         }
  1166.                 }
  1167.         }
  1168.         const uint32 numProcLayers = fragment->m_procLayers.size();
  1169.         for (uint32 i = 0; i < numProcLayers; ++i)
  1170.         {
  1171.                 const TProcClipSequence& sequence = fragment->m_procLayers[i];
  1172.  
  1173.                 XmlNodeRef xmlProcLayer = outXmlFrag->createNode("ProcLayer");
  1174.                 outXmlFrag->addChild(xmlProcLayer);
  1175.  
  1176.                 const uint32 numClips = sequence.size();
  1177.                 for (uint32 c = 0; c < numClips; c++)
  1178.                 {
  1179.                         const SProceduralEntry& procClip = sequence[c];
  1180.  
  1181.                         XmlNodeRef xmlBlend = xmlProcLayer->createNode("Blend");
  1182.                         BlendToXML(xmlBlend, procClip.blend, "Blend");
  1183.                         xmlProcLayer->addChild(xmlBlend);
  1184.  
  1185.                         const bool blendOnly = transition && (c == numClips - 1);
  1186.                         if (!blendOnly)
  1187.                         {
  1188.                                 XmlNodeRef xmlClip = xmlProcLayer->createNode("Procedural");
  1189.                                 ProceduralToXml(xmlClip, procClip);
  1190.                                 xmlProcLayer->addChild(xmlClip);
  1191.                         }
  1192.                 }
  1193.         }
  1194.  
  1195.         outXmlFrag->setAttr("BlendOutDuration", fragment->m_blendOutDuration);
  1196. }
  1197.  
  1198. bool CAnimationDatabaseLibrary::XMLToFragment(CFragment& fragment, XmlNodeRef root, bool transition) const
  1199. {
  1200.         const uint32 numChildren = root->getChildCount();
  1201.         uint32 numAnimLayers = 0;
  1202.         uint32 numProcLayers = 0;
  1203.  
  1204.         root->getAttr("BlendOutDuration", fragment.m_blendOutDuration);
  1205.  
  1206.         for (uint32 i = 0; i < numChildren; ++i)
  1207.         {
  1208.                 XmlNodeRef xmlLayer = root->getChild(i);
  1209.  
  1210.                 if (strcmp(xmlLayer->getTag(), "AnimLayer") == 0)
  1211.                 {
  1212.                         ++numAnimLayers;
  1213.                 }
  1214.                 else if (strcmp(xmlLayer->getTag(), "ProcLayer") == 0)
  1215.                 {
  1216.                         ++numProcLayers;
  1217.                 }
  1218.                 else
  1219.                 {
  1220.                         return false;
  1221.                 }
  1222.         }
  1223.  
  1224.         fragment.m_animLayers.resize(numAnimLayers);
  1225.         fragment.m_procLayers.resize(numProcLayers);
  1226.  
  1227.         uint32 animLayer = 0;
  1228.         uint32 procLayer = 0;
  1229.         for (uint32 i = 0; i < numChildren; ++i)
  1230.         {
  1231.                 XmlNodeRef xmlLayer = root->getChild(i);
  1232.  
  1233.                 if (strcmp(xmlLayer->getTag(), "AnimLayer") == 0)
  1234.                 {
  1235.                         const uint32 numEntries = xmlLayer->getChildCount();
  1236.                         const uint32 transitionInc = transition ? 1 : 0;
  1237.                         const uint32 numClips = (numEntries / 2) + transitionInc;
  1238.  
  1239.                         TAnimClipSequence& sequence = fragment.m_animLayers[animLayer];
  1240.                         sequence.resize(numClips);
  1241.  
  1242.                         uint32 clipNumber = 0;
  1243.                         for (uint32 e = 0; e < numEntries; ++e)
  1244.                         {
  1245.                                 XmlNodeRef xmlChild = xmlLayer->getChild(e);
  1246.                                 SAnimClip& animClip = sequence[clipNumber];
  1247.                                 if (strcmp(xmlChild->getTag(), "Blend") == 0)
  1248.                                 {
  1249.                                         XMLToBlend(animClip.blend, xmlChild);
  1250.                                 }
  1251.                                 else if (strcmp(xmlChild->getTag(), "Animation") == 0)
  1252.                                 {
  1253.                                         XMLToAnimEntry(animClip.animation, xmlChild);
  1254.                                         ++clipNumber;
  1255.                                 }
  1256.                         }
  1257.  
  1258.                         ++animLayer;
  1259.                 }
  1260.                 else if (strcmp(xmlLayer->getTag(), "ProcLayer") == 0)
  1261.                 {
  1262.                         const uint32 numEntries = xmlLayer->getChildCount();
  1263.                         const uint32 transitionInc = transition ? 1 : 0;
  1264.                         const uint32 numClips = (numEntries / 2) + transitionInc;
  1265.  
  1266.                         TProcClipSequence& sequence = fragment.m_procLayers[procLayer];
  1267.                         sequence.resize(numClips);
  1268.  
  1269.                         uint32 clipNumber = 0;
  1270.                         for (uint32 e = 0; e < numEntries; ++e)
  1271.                         {
  1272.                                 XmlNodeRef xmlChild = xmlLayer->getChild(e);
  1273.                                 SProceduralEntry& proceduralEntry = sequence[clipNumber];
  1274.                                 if (strcmp(xmlChild->getTag(), "Procedural") == 0)
  1275.                                 {
  1276.                                         XmlToProcedural(xmlChild, proceduralEntry);
  1277.                                         clipNumber++;
  1278.                                 }
  1279.                                 else if (strcmp(xmlChild->getTag(), "Blend") == 0)
  1280.                                 {
  1281.                                         XMLToBlend(proceduralEntry.blend, xmlChild);
  1282.                                 }
  1283.                         }
  1284.  
  1285.                         ++procLayer;
  1286.                 }
  1287.         }
  1288.  
  1289.         return true;
  1290. }
  1291.  
  1292. void CAnimationDatabaseLibrary::LoadDatabaseData
  1293. (
  1294.   CAnimationDatabase& animDB,
  1295.   const XmlNodeRef root,
  1296.   const CTagDefinition& fragIDs,
  1297.   const CTagDefinition& tagIDs,
  1298.   const TagState& adbFilter,
  1299.   bool recursive,
  1300.   CAnimationDatabase::SSubADB* subAnimDB
  1301. )
  1302. {
  1303.         if (recursive)
  1304.         {
  1305.                 XmlNodeRef subADBs = root->findChild("SubADBs");
  1306.                 const uint32 numSubADBs = subADBs ? subADBs->getChildCount() : 0;
  1307.                 for (uint32 i = 0; i < numSubADBs; ++i)
  1308.                 {
  1309.                         XmlNodeRef adbEntry = subADBs->getChild(i);
  1310.                         const char* tags = adbEntry->getAttr("Tags");
  1311.  
  1312.                         TagState subTags(TAG_STATE_EMPTY);
  1313.                         bool tagsMatched = false;
  1314.                         bool hasTags = (tags && strlen(tags) > 0);
  1315.                         if (hasTags)
  1316.                                 tagsMatched = tagIDs.TagListToFlags(tags, subTags);
  1317.  
  1318.                         char normalizedFilename[DEF_PATH_LENGTH];
  1319.                         NormalizeFilename(normalizedFilename, adbEntry->getAttr("File"));
  1320.  
  1321.                         CAnimationDatabase::SSubADB newSubADB;
  1322.                         newSubADB.tags = tagIDs.GetUnion(adbFilter, subTags);
  1323.                         newSubADB.comparisonMask = tagIDs.GenerateMask(newSubADB.tags);
  1324.                         newSubADB.filename = normalizedFilename;
  1325.  
  1326.                         CryLog("Loading subADB %s", normalizedFilename);
  1327.  
  1328.                         XmlNodeRef xmlData = gEnv->pSystem->GetXmlUtils()->LoadXmlFromFile(normalizedFilename);
  1329.                         if (xmlData && LoadDatabaseDefinitions(xmlData, animDB.m_filename.c_str(), &newSubADB.pFragDef, &newSubADB.pTagDef))
  1330.                         {
  1331.                                 //--- Create a mask of valid tags
  1332.                                 if (newSubADB.pTagDef == &tagIDs)
  1333.                                 {
  1334.                                         newSubADB.knownTags = TAG_STATE_FULL;
  1335.                                 }
  1336.                                 else
  1337.                                 {
  1338.                                         newSubADB.knownTags = tagIDs.GetSharedTags(*newSubADB.pTagDef);
  1339.                                 }
  1340.  
  1341.                                 int numFragIDs = adbEntry->getChildCount();
  1342.                                 for (int j = 0; j < numFragIDs; ++j)
  1343.                                 {
  1344.                                         XmlNodeRef FragIDEntry = adbEntry->getChild(j);
  1345.                                         const char* szFragmentName = FragIDEntry->getAttr("Name");
  1346.                                         if (szFragmentName && strlen(szFragmentName) > 0)
  1347.                                         {
  1348.                                                 int fragmentID = newSubADB.pFragDef->Find(szFragmentName);
  1349.                                                 if (fragmentID != TAG_ID_INVALID)
  1350.                                                         newSubADB.vFragIDs.push_back(fragmentID);
  1351.                                         }
  1352.                                 }
  1353.                                 if (!tagsMatched && hasTags)
  1354.                                 {
  1355.                                         CryLog("[CAnimationDatabaseManager::LoadDatabase] Unknown tags %s for subADB %s", tags, adbEntry->getAttr("File"));
  1356.                                         continue;
  1357.                                 }
  1358.  
  1359.                                 LoadDatabaseData(animDB, xmlData, fragIDs, tagIDs, newSubADB.tags, recursive, &newSubADB);
  1360.                         }
  1361.                         else
  1362.                         {
  1363.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "!Could not load animation database (ADB) file '%s' (check the log for XML reader warnings)", normalizedFilename);
  1364.                                 continue;
  1365.                         }
  1366.  
  1367.                         if (!subAnimDB)
  1368.                                 animDB.m_subADBs.push_back(newSubADB);
  1369.                         else
  1370.                                 subAnimDB->subADBs.push_back(newSubADB);
  1371.  
  1372.                         SLICE_AND_SLEEP();
  1373.                 }
  1374.         }
  1375.  
  1376.         if (root)
  1377.         {
  1378.                 CFragment newFragment;
  1379.                 XmlNodeRef fragmentList = root->findChild("FragmentList");
  1380.                 uint32 numChildren = fragmentList ? fragmentList->getChildCount() : 0;
  1381.                 for (uint32 i = 0; i < numChildren; ++i)
  1382.                 {
  1383.                         XmlNodeRef fragmentEntry = fragmentList->getChild(i);
  1384.                         const char* szFragmentName = fragmentEntry->getTag();
  1385.                         int fragmentID = fragIDs.Find(szFragmentName);
  1386.  
  1387.                         if (fragmentID >= 0)
  1388.                         {
  1389.                                 const uint32 numOptions = fragmentEntry->getChildCount();
  1390.  
  1391.                                 for (uint32 k = 0; k < numOptions; ++k)
  1392.                                 {
  1393.                                         XmlNodeRef fragment = fragmentEntry->getChild(k);
  1394.  
  1395.                                         const char* globalTags = fragment->getAttr("Tags");
  1396.                                         const char* fragTags = fragment->getAttr("FragTags");
  1397.                                         SFragTagState tagState;
  1398.                                         bool tagsMatched = tagIDs.TagListToFlags(globalTags, tagState.globalTags);
  1399.                                         const CTagDefinition* pFragTagDef = fragIDs.GetSubTagDefinition(fragmentID);
  1400.                                         if (fragTags && pFragTagDef)
  1401.                                         {
  1402.                                                 tagsMatched = tagsMatched && pFragTagDef->TagListToFlags(fragTags, tagState.fragmentTags);
  1403.                                         }
  1404.  
  1405.                                         if (tagsMatched)
  1406.                                         {
  1407.                                                 newFragment.m_animLayers.clear();
  1408.                                                 newFragment.m_procLayers.clear();
  1409.                                                 if (!XMLToFragment(newFragment, fragment, false))
  1410.                                                 {
  1411.                                                         CryLog("[CAnimationDatabaseManager::LoadDatabase] Broken fragment entry for fragmentID %s tag %s fragTags %s", szFragmentName, globalTags, fragTags ? fragTags : "None");
  1412.                                                 }
  1413.                                                 else
  1414.                                                 {
  1415.                                                         animDB.AddEntry(fragmentID, tagState, newFragment);
  1416.                                                 }
  1417.                                         }
  1418.                                         else
  1419.                                         {
  1420.                                                 CryLog("[CAnimationDatabaseManager::LoadDatabase] Unknown tags for fragmentID %s tag %s fragTags %s", szFragmentName, globalTags, fragTags ? fragTags : "None");
  1421.                                         }
  1422.                                 }
  1423.                         }
  1424.                         else
  1425.                         {
  1426.                                 CryLog("[CAnimationDatabaseManager::LoadDatabase] Warning missing fragmentID %s", szFragmentName);
  1427.                         }
  1428.                 }
  1429.  
  1430.                 XmlNodeRef fragmentBlendList = root->findChild("FragmentBlendList");
  1431.                 const uint32 numFragmentBlends = fragmentBlendList ? fragmentBlendList->getChildCount() : 0;
  1432.                 for (uint32 i = 0; i < numFragmentBlends; ++i)
  1433.                 {
  1434.                         XmlNodeRef xmlBlendEntry = fragmentBlendList->getChild(i);
  1435.                         const char* fragFrom = xmlBlendEntry->getAttr("from");
  1436.                         const char* fragTo = xmlBlendEntry->getAttr("to");
  1437.                         int fragIDFrom = fragIDs.Find(fragFrom);
  1438.                         int fragIDTo = fragIDs.Find(fragTo);
  1439.  
  1440.                         const bool fragFromValid = (fragIDFrom != FRAGMENT_ID_INVALID) || (fragFrom[0] == '\0');
  1441.                         const bool fragToValid = (fragIDTo != FRAGMENT_ID_INVALID) || (fragTo[0] == '\0');
  1442.  
  1443.                         if (fragFromValid && fragToValid)
  1444.                         {
  1445.                                 const uint32 numVariants = xmlBlendEntry->getChildCount();
  1446.                                 for (uint32 v = 0; v < numVariants; ++v)
  1447.                                 {
  1448.                                         XmlNodeRef xmlVariant = xmlBlendEntry->getChild(v);
  1449.                                         const char* tagFrom = xmlVariant->getAttr("from");
  1450.                                         const char* tagTo = xmlVariant->getAttr("to");
  1451.                                         SFragTagState tsFrom, tsTo;
  1452.                                         bool tagStateMatched = tagIDs.TagListToFlags(tagFrom, tsFrom.globalTags);
  1453.                                         tagStateMatched = tagStateMatched && tagIDs.TagListToFlags(tagTo, tsTo.globalTags);
  1454.  
  1455.                                         const CTagDefinition* fragFromDef = (fragIDFrom != FRAGMENT_ID_INVALID) ? fragIDs.GetSubTagDefinition(fragIDFrom) : NULL;
  1456.                                         const CTagDefinition* fragToDef = (fragIDTo != FRAGMENT_ID_INVALID) ? fragIDs.GetSubTagDefinition(fragIDTo) : NULL;
  1457.                                         const char* fragTagFrom = xmlVariant->getAttr("fromFrag");
  1458.                                         const char* fragTagTo = xmlVariant->getAttr("toFrag");
  1459.  
  1460.                                         if (fragFromDef && fragTagFrom)
  1461.                                         {
  1462.                                                 tagStateMatched = tagStateMatched && fragFromDef->TagListToFlags(fragTagFrom, tsFrom.fragmentTags);
  1463.                                         }
  1464.                                         if (fragToDef && fragTagTo)
  1465.                                         {
  1466.                                                 tagStateMatched = tagStateMatched && fragToDef->TagListToFlags(fragTagTo, tsTo.fragmentTags);
  1467.                                         }
  1468.  
  1469.                                         if (tagStateMatched)
  1470.                                         {
  1471.                                                 const uint32 numBlends = xmlVariant->getChildCount();
  1472.                                                 for (uint32 b = 0; b < numBlends; ++b)
  1473.                                                 {
  1474.                                                         TagState tempTags;
  1475.                                                         XmlNodeRef xmlBlend = xmlVariant->getChild(b);
  1476.                                                         SFragmentBlend fragBlend;
  1477.                                                         xmlBlend->getAttr("selectTime", fragBlend.selectTime);
  1478.                                                         xmlBlend->getAttr("startTime", fragBlend.startTime);
  1479.                                                         xmlBlend->getAttr("enterTime", fragBlend.enterTime);
  1480.                                                         const char* szBlendFlags = xmlBlend->getAttr("flags");
  1481.  
  1482.                                                         if (szBlendFlags && szBlendFlags[0])
  1483.                                                         {
  1484.                                                                 m_transitionFlags.TagListToIntegerFlags(szBlendFlags, fragBlend.flags);
  1485.                                                         }
  1486.  
  1487.                                                         fragBlend.pFragment = new CFragment();
  1488.                                                         if ((xmlBlend->getChildCount() != 0) && !XMLToFragment(*fragBlend.pFragment, xmlBlend, true))
  1489.                                                         {
  1490.                                                                 delete fragBlend.pFragment;
  1491.                                                                 CryLog("[CAnimationDatabaseManager::LoadDatabase] Broken fragment entry for blend");
  1492.                                                         }
  1493.                                                         else
  1494.                                                         {
  1495.                                                                 animDB.AddBlendInternal(fragIDFrom, fragIDTo, tsFrom, tsTo, fragBlend);
  1496.                                                         }
  1497.                                                 }
  1498.                                         }
  1499.                                         else
  1500.                                         {
  1501.                                                 CryLog("[CAnimationDatabaseManager::LoadDatabase] Unknown tags for blend %s to %s tag %s+%s to %s+%s", fragFrom, fragTo, tagFrom, fragTagFrom ? fragTagFrom : "None", tagTo, fragTagTo ? fragTagTo : "None");
  1502.                                         }
  1503.                                 }
  1504.                         }
  1505.                 }
  1506.         }
  1507. }
  1508.  
  1509. bool CAnimationDatabaseLibrary::LoadDatabaseDefinitions(const XmlNodeRef& root, const char* filename, const CTagDefinition** ppFragDefs, const CTagDefinition** ppTagDefs)
  1510. {
  1511.         const char* szBuffer;
  1512.         szBuffer = root->getAttr("Def");
  1513.         if (szBuffer && szBuffer[0])
  1514.         {
  1515.                 const SControllerDef* def = gEnv->pGameFramework->GetMannequinInterface().GetAnimationDatabaseManager().LoadControllerDef(szBuffer);
  1516.                 if (def)
  1517.                 {
  1518.                         *ppFragDefs = &def->m_fragmentIDs;
  1519.                         *ppTagDefs = &def->m_tags;
  1520.                         return true;
  1521.                 }
  1522.                 else
  1523.                 {
  1524.                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "!Missing def file for database %s - skipping load", filename);
  1525.                         return false;
  1526.                 }
  1527.         }
  1528.  
  1529.         szBuffer = root->getAttr("FragDef");
  1530.         if (szBuffer && szBuffer[0])
  1531.         {
  1532.                 *ppFragDefs = gEnv->pGameFramework->GetMannequinInterface().GetAnimationDatabaseManager().LoadTagDefs(szBuffer, false);
  1533.         }
  1534.  
  1535.         if (*ppFragDefs == NULL)
  1536.         {
  1537.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "!Missing fragment definition file for database %s - skipping load", filename);
  1538.                 return false;
  1539.         }
  1540.  
  1541.         szBuffer = root->getAttr("TagDef");
  1542.         if (szBuffer && szBuffer[0])
  1543.         {
  1544.                 *ppTagDefs = gEnv->pGameFramework->GetMannequinInterface().GetAnimationDatabaseManager().LoadTagDefs(szBuffer, true);
  1545.         }
  1546.  
  1547.         if (*ppTagDefs == NULL)
  1548.         {
  1549.                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "!Missing tag definition file for database %s - skipping load", filename);
  1550.                 return false;
  1551.         }
  1552.  
  1553.         return true;
  1554. }
  1555.  
  1556. bool CAnimationDatabaseLibrary::LoadDatabase(const XmlNodeRef& root, CAnimationDatabase& animDB, bool recursive)
  1557. {
  1558.         if (stricmp(root->getTag(), "AnimDB") != 0)
  1559.         {
  1560.                 return false;
  1561.         }
  1562.  
  1563.         if (LoadDatabaseDefinitions(root, animDB.m_filename.c_str(), &animDB.m_pFragDef, &animDB.m_pTagDef))
  1564.         {
  1565.                 const uint32 numActions = animDB.m_pFragDef->GetNum();
  1566.  
  1567.                 animDB.SetAutoSort(false);
  1568.  
  1569.                 animDB.m_fragmentList.resize(numActions);
  1570.                 for (uint32 i = 0; i < numActions; ++i)
  1571.                 {
  1572.                         animDB.m_fragmentList[i] = new CAnimationDatabase::SFragmentEntry();
  1573.                 }
  1574.  
  1575.                 LoadDatabaseData(animDB, root, *animDB.m_pFragDef, *animDB.m_pTagDef, TAG_STATE_EMPTY, recursive);
  1576.  
  1577.                 animDB.Sort();
  1578.                 animDB.SetAutoSort(true);
  1579.  
  1580.                 return true;
  1581.         }
  1582.  
  1583.         return false;
  1584. }
  1585.  
  1586. bool CAnimationDatabaseManager::CanSaveFragmentID(FragmentID fragID, const CAnimationDatabase& animDB, const CAnimationDatabase::SSubADB* subAnimDB) const
  1587. {
  1588.         if (subAnimDB && (subAnimDB->pFragDef != animDB.m_pFragDef) && (fragID != FRAGMENT_ID_INVALID))
  1589.                 return subAnimDB->pFragDef->Find(animDB.m_pFragDef->GetTagName(fragID)) != FRAGMENT_ID_INVALID;
  1590.  
  1591.         return true;
  1592. }
  1593.  
  1594. bool CAnimationDatabaseManager::FragmentMatches(uint32 fragCRC, const TagState& tagState, const CAnimationDatabase::SSubADB& subAnimDB, bool& bTagMatchFound) const
  1595. {
  1596.         //--- If this fragmentID is not known by this subADB, then it can't go here
  1597.         if ((fragCRC != 0) && (subAnimDB.pFragDef->Find(fragCRC) == FRAGMENT_ID_INVALID))
  1598.                 return false;
  1599.  
  1600.         bTagMatchFound = false;
  1601.         bool bFragMatchFound = false;
  1602.         bool bMatchFound = false;
  1603.         if (!subAnimDB.tags.IsEmpty())
  1604.         {
  1605.                 const TagState tagStateADB = subAnimDB.tags;
  1606.                 const TagState maskADB = subAnimDB.comparisonMask;
  1607.                 if (subAnimDB.pTagDef->Contains(tagState, tagStateADB, maskADB) && (subAnimDB.pFragDef->Find(fragCRC) != FRAGMENT_ID_INVALID))
  1608.                         bTagMatchFound = ((subAnimDB.knownTags & tagState) == tagState);
  1609.         }
  1610.  
  1611.         if (!subAnimDB.vFragIDs.empty())
  1612.                 for (CAnimationDatabase::SSubADB::TFragIDList::const_iterator itFID = subAnimDB.vFragIDs.begin(); itFID != subAnimDB.vFragIDs.end(); ++itFID)
  1613.                         if (subAnimDB.pFragDef->GetTagCRC(*itFID) == fragCRC)
  1614.                                 bFragMatchFound = true;
  1615.  
  1616.         if ((subAnimDB.tags.IsEmpty() || bTagMatchFound) && (subAnimDB.vFragIDs.empty() || bFragMatchFound))
  1617.                 bMatchFound = true;
  1618.  
  1619.         return bMatchFound;
  1620. }
  1621.  
  1622. bool CAnimationDatabaseManager::ShouldSaveFragment(FragmentID fragID, const TagState& tagState, const CAnimationDatabase& animDB, const CAnimationDatabase::SSubADB* subAnimDB, bool& bTagMatchFound) const
  1623. {
  1624.         uint32 fragCRC = animDB.m_pFragDef->GetTagCRC(fragID);
  1625.         bTagMatchFound = false;
  1626.         if (!subAnimDB || FragmentMatches(fragCRC, tagState, *subAnimDB, bTagMatchFound))
  1627.         {
  1628.                 const CAnimationDatabase::TSubADBList& vSubADBs = subAnimDB ? subAnimDB->subADBs : animDB.m_subADBs;
  1629.  
  1630.                 if (vSubADBs.empty())
  1631.                 {
  1632.                         return true;
  1633.                 }
  1634.  
  1635.                 bool bDummy;
  1636.                 for (CAnimationDatabase::TSubADBList::const_iterator itSubADB = vSubADBs.begin(); itSubADB != vSubADBs.end(); ++itSubADB)
  1637.                         if (FragmentMatches(fragCRC, tagState, *itSubADB, bDummy))
  1638.                                 return false;
  1639.  
  1640.                 return true;
  1641.         }
  1642.  
  1643.         return !subAnimDB;
  1644. }
  1645.  
  1646. bool CAnimationDatabaseManager::TransitionMatches(uint32 fragCRCFrom, uint32 fragCRCTo, const TagState& tagStateFrom, const TagState& tagStateTo, const CTagDefinition& parentTagDefs, const CAnimationDatabase::SSubADB& subAnimDB, bool& bTagMatchFound) const
  1647. {
  1648.         //--- If these tags are not known by this subADB, then it can't go here
  1649.         const TagState totalTags = parentTagDefs.GetUnion(tagStateFrom, tagStateTo);
  1650.         if (((subAnimDB.knownTags & totalTags) != totalTags)
  1651.             || ((fragCRCFrom != 0) && (subAnimDB.pFragDef->Find(fragCRCFrom) == FRAGMENT_ID_INVALID))
  1652.             || ((fragCRCTo != 0) && (subAnimDB.pFragDef->Find(fragCRCTo) == FRAGMENT_ID_INVALID)))
  1653.         {
  1654.                 return false;
  1655.         }
  1656.  
  1657.         const TagState commonTags = parentTagDefs.GetIntersection(tagStateFrom, tagStateTo);
  1658.         bool bMatchFound = false;
  1659.         bTagMatchFound = false;
  1660.         bool bFragMatchFound = false;
  1661.         const TagState tagStateADB = subAnimDB.tags;
  1662.         const TagState maskADB = subAnimDB.comparisonMask;
  1663.         if (tagStateADB.IsEmpty() || parentTagDefs.Contains(commonTags, tagStateADB, maskADB))
  1664.         {
  1665.                 bTagMatchFound = true;
  1666.         }
  1667.  
  1668.         if (!subAnimDB.vFragIDs.empty() && (fragCRCFrom != 0 || fragCRCTo != 0))
  1669.         {
  1670.                 bool bFragMatchFoundFrom = false;
  1671.                 bool bFragMatchFoundTo = false;
  1672.                 for (CAnimationDatabase::SSubADB::TFragIDList::const_iterator itFID = subAnimDB.vFragIDs.begin(); itFID != subAnimDB.vFragIDs.end(); ++itFID)
  1673.                 {
  1674.                         if (subAnimDB.pFragDef->GetTagCRC(*itFID) == fragCRCFrom)
  1675.                                 bFragMatchFoundFrom = true;
  1676.  
  1677.                         if (subAnimDB.pFragDef->GetTagCRC(*itFID) == fragCRCTo)
  1678.                                 bFragMatchFoundTo = true;
  1679.                 }
  1680.                 bFragMatchFound = (bFragMatchFoundFrom || !fragCRCFrom) && (bFragMatchFoundTo || !fragCRCTo);
  1681.         }
  1682.  
  1683.         if (bTagMatchFound && (subAnimDB.vFragIDs.empty() || bFragMatchFound))
  1684.                 bMatchFound = true;
  1685.  
  1686.         return bMatchFound;
  1687. }
  1688.  
  1689. bool CAnimationDatabaseManager::ShouldSaveTransition
  1690. (
  1691.   FragmentID fragIDFrom,
  1692.   FragmentID fragIDTo,
  1693.   const TagState& tagStateFrom,
  1694.   const TagState& tagStateTo,
  1695.   const CAnimationDatabase& animDB,
  1696.   const CAnimationDatabase::SSubADB* subAnimDB,
  1697.   bool& bTagMatchFound
  1698. ) const
  1699. {
  1700.         //--- Special case rule: if this is an any to any then stick it at the top level, otherwise it'll go in the first match
  1701.         if ((fragIDFrom == FRAGMENT_ID_INVALID) && (fragIDTo == FRAGMENT_ID_INVALID))
  1702.         {
  1703.                 return (subAnimDB == NULL);
  1704.         }
  1705.  
  1706.         uint32 fragCRCFrom = (fragIDFrom == FRAGMENT_ID_INVALID) ? 0 : animDB.m_pFragDef->GetTagCRC(fragIDFrom);
  1707.         uint32 fragCRCTo = (fragIDTo == FRAGMENT_ID_INVALID) ? 0 : animDB.m_pFragDef->GetTagCRC(fragIDTo);
  1708.         if (!subAnimDB || TransitionMatches(fragCRCFrom, fragCRCTo, tagStateFrom, tagStateTo, *animDB.m_pTagDef, *subAnimDB, bTagMatchFound))
  1709.         {
  1710.                 const CAnimationDatabase::TSubADBList& vSubADBs = subAnimDB ? subAnimDB->subADBs : animDB.m_subADBs;
  1711.  
  1712.                 if (vSubADBs.empty())
  1713.                         return true;
  1714.  
  1715.                 bool bSubTag;
  1716.                 for (CAnimationDatabase::TSubADBList::const_iterator itSubADB = vSubADBs.begin(); itSubADB != vSubADBs.end(); ++itSubADB)
  1717.                         if (TransitionMatches(fragCRCFrom, fragCRCTo, tagStateFrom, tagStateTo, *animDB.m_pTagDef, *itSubADB, bSubTag))
  1718.                                 return false;
  1719.  
  1720.                 return true;
  1721.         }
  1722.  
  1723.         return !subAnimDB;
  1724. }
  1725.  
  1726. XmlNodeRef CAnimationDatabaseManager::SaveDatabase
  1727. (
  1728.   const CAnimationDatabase& animDB,
  1729.   const CAnimationDatabase::SSubADB* subAnimDB,
  1730.   const TFragmentSaveList& vFragSaveList,
  1731.   const TFragmentBlendSaveDatabase& mBlendSaveDatabase,
  1732.   bool bFlatten
  1733. ) const
  1734. {
  1735.         if (bFlatten && subAnimDB)
  1736.                 return XmlNodeRef();
  1737.  
  1738.         string sMyFileName = subAnimDB ? subAnimDB->filename : animDB.m_filename;
  1739.  
  1740.         XmlNodeRef root = GetISystem()->CreateXmlNode("AnimDB");
  1741.  
  1742.         if (subAnimDB)
  1743.         {
  1744.                 root->setAttr("FragDef", subAnimDB->pFragDef->GetFilename());
  1745.                 root->setAttr("TagDef", subAnimDB->pTagDef->GetFilename());
  1746.         }
  1747.         else
  1748.         {
  1749.                 root->setAttr("FragDef", animDB.m_pFragDef->GetFilename());
  1750.                 root->setAttr("TagDef", animDB.m_pTagDef->GetFilename());
  1751.         }
  1752.  
  1753.         const CAnimationDatabase::TSubADBList& vSubADBs = subAnimDB ? subAnimDB->subADBs : animDB.m_subADBs;
  1754.         const uint32 numSubADBs = vSubADBs.size();
  1755.         if (!vSubADBs.empty())
  1756.         {
  1757.                 XmlNodeRef subADBList;
  1758.  
  1759.                 for (CAnimationDatabase::TSubADBList::const_iterator itSubADB = vSubADBs.begin(); itSubADB != vSubADBs.end(); ++itSubADB)
  1760.                 {
  1761.                         const CAnimationDatabase::SSubADB& subADB = *itSubADB;
  1762.  
  1763.                         if (!subADBList)
  1764.                         {
  1765.                                 subADBList = root->createNode("SubADBs");
  1766.                                 root->addChild(subADBList);
  1767.                         }
  1768.  
  1769.                         XmlNodeRef adbEntry = subADBList->createNode("SubADB");
  1770.                         if (!subADB.tags.IsEmpty())
  1771.                         {
  1772.                                 CryStackStringT<char, 1024> sTags;
  1773.                                 animDB.m_pTagDef->FlagsToTagList(subADB.tags, sTags);
  1774.                                 adbEntry->setAttr("Tags", sTags.c_str());
  1775.                         }
  1776.                         adbEntry->setAttr("File", subADB.filename);
  1777.                         subADBList->addChild(adbEntry);
  1778.                         for (CAnimationDatabase::SSubADB::TFragIDList::const_iterator itFID = subADB.vFragIDs.begin(); itFID != subADB.vFragIDs.end(); ++itFID)
  1779.                         {
  1780.                                 XmlNodeRef FragmentIDEntry = adbEntry->createNode("FragmentID");
  1781.                                 FragmentIDEntry->setAttr("Name", subADB.pFragDef->GetTagName(*itFID));
  1782.                                 adbEntry->addChild(FragmentIDEntry);
  1783.                         }
  1784.                 }
  1785.         }
  1786.  
  1787.         XmlNodeRef fragmentList = root->createNode("FragmentList");
  1788.         root->addChild(fragmentList);
  1789.         for (uint32 i = 0; i < animDB.m_fragmentList.size(); ++i)
  1790.         {
  1791.                 if (CanSaveFragmentID(i, animDB, subAnimDB))
  1792.                 {
  1793.                         CAnimationDatabase::SFragmentEntry* entry = animDB.m_fragmentList[i];
  1794.                         const uint32 numTagSets = entry ? entry->tagSetList.Size() : 0;
  1795.                         if (numTagSets > 0)
  1796.                         {
  1797.                                 XmlNodeRef fragmentEntry;
  1798.  
  1799.                                 for (uint32 k = 0; k < numTagSets; k++)
  1800.                                 {
  1801.                                         const string& saveFileName = vFragSaveList[i].vSaveStates[k].m_sFileName;
  1802.                                         if (saveFileName == sMyFileName || bFlatten)
  1803.                                         {
  1804.                                                 if (!fragmentEntry)
  1805.                                                 {
  1806.                                                         fragmentEntry = root->createNode(animDB.m_pFragDef->GetTagName(i));
  1807.                                                         fragmentList->addChild(fragmentEntry);
  1808.                                                 }
  1809.  
  1810.                                                 const SFragTagState& tagState = entry->tagSetList.m_keys[k];
  1811.                                                 CAnimationDatabase::TFragmentOptionList& optionList = entry->tagSetList.m_values[k];
  1812.                                                 const uint32 numOptions = optionList.size();
  1813.                                                 for (uint32 o = 0; o < numOptions; ++o)
  1814.                                                 {
  1815.                                                         XmlNodeRef fragment = fragmentEntry->createNode("Fragment");
  1816.                                                         FragmentToXML(fragment, optionList[o].fragment, false);
  1817.  
  1818.                                                         CryStackStringT<char, 1024> sGlobalTags;
  1819.                                                         animDB.m_pTagDef->FlagsToTagList(tagState.globalTags, sGlobalTags);
  1820.                                                         fragment->setAttr("Tags", sGlobalTags.c_str());
  1821.  
  1822.                                                         const CTagDefinition* fragTagDef = animDB.m_pFragDef->GetSubTagDefinition(i);
  1823.                                                         if (fragTagDef && (tagState.fragmentTags != TAG_STATE_EMPTY))
  1824.                                                         {
  1825.                                                                 CryStackStringT<char, 1024> sFragmentTags;
  1826.                                                                 fragTagDef->FlagsToTagList(tagState.fragmentTags, sFragmentTags);
  1827.                                                                 fragment->setAttr("FragTags", sFragmentTags.c_str());
  1828.                                                         }
  1829.  
  1830.                                                         fragmentEntry->addChild(fragment);
  1831.                                                 }
  1832.                                         }
  1833.                                 }
  1834.                         }
  1835.                 }
  1836.         }
  1837.  
  1838.         if (!animDB.m_fragmentBlendDB.empty())
  1839.         {
  1840.                 XmlNodeRef fragmentBlendList = root->createNode("FragmentBlendList");
  1841.                 bool hasAnyBlends = false;
  1842.  
  1843.                 for (CAnimationDatabase::TFragmentBlendDatabase::const_iterator iter = animDB.m_fragmentBlendDB.begin(); iter != animDB.m_fragmentBlendDB.end(); ++iter)
  1844.                 {
  1845.                         const FragmentID fragIDFrom = iter->first.fragFrom;
  1846.                         const FragmentID fragIDTo = iter->first.fragTo;
  1847.  
  1848.                         if (CanSaveFragmentID(fragIDFrom, animDB, subAnimDB) && CanSaveFragmentID(fragIDTo, animDB, subAnimDB))
  1849.                         {
  1850.                                 XmlNodeRef pFragment = root->createNode("Blend");
  1851.                                 pFragment->setAttr("from", (fragIDFrom == FRAGMENT_ID_INVALID) ? "" : animDB.m_pFragDef->GetTagName(fragIDFrom));
  1852.                                 pFragment->setAttr("to", (fragIDTo == FRAGMENT_ID_INVALID) ? "" : animDB.m_pFragDef->GetTagName(fragIDTo));
  1853.  
  1854.                                 const CTagDefinition* fragFromDef = (fragIDFrom != FRAGMENT_ID_INVALID) ? animDB.m_pFragDef->GetSubTagDefinition(fragIDFrom) : NULL;
  1855.                                 const CTagDefinition* fragToDef = (fragIDTo != FRAGMENT_ID_INVALID) ? animDB.m_pFragDef->GetSubTagDefinition(fragIDTo) : NULL;
  1856.  
  1857.                                 bool hasAnyEntries = false;
  1858.  
  1859.                                 const uint32 numVars = iter->second.variantList.size();
  1860.                                 for (uint32 v = 0; v < numVars; ++v)
  1861.                                 {
  1862.                                         const CAnimationDatabase::SFragmentBlendVariant& variant = iter->second.variantList[v];
  1863.  
  1864.                                         TFragmentBlendSaveDatabase::const_iterator itSaveEntry = mBlendSaveDatabase.find(iter->first);
  1865.                                         if ((itSaveEntry != mBlendSaveDatabase.end() && itSaveEntry->second.vSaveStates[v].m_sFileName == sMyFileName) || bFlatten)
  1866.                                         {
  1867.                                                 hasAnyEntries = true;
  1868.                                                 hasAnyBlends = true;
  1869.                                                 XmlNodeRef xmlFragmentVariant = root->createNode("Variant");
  1870.                                                 pFragment->addChild(xmlFragmentVariant);
  1871.  
  1872.                                                 CryStackStringT<char, 1024> sGlobalTagsFrom;
  1873.                                                 animDB.m_pTagDef->FlagsToTagList(variant.tagsFrom.globalTags, sGlobalTagsFrom);
  1874.                                                 xmlFragmentVariant->setAttr("from", sGlobalTagsFrom.c_str());
  1875.  
  1876.                                                 CryStackStringT<char, 1024> sGlobalTagsTo;
  1877.                                                 animDB.m_pTagDef->FlagsToTagList(variant.tagsTo.globalTags, sGlobalTagsTo);
  1878.                                                 xmlFragmentVariant->setAttr("to", sGlobalTagsTo.c_str());
  1879.  
  1880.                                                 if ((variant.tagsFrom.fragmentTags != TAG_STATE_EMPTY) && fragFromDef)
  1881.                                                 {
  1882.                                                         CryStackStringT<char, 1024> sFragmentTags;
  1883.                                                         fragFromDef->FlagsToTagList(variant.tagsFrom.fragmentTags, sFragmentTags);
  1884.                                                         xmlFragmentVariant->setAttr("fromFrag", sFragmentTags.c_str());
  1885.                                                 }
  1886.  
  1887.                                                 if ((variant.tagsTo.fragmentTags != TAG_STATE_EMPTY) && fragToDef)
  1888.                                                 {
  1889.                                                         CryStackStringT<char, 1024> sFragmentTags;
  1890.                                                         fragToDef->FlagsToTagList(variant.tagsTo.fragmentTags, sFragmentTags);
  1891.                                                         xmlFragmentVariant->setAttr("toFrag", sFragmentTags.c_str());
  1892.                                                 }
  1893.  
  1894.                                                 const uint32 numBlends = variant.blendList.size();
  1895.                                                 for (uint32 b = 0; b < numBlends; ++b)
  1896.                                                 {
  1897.                                                         const SFragmentBlend& blend = variant.blendList[b];
  1898.  
  1899.                                                         XmlNodeRef xmlFragment = xmlFragmentVariant->createNode("Fragment");
  1900.                                                         FragmentToXML(xmlFragment, blend.pFragment, true);
  1901.                                                         xmlFragmentVariant->addChild(xmlFragment);
  1902.                                                         xmlFragment->setAttr("selectTime", blend.selectTime);
  1903.                                                         if (blend.startTime != 0.0f)
  1904.                                                         {
  1905.                                                                 xmlFragment->setAttr("startTime", blend.startTime);
  1906.                                                         }
  1907.                                                         xmlFragment->setAttr("enterTime", blend.enterTime);
  1908.  
  1909.                                                         if (blend.flags != 0)
  1910.                                                         {
  1911.                                                                 CryStackStringT<char, 1024> sFlags;
  1912.                                                                 m_transitionFlags.IntegerFlagsToTagList(blend.flags, sFlags);
  1913.                                                                 xmlFragment->setAttr("flags", sFlags.c_str());
  1914.                                                         }
  1915.                                                 }
  1916.                                         }
  1917.                                 }
  1918.  
  1919.                                 if (hasAnyEntries)
  1920.                                 {
  1921.                                         fragmentBlendList->addChild(pFragment);
  1922.                                 }
  1923.                         }
  1924.                 }
  1925.  
  1926.                 if (hasAnyBlends)
  1927.                 {
  1928.                         root->addChild(fragmentBlendList);
  1929.                 }
  1930.         }
  1931.  
  1932.         return root;
  1933. }
  1934.  
  1935. SControllerDef* CAnimationControllerDefLibrary::LoadControllerDef(const XmlNodeRef& root, const char* context)
  1936. {
  1937.         if (stricmp(root->getTag(), "ControllerDef") != 0)
  1938.         {
  1939.                 return NULL;
  1940.         }
  1941.  
  1942.         const char* szBuffer;
  1943.         const CTagDefinition* tagTD = NULL;
  1944.         const CTagDefinition* fragmentTD = NULL;
  1945.         CTagDefinition scopeTD;
  1946.  
  1947.         XmlNodeRef tagList = root->findChild("Tags");
  1948.         szBuffer = tagList ? tagList->getAttr("filename") : NULL;
  1949.         if (szBuffer)
  1950.         {
  1951.                 tagTD = gEnv->pGameFramework->GetMannequinInterface().GetAnimationDatabaseManager().LoadTagDefs(szBuffer, true);
  1952.         }
  1953.         XmlNodeRef fragList = root->findChild("Fragments");
  1954.         szBuffer = fragList ? fragList->getAttr("filename") : NULL;
  1955.         if (szBuffer)
  1956.         {
  1957.                 fragmentTD = gEnv->pGameFramework->GetMannequinInterface().GetAnimationDatabaseManager().LoadTagDefs(szBuffer, false);
  1958.         }
  1959.  
  1960.         {
  1961.                 XmlNodeRef scopeDefList = root->findChild("ScopeDefs");
  1962.                 if (scopeDefList)
  1963.                 {
  1964.                         const int scopeCount = scopeDefList->getChildCount();
  1965.                         for (int i = 0; i < scopeCount; ++i)
  1966.                         {
  1967.                                 XmlNodeRef xmlScopeNode = scopeDefList->getChild(i);
  1968.                                 const char* const scopeName = xmlScopeNode->getTag();
  1969.                                 scopeTD.AddTag(scopeName);
  1970.                         }
  1971.                         scopeTD.AssignBits();
  1972.                 }
  1973.         }
  1974.  
  1975.         if (tagTD && fragmentTD)
  1976.         {
  1977.                 SControllerDef* ret = new SControllerDef(*tagTD, *fragmentTD, scopeTD);
  1978.  
  1979.                 ret->m_fragmentDef.resize(fragmentTD->GetNum());
  1980.                 ret->m_scopeDef.resize(scopeTD.GetNum());
  1981.  
  1982.                 XmlNodeRef subContextList = root->findChild("SubContexts");
  1983.                 const uint32 numSubContexts = subContextList ? subContextList->getChildCount() : 0;
  1984.                 for (uint32 i = 0; i < numSubContexts; i++)
  1985.                 {
  1986.                         XmlNodeRef xmlSubContextEntry = subContextList->getChild(i);
  1987.                         ret->m_subContextIDs.AddTag(xmlSubContextEntry->getTag());
  1988.  
  1989.                         SSubContext subContext;
  1990.                         tagTD->TagListToFlags(xmlSubContextEntry->getAttr("tags"), subContext.additionalTags);
  1991.                         scopeTD.TagListToIntegerFlags(xmlSubContextEntry->getAttr("scopes"), subContext.scopeMask);
  1992.                         ret->m_subContext.push_back(subContext);
  1993.                 }
  1994.  
  1995.                 XmlNodeRef fragDefList = root->findChild("FragmentDefs");
  1996.                 DynArray<bool> loadedFragmentDefs(fragmentTD->GetNum(), false);
  1997.                 const uint32 numFragDefs = fragDefList ? fragDefList->getChildCount() : 0;
  1998.                 for (uint32 i = 0; i < numFragDefs; ++i)
  1999.                 {
  2000.                         XmlNodeRef xmlFragDefEntry = fragDefList->getChild(i);
  2001.  
  2002.                         uint32 fragID = fragmentTD->Find(xmlFragDefEntry->getTag());
  2003.                         if (fragID != FRAGMENT_ID_INVALID)
  2004.                         {
  2005.                                 if (!loadedFragmentDefs[fragID])
  2006.                                 {
  2007.                                         loadedFragmentDefs[fragID] = true;
  2008.                                         const char* fragDefFlags = xmlFragDefEntry->getAttr("flags");
  2009.                                         ActionScopes scopeMask = 0;
  2010.                                         scopeTD.TagListToIntegerFlags(xmlFragDefEntry->getAttr("scopes"), scopeMask);
  2011.                                         SFragmentDef& fragmentDef = ret->m_fragmentDef[fragID];
  2012.                                         SFragTagState fragTagState;
  2013.                                         fragmentDef.scopeMaskList.Insert(fragTagState, scopeMask);
  2014.                                         if (fragDefFlags && fragDefFlags[0])
  2015.                                         {
  2016.                                                 m_fragmentFlags.TagListToIntegerFlags(fragDefFlags, fragmentDef.flags);
  2017.                                         }
  2018.                                         const CTagDefinition* pFragTagDef = fragmentTD->GetSubTagDefinition(fragID);
  2019.  
  2020.                                         const uint32 numTags = xmlFragDefEntry->getChildCount();
  2021.                                         for (uint32 t = 0; t < numTags; ++t)
  2022.                                         {
  2023.                                                 XmlNodeRef xmlFragTag = xmlFragDefEntry->getChild(t);
  2024.  
  2025.                                                 const char* tags = xmlFragTag->getAttr("tags");
  2026.                                                 const char* fragTags = xmlFragTag->getAttr("fragTags");
  2027.                                                 const char* scopes = xmlFragTag->getAttr("scopes");
  2028.  
  2029.                                                 bool success = tagTD->TagListToFlags(tags, fragTagState.globalTags);
  2030.                                                 fragTagState.fragmentTags = TAG_STATE_EMPTY;
  2031.                                                 if (pFragTagDef && fragTags)
  2032.                                                 {
  2033.                                                         success = success && pFragTagDef->TagListToFlags(fragTags, fragTagState.fragmentTags);
  2034.                                                 }
  2035.                                                 success = success && scopeTD.TagListToIntegerFlags(scopes, scopeMask);
  2036.  
  2037.                                                 if (success)
  2038.                                                 {
  2039.                                                         fragmentDef.scopeMaskList.Insert(fragTagState, scopeMask);
  2040.                                                 }
  2041.                                         }
  2042.  
  2043.                                         fragmentDef.scopeMaskList.Sort(*tagTD, pFragTagDef);
  2044.                                 }
  2045.                                 else
  2046.                                 {
  2047.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Skipping duplicate fragment '%s' in %s", xmlFragDefEntry->getTag(), context);
  2048.                                 }
  2049.                         }
  2050.                         else
  2051.                         {
  2052.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Skipping unknown fragment '%s' in %s", xmlFragDefEntry->getTag(), context);
  2053.                         }
  2054.                 }
  2055.  
  2056.                 //--- Load in explicit scope contexts if they exist
  2057.                 XmlNodeRef scopeContextDefList = root->findChild("ScopeContextDefs");
  2058.                 if (scopeContextDefList)
  2059.                 {
  2060.                         const uint32 numScopeContextDefs = scopeContextDefList->getChildCount();
  2061.                         ret->m_scopeContextDef.reserve(numScopeContextDefs);
  2062.                         for (uint32 i = 0; i < numScopeContextDefs; ++i)
  2063.                         {
  2064.                                 XmlNodeRef xmlScopeContextDefEntry = scopeContextDefList->getChild(i);
  2065.                                 const char* contextName = xmlScopeContextDefEntry->getTag();
  2066.                                 if (ret->m_scopeContexts.Find(contextName) >= 0)
  2067.                                 {
  2068.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Duplicate scope context '%s' referenced in scopecontextdefs in %s", contextName, context);
  2069.                                 }
  2070.                                 else
  2071.                                 {
  2072.                                         TagID contextID = ret->m_scopeContexts.AddTag(contextName);
  2073.                                         ret->m_scopeContextDef.push_back();
  2074.                                         SScopeContextDef& contextDef = ret->m_scopeContextDef[contextID];
  2075.                                         if (xmlScopeContextDefEntry->haveAttr("tags"))
  2076.                                         {
  2077.                                                 tagTD->TagListToFlags(xmlScopeContextDefEntry->getAttr("tags"), contextDef.additionalTags);
  2078.                                         }
  2079.                                         if (xmlScopeContextDefEntry->haveAttr("sharedTags"))
  2080.                                         {
  2081.                                                 tagTD->TagListToFlags(xmlScopeContextDefEntry->getAttr("sharedTags"), contextDef.sharedTags);
  2082.                                         }
  2083.                                 }
  2084.                         }
  2085.                 }
  2086.  
  2087.                 XmlNodeRef scopeDefList = root->findChild("ScopeDefs");
  2088.                 DynArray<bool> loadedScopeDefs(scopeTD.GetNum(), false);
  2089.                 const uint32 numScopeDefs = scopeDefList ? scopeDefList->getChildCount() : 0;
  2090.  
  2091.                 assert(numScopeDefs <= sizeof(ActionScopes) * 8);
  2092.  
  2093.                 for (uint32 i = 0; i < numScopeDefs; ++i)
  2094.                 {
  2095.                         XmlNodeRef xmlScopeDefEntry = scopeDefList->getChild(i);
  2096.  
  2097.                         int scopeID = scopeTD.Find(xmlScopeDefEntry->getTag());
  2098.                         if (scopeID < 0)
  2099.                         {
  2100.                                 CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Skipping unknown scope '%s' referenced in scopedefs in %s", xmlScopeDefEntry->getTag(), context);
  2101.                         }
  2102.                         else
  2103.                         {
  2104.                                 if (!loadedScopeDefs[scopeID])
  2105.                                 {
  2106.                                         xmlScopeDefEntry->getAttr("layer", ret->m_scopeDef[scopeID].layer);
  2107.                                         xmlScopeDefEntry->getAttr("numLayers", ret->m_scopeDef[scopeID].numLayers);
  2108.                                         const char* szScopeAlias = xmlScopeDefEntry->getAttr("scopeAlias");
  2109.                                         ret->m_scopeDef[scopeID].scopeAlias = (szScopeAlias && szScopeAlias[0]) ? szScopeAlias : scopeTD.GetTagName(scopeID);
  2110.                                         const char* contextName = xmlScopeDefEntry->getAttr("context");
  2111.                                         tagTD->TagListToFlags(xmlScopeDefEntry->getAttr("Tags"), ret->m_scopeDef[scopeID].additionalTags);
  2112.                                         int contextID = ret->m_scopeContexts.Find(contextName);
  2113.                                         if (contextID < 0)
  2114.                                         {
  2115.                                                 contextID = ret->m_scopeContexts.AddTag(contextName);
  2116.                                                 ret->m_scopeContextDef.push_back();
  2117.                                         }
  2118.                                         ret->m_scopeDef[scopeID].context = contextID;
  2119.                                 }
  2120.                                 else
  2121.                                 {
  2122.                                         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_WARNING, "Skipping duplicate scope '%s' in %s", xmlScopeDefEntry->getTag(), context);
  2123.                                 }
  2124.                         }
  2125.                 }
  2126.  
  2127.                 return ret;
  2128.         }
  2129.  
  2130.         CryWarning(VALIDATOR_MODULE_GAME, VALIDATOR_ERROR, "Tags, Fragments or Scopes missing in %s", context);
  2131.         return NULL;
  2132. }
  2133.  
  2134. XmlNodeRef CAnimationDatabaseManager::SaveControllerDef(const SControllerDef& controllerDef) const
  2135. {
  2136.         XmlNodeRef root = GetISystem()->CreateXmlNode("ControllerDef");
  2137.  
  2138.         XmlNodeRef tagList = root->createNode("Tags");
  2139.         root->addChild(tagList);
  2140.         tagList->setAttr("filename", controllerDef.m_tags.GetFilename());
  2141.  
  2142.         XmlNodeRef fragList = root->createNode("Fragments");
  2143.         root->addChild(fragList);
  2144.         fragList->setAttr("filename", controllerDef.m_fragmentIDs.GetFilename());
  2145.  
  2146.         const uint32 numTagContexts = controllerDef.m_subContextIDs.GetNum();
  2147.         if (numTagContexts > 0)
  2148.         {
  2149.                 XmlNodeRef subContextList = root->createNode("SubContexts");
  2150.                 root->addChild(subContextList);
  2151.  
  2152.                 for (uint32 i = 0; i < numTagContexts; i++)
  2153.                 {
  2154.                         const SSubContext& subContext = controllerDef.m_subContext[i];
  2155.                         XmlNodeRef xmlSubContextEntry = root->createNode(controllerDef.m_subContextIDs.GetTagName(i));
  2156.                         subContextList->addChild(xmlSubContextEntry);
  2157.  
  2158.                         if (subContext.scopeMask != ACTION_SCOPES_NONE)
  2159.                         {
  2160.                                 CryStackStringT<char, 1024> sScopeMask;
  2161.                                 controllerDef.m_scopeIDs.IntegerFlagsToTagList(subContext.scopeMask, sScopeMask);
  2162.                                 xmlSubContextEntry->setAttr("scopes", sScopeMask.c_str());
  2163.                         }
  2164.  
  2165.                         if (subContext.additionalTags != TAG_STATE_EMPTY)
  2166.                         {
  2167.                                 CryStackStringT<char, 1024> sAdditionalTags;
  2168.                                 controllerDef.m_tags.FlagsToTagList(subContext.additionalTags, sAdditionalTags);
  2169.                                 xmlSubContextEntry->setAttr("tags", sAdditionalTags.c_str());
  2170.                         }
  2171.                 }
  2172.         }
  2173.  
  2174.         XmlNodeRef tagDefList = root->createNode("FragmentDefs");
  2175.         root->addChild(tagDefList);
  2176.         const uint32 numFrags = controllerDef.m_fragmentDef.size();
  2177.         for (uint32 i = 0; i < numFrags; ++i)
  2178.         {
  2179.                 const SFragmentDef& fragDef = controllerDef.m_fragmentDef[i];
  2180.                 const CTagDefinition* pFragTagDef = controllerDef.GetFragmentTagDef(i);
  2181.                 ActionScopes scopeMask = fragDef.scopeMaskList.GetDefault();
  2182.  
  2183.                 XmlNodeRef xmlFragDef = tagDefList->createNode(controllerDef.m_fragmentIDs.GetTagName(i));
  2184.                 tagDefList->addChild(xmlFragDef);
  2185.  
  2186.                 if (scopeMask != 0)
  2187.                 {
  2188.                         CryStackStringT<char, 1024> sScopeMask;
  2189.                         controllerDef.m_scopeIDs.IntegerFlagsToTagList(scopeMask, sScopeMask);
  2190.                         xmlFragDef->setAttr("scopes", sScopeMask.c_str());
  2191.                 }
  2192.  
  2193.                 //if (fragDef.tagDef)
  2194.                 //{
  2195.                 //      xmlFragDef->setAttr("tags", fragDef.tagDef->GetFilename());
  2196.                 //}
  2197.                 if (fragDef.flags)
  2198.                 {
  2199.                         CryStackStringT<char, 1024> sFlags;
  2200.                         m_fragmentFlags.IntegerFlagsToTagList(fragDef.flags, sFlags);
  2201.                         xmlFragDef->setAttr("flags", sFlags.c_str());
  2202.                 }
  2203.  
  2204.                 const uint32 numTags = fragDef.scopeMaskList.Size();
  2205.                 for (uint32 t = 0; t < numTags - 1; ++t)
  2206.                 {
  2207.                         const SFragTagState& fragTagState = fragDef.scopeMaskList.m_keys[t];
  2208.                         const ActionScopes& actionScope = fragDef.scopeMaskList.m_values[t];
  2209.  
  2210.                         XmlNodeRef xmlOverrideDef = tagDefList->createNode("Override");
  2211.                         xmlFragDef->addChild(xmlOverrideDef);
  2212.  
  2213.                         CryStackStringT<char, 1024> sGlobalTags;
  2214.                         controllerDef.m_tags.FlagsToTagList(fragTagState.globalTags, sGlobalTags);
  2215.                         xmlOverrideDef->setAttr("tags", sGlobalTags.c_str());
  2216.  
  2217.                         if (pFragTagDef && (fragTagState.fragmentTags != TAG_STATE_EMPTY))
  2218.                         {
  2219.                                 CryStackStringT<char, 1024> sFragmentTags;
  2220.                                 pFragTagDef->FlagsToTagList(fragTagState.fragmentTags, sFragmentTags);
  2221.                                 xmlOverrideDef->setAttr("fragTags", sFragmentTags.c_str());
  2222.                         }
  2223.  
  2224.                         CryStackStringT<char, 1024> sActionScope;
  2225.                         controllerDef.m_scopeIDs.IntegerFlagsToTagList(actionScope, sActionScope);
  2226.                         xmlOverrideDef->setAttr("scopes", sActionScope.c_str());
  2227.                 }
  2228.         }
  2229.  
  2230.         XmlNodeRef scopeContextDefList = root->createNode("ScopeContextDefs");
  2231.         root->addChild(scopeContextDefList);
  2232.         const uint32 numScopeContexts = controllerDef.m_scopeContextDef.size();
  2233.         for (uint32 i = 0; i < numScopeContexts; ++i)
  2234.         {
  2235.                 const SScopeContextDef& scopeContextDef = controllerDef.m_scopeContextDef[i];
  2236.                 XmlNodeRef xmlScopeContextDef = scopeContextDefList->createNode(controllerDef.m_scopeContexts.GetTagName(i));
  2237.                 scopeContextDefList->addChild(xmlScopeContextDef);
  2238.                 if (scopeContextDef.additionalTags != TAG_STATE_EMPTY)
  2239.                 {
  2240.                         CryStackStringT<char, 1024> sAdditionalTags;
  2241.                         controllerDef.m_tags.FlagsToTagList(scopeContextDef.additionalTags, sAdditionalTags);
  2242.                         xmlScopeContextDef->setAttr("tags", sAdditionalTags.c_str());
  2243.                 }
  2244.                 if (scopeContextDef.sharedTags != TAG_STATE_FULL)
  2245.                 {
  2246.                         CryStackStringT<char, 1024> sSharedTags;
  2247.                         controllerDef.m_tags.FlagsToTagList(scopeContextDef.sharedTags, sSharedTags);
  2248.                         xmlScopeContextDef->setAttr("sharedTags", sSharedTags.c_str());
  2249.                 }
  2250.         }
  2251.  
  2252.         XmlNodeRef scopeDefList = root->createNode("ScopeDefs");
  2253.         root->addChild(scopeDefList);
  2254.         const uint32 numScopes = controllerDef.m_scopeDef.size();
  2255.         for (uint32 i = 0; i < numScopes; ++i)
  2256.         {
  2257.                 const SScopeDef& scopeDef = controllerDef.m_scopeDef[i];
  2258.  
  2259.                 XmlNodeRef xmlScopeDef = scopeDefList->createNode(controllerDef.m_scopeIDs.GetTagName(i));
  2260.                 scopeDefList->addChild(xmlScopeDef);
  2261.                 xmlScopeDef->setAttr("layer", scopeDef.layer);
  2262.                 xmlScopeDef->setAttr("numLayers", scopeDef.numLayers);
  2263.                 if (0 != strcmp(scopeDef.scopeAlias.c_str(), controllerDef.m_scopeIDs.GetTagName(i)))
  2264.                 {
  2265.                         xmlScopeDef->setAttr("scopeAlias", scopeDef.scopeAlias.c_str());
  2266.                 }
  2267.                 const char* scopeContextName = controllerDef.m_scopeContexts.GetTagName(scopeDef.context);
  2268.                 xmlScopeDef->setAttr("context", scopeContextName);
  2269.                 if (scopeDef.additionalTags != TAG_STATE_EMPTY)
  2270.                 {
  2271.                         CryStackStringT<char, 1024> sAdditionalTags;
  2272.                         controllerDef.m_tags.FlagsToTagList(scopeDef.additionalTags, sAdditionalTags);
  2273.                         xmlScopeDef->setAttr("Tags", sAdditionalTags.c_str());
  2274.                 }
  2275.         }
  2276.         return root;
  2277. }
  2278.  
  2279. EModifyFragmentIdResult CAnimationDatabaseManager::CreateFragmentID(const CTagDefinition& inFragmentIds, const char* szFragmentIdName)
  2280. {
  2281.         const bool validFragmentIdName = IsValidNameIdentifier(szFragmentIdName);
  2282.         if (!validFragmentIdName)
  2283.         {
  2284.                 return eMFIR_InvalidNameIdentifier;
  2285.         }
  2286.  
  2287.         const char* fragmentDefFilename = inFragmentIds.GetFilename();
  2288.         const uint32 fragmentDefFilenameCrc = CCrc32::ComputeLowercase(fragmentDefFilename);
  2289.  
  2290.         CTagDefinition* fragmentDefs = stl::find_in_map(m_tagDefs, fragmentDefFilenameCrc, NULL);
  2291.         assert(fragmentDefs);
  2292.         if (!fragmentDefs)
  2293.         {
  2294.                 return eMFIR_UnknownInputTagDefinition;
  2295.         }
  2296.  
  2297.         const int fragmentTagId = fragmentDefs->Find(szFragmentIdName);
  2298.         const bool fragmentTagIdFound = (fragmentTagId != FRAGMENT_ID_INVALID);
  2299.         if (fragmentTagIdFound)
  2300.         {
  2301.                 return eMFIR_DuplicateName;
  2302.         }
  2303.  
  2304.         const int newFragmentTagId = fragmentDefs->AddTag(szFragmentIdName);
  2305.         assert(newFragmentTagId != FRAGMENT_ID_INVALID);
  2306.  
  2307.         for (TControllerDefList::const_iterator cit = m_controllerDefs.begin(); cit != m_controllerDefs.end(); ++cit)
  2308.         {
  2309.                 SControllerDef* controllerDef = cit->second;
  2310.                 const char* controllerFragmentDefFilename = controllerDef->m_fragmentIDs.GetFilename();
  2311.                 const uint32 controllerFragmentDefFilenameCrc = CCrc32::ComputeLowercase(controllerFragmentDefFilename);
  2312.                 const bool usingSameFragmentDef = (controllerFragmentDefFilenameCrc == fragmentDefFilenameCrc);
  2313.                 if (usingSameFragmentDef)
  2314.                 {
  2315.                         controllerDef->m_fragmentDef.push_back(SFragmentDef());
  2316.                 }
  2317.         }
  2318.  
  2319.         for (TAnimDatabaseList::const_iterator cit = m_databases.begin(); cit != m_databases.end(); ++cit)
  2320.         {
  2321.                 CAnimationDatabase* otherAnimDB = cit->second;
  2322.                 const char* otherDBFragmentDefFilename = otherAnimDB->GetFragmentDefs().GetFilename();
  2323.                 const uint32 otherDBFragmentDefFilenameCrc = CCrc32::ComputeLowercase(otherDBFragmentDefFilename);
  2324.                 const bool usingSameFragmentDef = (otherDBFragmentDefFilenameCrc == fragmentDefFilenameCrc);
  2325.                 if (usingSameFragmentDef)
  2326.                 {
  2327.                         CAnimationDatabase::SFragmentEntry* fragmentEntry = new CAnimationDatabase::SFragmentEntry();
  2328.                         assert(otherAnimDB->m_fragmentList.size() == newFragmentTagId);
  2329.                         otherAnimDB->m_fragmentList.push_back(fragmentEntry);
  2330.                 }
  2331.         }
  2332.  
  2333.         NotifyListenersTagDefinitionChanged(*fragmentDefs);
  2334.         return eMFIR_Success;
  2335. }
  2336.  
  2337. EModifyFragmentIdResult CAnimationDatabaseManager::RenameFragmentID(const CTagDefinition& fragmentIds, FragmentID fragmentID, const char* szFragmentIdName)
  2338. {
  2339.         if (fragmentID == FRAGMENT_ID_INVALID)
  2340.         {
  2341.                 return eMFIR_InvalidFragmentId;
  2342.         }
  2343.  
  2344.         const FragmentID fragmentIDCount = fragmentIds.GetNum();
  2345.         if (fragmentIDCount <= fragmentID)
  2346.         {
  2347.                 return eMFIR_InvalidFragmentId;
  2348.         }
  2349.  
  2350.         const bool validFragmentIdName = IsValidNameIdentifier(szFragmentIdName);
  2351.         if (!validFragmentIdName)
  2352.         {
  2353.                 return eMFIR_InvalidNameIdentifier;
  2354.         }
  2355.  
  2356.         const FragmentID foundFragmentIdWithDesiredName = fragmentIds.Find(szFragmentIdName);
  2357.         const bool duplicateFragmentIdName = ((foundFragmentIdWithDesiredName != FRAGMENT_ID_INVALID) && (foundFragmentIdWithDesiredName != fragmentID));
  2358.         if (duplicateFragmentIdName)
  2359.         {
  2360.                 return eMFIR_DuplicateName;
  2361.         }
  2362.  
  2363.         const char* fragmentDefFilename = fragmentIds.GetFilename();
  2364.         const uint32 fragmentDefFilenameCrc = CCrc32::ComputeLowercase(fragmentDefFilename);
  2365.  
  2366.         CTagDefinition* fragmentDefs = stl::find_in_map(m_tagDefs, fragmentDefFilenameCrc, NULL);
  2367.         assert(fragmentDefs);
  2368.         assert(fragmentDefs == &fragmentIds);
  2369.         if (!fragmentDefs)
  2370.         {
  2371.                 return eMFIR_UnknownInputTagDefinition;
  2372.         }
  2373.  
  2374.         fragmentDefs->SetTagName(fragmentID, szFragmentIdName);
  2375.  
  2376.         NotifyListenersTagDefinitionChanged(*fragmentDefs);
  2377.         return eMFIR_Success;
  2378. }
  2379.  
  2380. EModifyFragmentIdResult CAnimationDatabaseManager::DeleteFragmentID(const CTagDefinition& fragmentIds, FragmentID fragmentID)
  2381. {
  2382.         if (fragmentID == FRAGMENT_ID_INVALID)
  2383.                 return eMFIR_InvalidFragmentId;
  2384.  
  2385.         const FragmentID fragmentIDCount = fragmentIds.GetNum();
  2386.         if (fragmentIDCount <= fragmentID)
  2387.                 return eMFIR_InvalidFragmentId;
  2388.  
  2389.         const char* fragmentDefFilename = fragmentIds.GetFilename();
  2390.         const uint32 fragmentDefFilenameCrc = CCrc32::ComputeLowercase(fragmentDefFilename);
  2391.  
  2392.         CTagDefinition* fragmentDefs = stl::find_in_map(m_tagDefs, fragmentDefFilenameCrc, NULL);
  2393.         assert(fragmentDefs);
  2394.         assert(fragmentDefs == &fragmentIds);
  2395.         if (!fragmentDefs)
  2396.                 return eMFIR_UnknownInputTagDefinition;
  2397.  
  2398.         fragmentDefs->RemoveTag(fragmentID);
  2399.  
  2400.         for (TControllerDefList::const_iterator cit = m_controllerDefs.begin(); cit != m_controllerDefs.end(); ++cit)
  2401.         {
  2402.                 SControllerDef* controllerDef = cit->second;
  2403.                 const char* controllerFragmentDefFilename = controllerDef->m_fragmentIDs.GetFilename();
  2404.                 const uint32 controllerFragmentDefFilenameCrc = CCrc32::ComputeLowercase(controllerFragmentDefFilename);
  2405.                 const bool usingSameFragmentDef = (controllerFragmentDefFilenameCrc == fragmentDefFilenameCrc);
  2406.                 if (usingSameFragmentDef)
  2407.                 {
  2408.                         controllerDef->m_fragmentDef.erase(fragmentID);
  2409.                 }
  2410.         }
  2411.  
  2412.         for (TAnimDatabaseList::const_iterator it = m_databases.begin(), itEnd = m_databases.end(); it != itEnd; ++it)
  2413.         {
  2414.                 CAnimationDatabase* database = it->second;
  2415.                 const char* databaseFragmentDefFilename = database->GetFragmentDefs().GetFilename();
  2416.                 const uint32 databaseFragmentDefFilenameCrc = CCrc32::ComputeLowercase(databaseFragmentDefFilename);
  2417.                 const bool usingSameFragmentDef = (databaseFragmentDefFilenameCrc == fragmentDefFilenameCrc);
  2418.                 if (usingSameFragmentDef)
  2419.                 {
  2420.                         database->DeleteFragmentID(fragmentID);
  2421.                 }
  2422.         }
  2423.  
  2424.         NotifyListenersTagDefinitionChanged(*fragmentDefs);
  2425.         return eMFIR_Success;
  2426. }
  2427.  
  2428. bool CAnimationDatabaseManager::SetFragmentTagDef(const CTagDefinition& fragmentIds, FragmentID fragmentID, const CTagDefinition* pFragTagDefs)
  2429. {
  2430.         if (fragmentID == FRAGMENT_ID_INVALID)
  2431.                 return false;
  2432.  
  2433.         const char* fragmentDefFilename = fragmentIds.GetFilename();
  2434.         const uint32 fragmentDefFilenameCrc = CCrc32::ComputeLowercase(fragmentDefFilename);
  2435.  
  2436.         CTagDefinition* fragmentDefs = stl::find_in_map(m_tagDefs, fragmentDefFilenameCrc, NULL);
  2437.         assert(fragmentDefs);
  2438.         assert(fragmentDefs == &fragmentIds);
  2439.         if (fragmentDefs)
  2440.         {
  2441.                 fragmentDefs->SetSubTagDefinition(fragmentID, pFragTagDefs);
  2442.                 return true;
  2443.         }
  2444.  
  2445.         return false;
  2446. }
  2447.  
  2448. void CAnimationDatabaseManager::SetFragmentDef(const SControllerDef& inControllerDef, FragmentID fragmentID, const SFragmentDef& fragmentDef)
  2449. {
  2450.         if (fragmentID == FRAGMENT_ID_INVALID)
  2451.         {
  2452.                 return;
  2453.         }
  2454.  
  2455.         const char* controllerDefFilename = inControllerDef.m_filename.c_str();
  2456.         const uint32 controllerDefFilenameCrc = CCrc32::ComputeLowercase(controllerDefFilename);
  2457.  
  2458.         SControllerDef* controllerDef = stl::find_in_map(m_controllerDefs, controllerDefFilenameCrc, NULL);
  2459.         assert(controllerDef);
  2460.         if (!controllerDef)
  2461.         {
  2462.                 return;
  2463.         }
  2464.  
  2465.         DynArray<SFragmentDef>& fragmentDefs = controllerDef->m_fragmentDef;
  2466.         if (fragmentDefs.size() <= fragmentID)
  2467.         {
  2468.                 return;
  2469.         }
  2470.  
  2471.         fragmentDefs[fragmentID] = fragmentDef;
  2472. }
  2473.  
  2474. bool CAnimationDatabaseManager::DeleteFragmentEntry(IAnimationDatabase* pDatabaseInterface, FragmentID fragmentID, const SFragTagState& tagState, uint32 optionIdx, bool logWarning)
  2475. {
  2476.         assert(pDatabaseInterface);
  2477.         CAnimationDatabase* pDatabase = static_cast<CAnimationDatabase*>(pDatabaseInterface);
  2478.  
  2479.         bool successfullyDeleted = pDatabase->DeleteEntry(fragmentID, tagState, optionIdx);
  2480.  
  2481.         if (logWarning && !successfullyDeleted)
  2482.         {
  2483.                 CryWarning(VALIDATOR_MODULE_ANIMATION, VALIDATOR_WARNING, "AnimDatabaseManager: Invalid fragment entry: %d passed to %s", fragmentID, pDatabase->GetFilename());
  2484.         }
  2485.  
  2486.         int fragCRC = pDatabase->m_pFragDef->GetTagCRC(fragmentID);
  2487.  
  2488.         CryStackStringT<char, 1024> sTaglist;
  2489.         pDatabase->m_pTagDef->FlagsToTagList(tagState.globalTags, sTaglist);
  2490.         SFragTagState targetTagState = tagState;
  2491.  
  2492.         const std::vector<CAnimationDatabase*>& impactedDatabases = FindImpactedDatabases(pDatabase, fragmentID, tagState.globalTags);
  2493.         for (std::vector<CAnimationDatabase*>::const_iterator itDatabases = impactedDatabases.begin(); itDatabases != impactedDatabases.end(); ++itDatabases)
  2494.         {
  2495.                 CAnimationDatabase* pCurrDatabase = *itDatabases;
  2496.                 if (pCurrDatabase != pDatabase)
  2497.                 {
  2498.                         pCurrDatabase->m_pTagDef->TagListToFlags(sTaglist.c_str(), targetTagState.globalTags);
  2499.                         FragmentID targetFragID = pCurrDatabase->m_pFragDef->Find(fragCRC);
  2500.  
  2501.                         bool success = pCurrDatabase->DeleteEntry(targetFragID, targetTagState, optionIdx);
  2502.                         if (logWarning && !success)
  2503.