/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYACTION_ICRYMANNEQUINUSERPARAMS_H #define CRYINCLUDE_CRYACTION_ICRYMANNEQUINUSERPARAMS_H #pragma once struct IMannequinUserParams { virtual ~IMannequinUserParams() {} virtual void Init(const SControllerDef& controllerDef) = 0; }; class CMannequinUserParamId { public: CMannequinUserParamId(const SControllerDef& controllerDef, const uint32 paramType) : m_controllerDefPathCrc(0) , m_paramType(paramType) { m_controllerDefPathCrc = controllerDef.m_filename.crc; } bool operator == (const CMannequinUserParamId& rhs) const { return ((m_controllerDefPathCrc == rhs.m_controllerDefPathCrc) && (m_paramType == rhs.m_paramType)); } bool operator < (const CMannequinUserParamId& rhs) const { if (m_controllerDefPathCrc < rhs.m_controllerDefPathCrc) { return true; } else if (m_controllerDefPathCrc == rhs.m_controllerDefPathCrc) { return (m_paramType < rhs.m_paramType); } return false; } uint32 GetControllerDefCrc() const { return m_controllerDefPathCrc; } private: uint32 m_controllerDefPathCrc; uint32 m_paramType; }; class CMannequinUserParamsManager { public: CMannequinUserParamsManager() : m_autoIncValue(0) {} ~CMannequinUserParamsManager() { Clear(); } void Clear() { for (TMannequinOwnedUserParams::iterator it = m_ownedUserParams.begin(); it != m_ownedUserParams.end(); ++it) { IMannequinUserParams* pParams = *it; delete pParams; } m_userParams.clear(); m_ownedUserParams.clear(); } void ReloadAll(IAnimationDatabaseManager& animationDatabaseManager) { static CTagDefinition s_dummyTagDefinition; static SControllerDef s_dummyControllerDef(s_dummyTagDefinition, s_dummyTagDefinition, s_dummyTagDefinition); for (TMannequinUserParams::iterator it = m_userParams.begin(); it != m_userParams.end(); ++it) { SMannequinParamEntry& entry = *it; const CMannequinUserParamId& mannequinUserParamId = entry.paramId; const uint32 controllerDefCrc = mannequinUserParamId.GetControllerDefCrc(); const SControllerDef* pControllerDef = animationDatabaseManager.FindControllerDef(controllerDefCrc); CRY_ASSERT(pControllerDef != NULL); pControllerDef = pControllerDef ? pControllerDef : &s_dummyControllerDef; IMannequinUserParams* pParams = entry.pParams; pParams->Init(*pControllerDef); } } template< typename T > const T* FindOrCreateParams(const IActionController* pActionController) { if (pActionController == NULL) { return NULL; } const SAnimationContext& animationContext = pActionController->GetContext(); const SControllerDef& controllerDef = animationContext.controllerDef; return FindOrCreateParams< T >(controllerDef); } template< typename T > const T* FindOrCreateParams(const SControllerDef& controllerDef) { static uint32 s_mannequinParamType = GetAutoIncParamTypeValue(); const CMannequinUserParamId mannequinUserParamId(controllerDef, s_mannequinParamType); { const IMannequinUserParams* pParams = FindParams(mannequinUserParamId); if (pParams != NULL) { return static_cast< const T* >(pParams); } } T* pParams = new T(); pParams->Init(controllerDef); AddParams(mannequinUserParamId, pParams, eMPO_ManagerOwnership); return pParams; } template< typename T > void RegisterParams(const IActionController* pActionController, IMannequinUserParams* pParams) { if (pActionController == NULL) { return; } const SAnimationContext& animationContext = pActionController->GetContext(); const SControllerDef& controllerDef = animationContext.controllerDef; RegisterParams< T >(controllerDef, pParams); } template< typename T > void RegisterParams(const SControllerDef& controllerDef, IMannequinUserParams* pParams) { if (pParams == NULL) { return; } static uint32 s_mannequinParamType = GetAutoIncParamTypeValue(); const CMannequinUserParamId mannequinUserParamId(controllerDef, s_mannequinParamType); const IMannequinUserParams* pParamsOther = FindParams(mannequinUserParamId); if (pParamsOther != NULL) { CRY_ASSERT(pParams == pParamsOther); return; } pParams->Init(controllerDef); AddParams(mannequinUserParamId, pParams, eMPO_ExternalOwnership); } protected: const IMannequinUserParams* FindParams(const CMannequinUserParamId& paramId) const { TMannequinUserParams::const_iterator cit = std::lower_bound(m_userParams.begin(), m_userParams.end(), SMannequinParamEntry(paramId)); const bool found = (cit != m_userParams.end()) && (cit->paramId == paramId); return (found) ? cit->pParams : NULL; } enum EMannequinParamsOwnership { eMPO_ExternalOwnership, eMPO_ManagerOwnership }; void AddParams(const CMannequinUserParamId& paramId, IMannequinUserParams* pParams, const EMannequinParamsOwnership ownership) { const SMannequinParamEntry entry(paramId, pParams); m_userParams.insert(std::lower_bound(m_userParams.begin(), m_userParams.end(), entry), entry); if (ownership == eMPO_ManagerOwnership) { m_ownedUserParams.push_back(pParams); } } private: uint32 GetAutoIncParamTypeValue() { m_autoIncValue++; return m_autoIncValue; } private: struct SMannequinParamEntry { CMannequinUserParamId paramId; IMannequinUserParams* pParams; SMannequinParamEntry(const CMannequinUserParamId& paramId_, IMannequinUserParams* pParams_ = NULL) : paramId(paramId_) , pParams(pParams_) { } bool operator < (const SMannequinParamEntry& rhs) const { return (paramId < rhs.paramId); } }; typedef DynArray< SMannequinParamEntry > TMannequinUserParams; typedef DynArray< IMannequinUserParams* > TMannequinOwnedUserParams; TMannequinUserParams m_userParams; TMannequinOwnedUserParams m_ownedUserParams; uint32 m_autoIncValue; }; template< typename T, T invalidValue > struct TMannequinAutoInit { public: TMannequinAutoInit() : m_value(invalidValue) { } const TMannequinAutoInit< T, invalidValue >& operator = (const T value) { m_value = value; return *this; } operator const T () const { return m_value; } bool IsValid() const { return (m_value != invalidValue); } private: T m_value; }; typedef TMannequinAutoInit< TagID, TAG_ID_INVALID > TagIDAutoInit; typedef TMannequinAutoInit< TagGroupID, GROUP_ID_NONE > TagGroupIDAutoInit; typedef TMannequinAutoInit< FragmentID, FRAGMENT_ID_INVALID > FragmentIDAutoInit; typedef TMannequinAutoInit< TagID, SCOPE_ID_INVALID > ScopeIDAutoInit; typedef TMannequinAutoInit< TagID, SCOPE_CONTEXT_ID_INVALID > ContextIDAutoInit; #define MANNEQUIN_USER_PARAMS__IMPL_IMPL_GET_THIRD_ARG(arg1, arg2, arg3, ...) arg3 #define MANNEQUIN_USER_PARAMS__IMPL_GET_THIRD_ARG(x) MANNEQUIN_USER_PARAMS__IMPL_IMPL_GET_THIRD_ARG x #define MANNEQUIN_USER_PARAMS__GET_THIRD_ARG(...) MANNEQUIN_USER_PARAMS__IMPL_GET_THIRD_ARG((__VA_ARGS__)) #define MANNEQUIN_USER_PARAMS__NOTHING #define MANNEQUIN_USER_PARAMS__ADD_ONE(x, ...) + 1 #define MANNEQUIN_USER_PARAMS__OPTIONAL_ARGUMENT(...) ,##__VA_ARGS__ #define MANNEQUIN_USER_PARAMS__OPTIONAL_ARGUMENT_FROM_LIST(list) MANNEQUIN_USER_PARAMS__OPTIONAL_ARGUMENT(list(MANNEQUIN_USER_PARAMS__ADD_ONE)) #define MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(list, stuff) MANNEQUIN_USER_PARAMS__GET_THIRD_ARG(1 MANNEQUIN_USER_PARAMS__OPTIONAL_ARGUMENT_FROM_LIST(list), stuff, MANNEQUIN_USER_PARAMS__NOTHING) #define MANNEQUIN_USER_PARAMS__EMPTY_LIST(x) #define MANNEQUIN_USER_PARAMS__DECLARE_FRAGMENT(elem) FragmentIDAutoInit elem; #define MANNEQUIN_USER_PARAMS__INIT_FRAGMENT(elem) elem = tagDefs.Find( #elem); #define MANNEQUIN_USER_PARAMS__FRAGMENT_STRUCT(elementsName, elementList) \ struct elementsName \ { \ elementList(MANNEQUIN_USER_PARAMS__DECLARE_FRAGMENT) \ \ void Init(const CTagDefinition&tagDefs) \ { \ elementList(MANNEQUIN_USER_PARAMS__INIT_FRAGMENT) \ } \ }; #define MANNEQUIN_USER_PARAMS__DECLARE_TAG(elem) TagIDAutoInit elem; #define MANNEQUIN_USER_PARAMS__INIT_TAG(elem) elem = tagDefs.Find( #elem); #define MANNEQUIN_USER_PARAMS__TAG_STRUCT(elementsName, elementList) \ struct elementsName \ { \ elementList(MANNEQUIN_USER_PARAMS__DECLARE_TAG) \ \ void Init(const CTagDefinition&tagDefs) \ { \ elementList(MANNEQUIN_USER_PARAMS__INIT_TAG) \ } \ }; #define MANNEQUIN_USER_PARAMS__DECLARE_TAGGROUP(groupElem) TagGroupIDAutoInit groupElem; #define MANNEQUIN_USER_PARAMS__INIT_TAGGROUP(groupElem) groupElem = tagDefs.FindGroup( #groupElem); #define MANNEQUIN_USER_PARAMS__TAGGROUP_STRUCT(elementsName, elementList) \ struct elementsName \ { \ elementList(MANNEQUIN_USER_PARAMS__DECLARE_TAGGROUP) \ \ void Init(const CTagDefinition&tagDefs) \ { \ elementList(MANNEQUIN_USER_PARAMS__INIT_TAGGROUP) \ } \ }; #define MANNEQUIN_USER_PARAMS__DECLARE_SCOPE(elem) ScopeIDAutoInit elem; #define MANNEQUIN_USER_PARAMS__INIT_SCOPE(elem) elem = tagDefs.Find( #elem); #define MANNEQUIN_USER_PARAMS__SCOPE_STRUCT(elementsName, elementList) \ struct elementsName \ { \ elementList(MANNEQUIN_USER_PARAMS__DECLARE_SCOPE) \ \ void Init(const CTagDefinition&tagDefs) \ { \ elementList(MANNEQUIN_USER_PARAMS__INIT_SCOPE) \ } \ }; #define MANNEQUIN_USER_PARAMS__FRAGTAG_STRUCT(fragmentName, fragTagTagsList, fragTagTagGroupsList) \ struct S##fragmentName \ { \ S##fragmentName() \ : pTagDefinition(NULL) \ {} \ \ \ void Init(const SControllerDef&controllerDef) \ { \ pTagDefinition = NULL; \ fragmentID = controllerDef.m_fragmentIDs.Find( #fragmentName); \ if (fragmentID != FRAGMENT_ID_INVALID) \ { \ pTagDefinition = controllerDef.GetFragmentTagDef(fragmentID); \ } \ \ static CTagDefinition s_dummyTagDefinition; \ pTagDefinition = pTagDefinition ? pTagDefinition : &s_dummyTagDefinition; \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragTagTagsList, fragmentTagIDs.Init(*pTagDefinition)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragTagTagGroupsList, fragmentTagGroupIDs.Init(*pTagDefinition)); \ } \ \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragTagTagsList, MANNEQUIN_USER_PARAMS__FRAGMENT_STRUCT(FragmentTagIDs, fragTagTagsList)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragTagTagGroupsList, MANNEQUIN_USER_PARAMS__TAGGROUP_STRUCT(FragmentTagGroupIDs, fragTagTagGroupsList)); \ \ TagIDAutoInit fragmentID; \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragTagTagsList, FragmentTagIDs fragmentTagIDs); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragTagTagGroupsList, FragmentTagGroupIDs fragmentTagGroupIDs); \ const CTagDefinition* pTagDefinition; \ }; \ \ S##fragmentName fragmentName; #define MANNEQUIN_USER_PARAMS__FRAGTAG_STRUCT_INIT(fragmentName, ...) fragmentName.Init(controllerDef); #define MANNEQUIN_USER_PARAMS__FRAGTAG_HOLDER_STRUCT(elementsName, elementList) \ struct elementsName \ { \ elementList(MANNEQUIN_USER_PARAMS__FRAGTAG_STRUCT) \ \ void Init(const SControllerDef&controllerDef) \ { \ elementList(MANNEQUIN_USER_PARAMS__FRAGTAG_STRUCT_INIT) \ } \ \ }; #define MANNEQUIN_USER_PARAMS(structName, fragmentList, tagList, tagGroupList, scopeList, contextList, fragmentTagsList) \ struct structName \ : public IMannequinUserParams \ { \ virtual void Init(const SControllerDef&controllerDef) \ { \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragmentList, fragmentIDs.Init(controllerDef.m_fragmentIDs)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(tagList, tagIDs.Init(controllerDef.m_tags)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(tagGroupList, tagGroupIDs.Init(controllerDef.m_tags)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(scopeList, scopeIDs.Init(controllerDef.m_scopeIDs)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(contextList, contextIDs.Init(controllerDef.m_scopeContexts)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragmentTagsList, fragments.Init(controllerDef)); \ } \ \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragmentList, MANNEQUIN_USER_PARAMS__FRAGMENT_STRUCT(FragmentIDs, fragmentList)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(tagList, MANNEQUIN_USER_PARAMS__TAG_STRUCT(TagIDs, tagList)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(tagGroupList, MANNEQUIN_USER_PARAMS__TAGGROUP_STRUCT(TagGroupIDs, tagGroupList)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(scopeList, MANNEQUIN_USER_PARAMS__SCOPE_STRUCT(ScopeIDs, scopeList)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(contextList, MANNEQUIN_USER_PARAMS__TAG_STRUCT(ContextIDs, contextList)); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragmentTagsList, MANNEQUIN_USER_PARAMS__FRAGTAG_HOLDER_STRUCT(Fragments, fragmentTagsList)); \ \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragmentList, FragmentIDs fragmentIDs); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(tagList, TagIDs tagIDs); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(tagGroupList, TagGroupIDs tagGroupIDs); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(scopeList, ScopeIDs scopeIDs); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(contextList, ContextIDs contextIDs); \ MANNEQUIN_USER_PARAMS__IF_LIST_NOT_EMPTY(fragmentTagsList, Fragments fragments); \ }; #define MANNEQUIN_AUTO_CRC__DECLARE_ELEMENT(elem) uint32 elem; #define MANNEQUIN_AUTO_CRC__INIT_ELEMENT(elem) elem = CCrc32::ComputeLowercase( #elem); #define MANNEQUIN_AUTO_CRC(structName, crcList) \ struct structName \ { \ structName() \ : m_initialised(false) \ {} \ \ void Init() \ { \ if (!m_initialised) \ { \ crcList(MANNEQUIN_AUTO_CRC__INIT_ELEMENT) \ m_initialised = true; \ } \ } \ \ crcList(MANNEQUIN_AUTO_CRC__DECLARE_ELEMENT); \ bool m_initialised; \ }; #endif // CRYINCLUDE_CRYACTION_ICRYMANNEQUINUSERPARAMS_H