#include "Runtime/Character/CCharacterFactory.hpp" #include "Runtime/CRandom16.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/Character/CAdditiveAnimPlayback.hpp" #include "Runtime/Character/CAnimCharacterSet.hpp" #include "Runtime/Character/CAnimData.hpp" #include "Runtime/Character/CAnimationDatabaseGame.hpp" #include "Runtime/Character/CAnimationManager.hpp" #include "Runtime/Character/CCharLayoutInfo.hpp" #include "Runtime/Character/CParticleGenInfo.hpp" #include "Runtime/Character/CPrimitive.hpp" #include "Runtime/Character/CTransitionDatabaseGame.hpp" #include "Runtime/Character/CTransitionManager.hpp" #include "Runtime/Graphics/CSkinnedModel.hpp" namespace urde { CFactoryFnReturn CCharacterFactory::CDummyFactory::Build(const SObjectTag& tag, const CVParamTransfer& params, CObjectReference* selfRef) { const CCharacterInfo& charInfo = *params.GetOwnedObj(); switch (tag.type.toUint32() & 0x1) { case 0: return TToken::GetIObjObjectFor( std::make_unique(*g_SimplePool, charInfo.GetModelId(), charInfo.GetSkinRulesId(), charInfo.GetCharLayoutInfoId(), 0, tag.type.toUint32() >> 16)); case 1: return TToken::GetIObjObjectFor( std::make_unique(*g_SimplePool, charInfo.GetIceModelId(), charInfo.GetIceSkinRulesId(), charInfo.GetCharLayoutInfoId(), 0, tag.type.toUint32() >> 16)); default: break; } return {}; } void CCharacterFactory::CDummyFactory::BuildAsync(const SObjectTag& tag, const CVParamTransfer& parms, std::unique_ptr* objOut, CObjectReference* selfRef) { *objOut = Build(tag, parms, selfRef); } void CCharacterFactory::CDummyFactory::CancelBuild(const SObjectTag&) {} bool CCharacterFactory::CDummyFactory::CanBuild(const SObjectTag&) { return true; } const SObjectTag* CCharacterFactory::CDummyFactory::GetResourceIdByName(std::string_view) const { return nullptr; } FourCC CCharacterFactory::CDummyFactory::GetResourceTypeById(CAssetId id) const { return {}; } void CCharacterFactory::CDummyFactory::EnumerateResources(const std::function& lambda) const {} void CCharacterFactory::CDummyFactory::EnumerateNamedResources( const std::function& lambda) const {} u32 CCharacterFactory::CDummyFactory::ResourceSize(const urde::SObjectTag& tag) { return 0; } std::shared_ptr CCharacterFactory::CDummyFactory::LoadResourceAsync(const urde::SObjectTag& tag, void* target) { return {}; } std::shared_ptr CCharacterFactory::CDummyFactory::LoadResourcePartAsync(const urde::SObjectTag& tag, u32 off, u32 size, void* target) { return {}; } std::unique_ptr CCharacterFactory::CDummyFactory::LoadResourceSync(const urde::SObjectTag& tag) { return {}; } std::unique_ptr CCharacterFactory::CDummyFactory::LoadNewResourcePartSync(const urde::SObjectTag& tag, u32 off, u32 size) { return {}; } std::unique_ptr CCharacterFactory::CreateCharacter(int charIdx, bool loop, const TLockedToken& factory, int defaultAnim, int drawInsts) const { const CCharacterInfo& charInfo = x4_charInfoDB[charIdx]; CVParamTransfer charParm(new TObjOwnerParam(&charInfo)); TToken skinnedModel = const_cast(this)->x70_cacheResPool.GetObj( {FourCC(drawInsts << 16), charInfo.GetModelId()}, charParm); std::optional> iceModel; if (charInfo.GetIceModelId().IsValid() && charInfo.GetIceSkinRulesId().IsValid()) iceModel.emplace(const_cast(this)->x70_cacheResPool.GetObj( {FourCC((drawInsts << 16) | 1), charInfo.GetIceModelId()}, charParm)); return std::make_unique(x68_selfId, charInfo, defaultAnim, charIdx, loop, x14_charLayoutInfoDB[charIdx], skinnedModel, iceModel, x24_sysContext, x28_animMgr, x2c_transMgr, factory, drawInsts); } CAssetId CCharacterFactory::GetEventResourceIdForAnimResourceId(CAssetId id) const { auto search = std::find_if(x58_animResources.cbegin(), x58_animResources.cend(), [&](const std::pair& elem) -> bool { return id == elem.first; }); if (search == x58_animResources.cend()) return CAssetId(); return search->second; } const CAdditiveAnimationInfo& CCharacterFactory::FindAdditiveInfo(s32 idx) const { auto search = rstl::binary_find(x40_additiveInfo.cbegin(), x40_additiveInfo.cend(), idx, [](const auto& anim) { return anim.first; }); if (search == x40_additiveInfo.cend()) return x50_defaultAdditiveInfo; return search->second; } bool CCharacterFactory::HasAdditiveInfo(s32 idx) const { auto search = rstl::binary_find(x40_additiveInfo.cbegin(), x40_additiveInfo.cend(), idx, [](const auto& anim) { return anim.first; }); return search != x40_additiveInfo.cend(); } std::vector CCharacterFactory::GetCharacterInfoDB(const CAnimCharacterSet& ancs) { std::vector ret; const std::map& charInfoMap = ancs.GetCharacterSet().GetCharacterInfoMap(); ret.reserve(charInfoMap.size()); for (const auto& charInfo : charInfoMap) ret.push_back(charInfo.second); return ret; } std::vector> CCharacterFactory::GetCharLayoutInfoDB(CSimplePool& store, const std::vector& chars) { std::vector> ret; ret.reserve(chars.size()); for (const CCharacterInfo& charInfo : chars) ret.push_back(store.GetObj({SBIG('CINF'), charInfo.GetCharLayoutInfoId()})); return ret; } CCharacterFactory::CCharacterFactory(CSimplePool& store, const CAnimCharacterSet& ancs, CAssetId selfId) : x4_charInfoDB(GetCharacterInfoDB(ancs)) , x14_charLayoutInfoDB(GetCharLayoutInfoDB(store, x4_charInfoDB)) , x24_sysContext(std::make_shared( TToken(std::make_unique( ancs.GetAnimationSet().GetTransitions(), ancs.GetAnimationSet().GetHalfTransitions(), ancs.GetAnimationSet().GetDefaultTransition())), 2334, store)) , x28_animMgr(std::make_shared( TToken(std::make_unique(ancs.GetAnimationSet().GetAnimations())), *x24_sysContext)) , x2c_transMgr(std::make_shared(*x24_sysContext)) , x40_additiveInfo(ancs.GetAnimationSet().GetAdditiveInfo()) , x50_defaultAdditiveInfo(ancs.GetAnimationSet().GetDefaultAdditiveInfo()) , x58_animResources(ancs.GetAnimationSet().GetAnimResIds()) , x68_selfId(selfId) , x70_cacheResPool(x6c_dummyFactory) { std::vector primitives; x28_animMgr->GetAnimationDatabase()->GetAllUniquePrimitives(primitives); x30_animSourceDB.reserve(primitives.size()); for (const CPrimitive& prim : primitives) x30_animSourceDB.push_back(store.GetObj({SBIG('ANIM'), prim.GetAnimResId()})); } } // namespace urde