From 8c8d9c0e7036d22d3eebe1c8dca54b44b601e8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Fri, 19 Mar 2021 14:31:19 +0100 Subject: [PATCH] ksys/res: Finish implementing ModelList --- data/uking_functions.csv | 64 +-- ...3res9ModelList6parse_EPhmPN4sead4HeapE.bin | Bin 0 -> 2096 bytes lib/sead | 2 +- src/KingSystem/ActorSystem/actInfoData.cpp | 15 +- .../Resource/resResourceModelList.cpp | 367 ++++++++++++++++++ .../Resource/resResourceModelList.h | 114 ++++-- src/KingSystem/Utils/CMakeLists.txt | 1 + src/KingSystem/Utils/ParamIO.cpp | 21 + src/KingSystem/Utils/ParamIO.h | 6 + 9 files changed, 515 insertions(+), 75 deletions(-) create mode 100644 expected/_ZN4ksys3res9ModelList6parse_EPhmPN4sead4HeapE.bin create mode 100644 src/KingSystem/Utils/ParamIO.cpp diff --git a/data/uking_functions.csv b/data/uking_functions.csv index a59b7679..7cb7f42f 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -90948,8 +90948,8 @@ 0x0000007101167b3c,sub_7101167B3C,316, 0x0000007101167c78,sub_7101167C78,328, 0x0000007101167dc0,sub_7101167DC0,76, -0x0000007101167e0c,sub_7101167E0C,124, -0x0000007101167e88,sub_7101167E88,140, +0x0000007101167e0c,sub_7101167E0C,124,_ZNK4ksys7ParamIO9getStringERKN3agl3utl15ResParameterObjEPKcS7_Pv +0x0000007101167e88,sub_7101167E88,140,_ZNK4ksys7ParamIO7getVec3ERKN3agl3utl15ResParameterObjEPKcN4sead7Vector3IfEEPv? 0x0000007101167f14,sub_7101167F14,152,_ZN4ksys3act13ActorParamMgr18SingletonDisposer_D2Ev 0x0000007101167fac,sub_7101167FAC,160,_ZN4ksys3act13ActorParamMgr18SingletonDisposer_D0Ev 0x000000710116804c,ActorParam::createInstance,136,_ZN4ksys3act13ActorParamMgr14createInstanceEPN4sead4HeapE @@ -91533,36 +91533,36 @@ 0x00000071011ae438,sub_71011AE438,212, 0x00000071011ae50c,Bmodellist::ctor,596,_ZN4ksys3res9ModelListC1Ev 0x00000071011ae760,BmodellistSub::ctor,404,_ZN4ksys3res9ModelList9AttentionC2Ev -0x00000071011ae8f4,sub_71011AE8F4,972, -0x00000071011aecc0,sub_71011AECC0,8, -0x00000071011aecc8,sub_71011AECC8,8, -0x00000071011aecd0,sub_71011AECD0,36, -0x00000071011aecf4,sub_71011AECF4,40, -0x00000071011aed1c,sub_71011AED1C,40, -0x00000071011aed44,nullsub_4625,4, -0x00000071011aed48,nullsub_4626,4, -0x00000071011aed4c,Bmodellist::parse,2096, -0x00000071011af57c,sub_71011AF57C,2488, -0x00000071011aff34,sub_71011AFF34,2636, -0x00000071011b0980,ResourceBmodellist::parse,8, -0x00000071011b0988,sub_71011B0988,312, -0x00000071011b0ac0,sub_71011B0AC0,332, -0x00000071011b0c0c,Bmodellist::x,8, -0x00000071011b0c14,modellist::x,376, -0x00000071011b0d8c,sub_71011B0D8C,688, -0x00000071011b103c,sub_71011B103C,296,_ZN4ksys3actL21getLocatorTypeFromStrERKN4sead14SafeStringBaseIcEE -0x00000071011b1164,sub_71011B1164,544, -0x00000071011b1384,sub_71011B1384,32, -0x00000071011b13a4,sub_71011B13A4,32, -0x00000071011b13c4,sub_71011B13C4,32, -0x00000071011b13e4,sub_71011B13E4,172, -0x00000071011b1490,sub_71011B1490,8, -0x00000071011b1498,sub_71011B1498,92, -0x00000071011b14f4,sub_71011B14F4,8, -0x00000071011b14fc,sub_71011B14FC,8, -0x00000071011b1504,sub_71011B1504,92, -0x00000071011b1560,sub_71011B1560,8, -0x00000071011b1568,sub_71011B1568,372, +0x00000071011ae8f4,sub_71011AE8F4,972,_ZN4ksys3res9ModelListD1Ev +0x00000071011aecc0,sub_71011AECC0,8,_ZThn632_N4ksys3res9ModelListD1Ev +0x00000071011aecc8,sub_71011AECC8,8,_ZThn664_N4ksys3res9ModelListD1Ev +0x00000071011aecd0,sub_71011AECD0,36,_ZN4ksys3res9ModelListD0Ev +0x00000071011aecf4,sub_71011AECF4,40,_ZThn632_N4ksys3res9ModelListD0Ev +0x00000071011aed1c,sub_71011AED1C,40,_ZThn664_N4ksys3res9ModelListD0Ev +0x00000071011aed44,nullsub_4625,4,_ZN4ksys3res9ModelList9doCreate_EPhjPN4sead4HeapE +0x00000071011aed48,nullsub_4626,4,_ZThn632_N4ksys3res9ModelList9doCreate_EPhjPN4sead4HeapE +0x00000071011aed4c,Bmodellist::parse,2096,_ZN4ksys3res9ModelList6parse_EPhmPN4sead4HeapE? +0x00000071011af57c,sub_71011AF57C,2488,_ZN4ksys3res9ModelList14parseModelDataERKN3agl3utl16ResParameterListEPN4sead4HeapE +0x00000071011aff34,sub_71011AFF34,2636,_ZN4ksys3res9ModelList14parseAnmTargetERKN3agl3utl16ResParameterListEPN4sead4HeapE +0x00000071011b0980,ResourceBmodellist::parse,8,_ZThn632_N4ksys3res9ModelList6parse_EPhmPN4sead4HeapE +0x00000071011b0988,sub_71011B0988,312,_ZN4ksys3res20allocModelDataBufferERN4sead6BufferINS0_9ModelList9ModelDataEEEiPNS1_4HeapEi +0x00000071011b0ac0,sub_71011B0AC0,332,_ZN4ksys3res27allocAnmTargetPartialBufferERN4sead6BufferINS0_9ModelList7PartialEEEiPNS1_4HeapEi +0x00000071011b0c0c,Bmodellist::x,8,_ZNK4ksys3res9ModelList16getNumAnmTargetsEv +0x00000071011b0c14,modellist::x,376,_ZNK4ksys3res9ModelList16getModelDataInfoEPNS1_13ModelDataInfoE +0x00000071011b0d8c,sub_71011B0D8C,688,_ZNK4ksys3res9ModelList16getAttentionInfoEPNS1_13AttentionInfoE +0x00000071011b103c,sub_71011B103C,296,_ZN4ksys3res9ModelList21getLocatorTypeFromStrERKN4sead14SafeStringBaseIcEE +0x00000071011b1164,sub_71011B1164,544,_ZNK4ksys3res9ModelList14getLocatorInfoEPNS_3act8InfoData7LocatorENS4_4TypeE! +0x00000071011b1384,sub_71011B1384,32,_ZNK4ksys3res9ModelList16isParticalEnableEi +0x00000071011b13a4,sub_71011B13A4,32,_ZNK4ksys3res9ModelList12getNumASSlotEi +0x00000071011b13c4,sub_71011B13C4,32,_ZNK4ksys3res9ModelList14getNumPartialsEi +0x00000071011b13e4,sub_71011B13E4,172,_ZNK4ksys3res9ModelList14getPartialInfoEPNS1_11PartialInfoEii +0x00000071011b1490,sub_71011B1490,8,_ZNK4ksys3res9ModelList27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x00000071011b1498,sub_71011B1498,92,_ZNK4ksys3res9ModelList18getRuntimeTypeInfoEv +0x00000071011b14f4,sub_71011B14F4,8,_ZNK4ksys3res9ModelList10needsParseEv +0x00000071011b14fc,sub_71011B14FC,8,_ZThn632_NK4ksys3res9ModelList27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x00000071011b1504,sub_71011B1504,92,_ZThn632_NK4ksys3res9ModelList18getRuntimeTypeInfoEv +0x00000071011b1560,sub_71011B1560,8,_ZThn632_NK4ksys3res9ModelList10needsParseEv +0x00000071011b1568,sub_71011B1568,372,_ZN4ksys3res9ModelList33checkDerivedRuntimeTypeInfoStaticEPKN4sead15RuntimeTypeInfo9InterfaceE 0x00000071011b16dc,nullsub_4627,4, 0x00000071011b16e0,ResourceBphysics::m5_null,4, 0x00000071011b16e4,sub_71011B16E4,80, diff --git a/expected/_ZN4ksys3res9ModelList6parse_EPhmPN4sead4HeapE.bin b/expected/_ZN4ksys3res9ModelList6parse_EPhmPN4sead4HeapE.bin new file mode 100644 index 0000000000000000000000000000000000000000..942f12b1f2c48f832ba5e53cf7558d3a8861b7a9 GIT binary patch literal 2096 zcmai$ZD>8$b?)x|6^6KRn1ygDot=O^MClObN8d}AmcSm3O6e1{T!8}Usx*5*;!fe=TY z-D9}7HSVYQ-wPVIh$q~ihlcBt0}A^_;J>DB&vCA>0~7s9be>m+W4tPSM`7mA83BvfL*Nb+vPp5=ld9=v(l?u)OwOefBWkg%{Xmfu*Oh3HtI<2qFNQj$7Acgs zTbTU&Hq)nCy7a03t@_-1@xY67>1nO6$cz_HZIqNVc1%f8Eai?JQBv7>%KZsBi}lV+ zz7tBy_mPsiF_)gyBE?qzNUNEj&CSibf;>^grbYX%lvD8-r(fa*&EoVPZV0Ex@bz+I zfNJ%X$f^D=omdml65OFish-eXrk<&mtaA06?43q2E~+ojfAx+cquJRf4+ zH`9JCSSrPAn{;nraxBJ;TyNB8vsX`B-iSF!Ots9c|1+4^X4C#niRa}!dU3fl9f;wi zJy<}l9lH<$XT)1CwHL~yxV3(jE}C_gLA4K}_Tnt&9zlKT!J9U#2f?zgd_CwPJ(cY}&uJpSbd837Fy6f)Fl#64|@7fGk0nYbv7U4W$Gf>M<8pSq_ z`K{KTt9vtQxo)Ntn%9aEuQplxdcn3byUcEr&t}Aja9?O@h2^uM#`5`XPCRxkch*(p zvk&pOf8K%5MVhscQkcFUgwC;2P18>lfUekjLmDoq{Poi@D@ANx!i zNb`e1@Pmj0e=qnx;@@kNTFknZkAD|=Ccihse>uZ{&2FFv2{EEb&0FGYnYV9ihVt0r2Ji*>&pAF|xL%^>V*Ky;OUuO_c z{aNB{i{`DB;$yez?|gGz*MB@>zBFf=@rUFwX6gB@-Fyc7#qQ1MvBk~j@vW@KK8Lkq zM{v@P9dj5ra6gOo=dfdSkL~e6;s+6j8Bc-lq8X1CW5=v(`S^RX{9iKs8H+!G9o_U~ zh52mq%{h!u*R6g&-SWo+gLv2ZR8OkP?McmZCKq@`_)>u0)AYMCJg#n^IeUhusF!%3 fw=SRDkMDq9d=Koycfnr$;n5yF&F%6kKQ!|%!5g{N literal 0 HcmV?d00001 diff --git a/lib/sead b/lib/sead index 80d838dc..0295cef7 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit 80d838dcc8db49409b490b51f6a81ff96e0ea8a2 +Subproject commit 0295cef7a2f87eef8c7b75b6a21d8b3a9bd1572d diff --git a/src/KingSystem/ActorSystem/actInfoData.cpp b/src/KingSystem/ActorSystem/actInfoData.cpp index 028cb26e..a36aeb30 100644 --- a/src/KingSystem/ActorSystem/actInfoData.cpp +++ b/src/KingSystem/ActorSystem/actInfoData.cpp @@ -6,6 +6,7 @@ #include "KingSystem/ActorSystem/actDebug.h" #include "KingSystem/Event/evtEvent.h" #include "KingSystem/Event/evtManager.h" +#include "KingSystem/Resource/resResourceModelList.h" #include "KingSystem/Utils/Byaml/Byaml.h" #include "KingSystem/Utils/Byaml/ByamlArrayIter.h" #include "KingSystem/Utils/Byaml/ByamlData.h" @@ -215,17 +216,6 @@ const char* InfoData::getStringByKey(const al::ByamlIter& iter, const char* key, return iter.tryGetStringByKey(&value, key) ? value : default_.cstr(); } -[[gnu::noinline]] static InfoData::Locator::Type -getLocatorTypeFromStr(const sead::SafeString& type) { - static constexpr const char* types[] = {"Trunk", "Branch", "GlowStone", - "OnTree", "MagnePos", "StopTimerPos"}; - for (s32 i = 0; i < s32(std::size(types)); ++i) { - if (type == types[i]) - return InfoData::Locator::Type(i); - } - return InfoData::Locator::Type::Invalid; -} - void InfoData::getLocators(const char* actor, Locators& info) const { info.num = 0; @@ -255,7 +245,8 @@ void InfoData::getLocators(const char* actor, Locators& info) const { it.tryGetFloatByKey(&locator.rot.z, "rot_z"); it.tryGetStringByKey(&type_str, "type"); - locator.type = type_str ? getLocatorTypeFromStr(type_str) : Locator::Type::Invalid; + locator.type = + type_str ? res::ModelList::getLocatorTypeFromStr(type_str) : Locator::Type::Invalid; locator.rot *= 2 * sead::numbers::pi / 360.0; } diff --git a/src/KingSystem/Resource/resResourceModelList.cpp b/src/KingSystem/Resource/resResourceModelList.cpp index b5d6ed03..9450ee52 100644 --- a/src/KingSystem/Resource/resResourceModelList.cpp +++ b/src/KingSystem/Resource/resResourceModelList.cpp @@ -1,7 +1,374 @@ #include "KingSystem/Resource/resResourceModelList.h" +#include +#include "KingSystem/Resource/resModelResourceDivide.h" namespace ksys::res { +namespace { +sead::SafeString str_ModelData{"ModelData"}; +sead::SafeString str_Unit{"Unit"}; +sead::SafeString str_AnmTarget{"AnmTarget"}; +sead::SafeString str_Partial{"Partial"}; + +sead::SafeArray sLocatorTypes{{ + "Trunk", + "Branch", + "GlowStone", + "OnTree", + "MagnePos", + "StopTimerPos", +}}; + +constexpr u32 NumUnitMax = 8; +} // namespace + ModelList::ModelList() : ParamIO("modellist", 0) {} +ModelList::~ModelList() { + for (auto& entry : mModelData) + entry.units.freeBuffer(); + mModelData.freeBuffer(); + + for (auto& entry : mAnmTargets) + entry.partials.freeBuffer(); + mAnmTargets.freeBuffer(); +} + +void ModelList::doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) {} + +// NON_MATCHING: reorderings +bool ModelList::parse_(u8* data, size_t size, sead::Heap* heap) { + agl::utl::ResParameterArchive archive{data}; + const auto root = archive.getRootList(); + + const auto model_data_list = agl::utl::getResParameterList(root, str_ModelData); + if (model_data_list.ptr() && model_data_list.getResParameterListNum() > 0) { + if (!parseModelData(model_data_list, heap)) + return false; + } + addList(&mModelDataList, str_ModelData); + + const auto anm_target_list = agl::utl::getResParameterList(root, str_AnmTarget); + if (anm_target_list.ptr() && anm_target_list.getResParameterListNum() > 0) { + if (!parseAnmTarget(anm_target_list, heap)) + return false; + } + addList(&mAnmTargetList, str_AnmTarget); + + mControllerInfo->mAddColor.init({0.0, 0.0, 0.0, 0.0}, "AddColor", "", &mControllerInfo->mObj); + mControllerInfo->mMulColor.init({1.0, 1.0, 1.0, 1.0}, "MulColor", "", &mControllerInfo->mObj); + mControllerInfo->mBaseScale.init(sead::Vector3f::ones, "BaseScale", "", &mControllerInfo->mObj); + mControllerInfo->mVariationMatAnim.init("", "VariationMatAnim", "", &mControllerInfo->mObj); + mControllerInfo->mVariationMatAnimFrame.init(0, "VariationMatAnimFrame", "", + &mControllerInfo->mObj); + mControllerInfo->mVariationShaderAnim.init("", "VariationShaderAnim", "", + &mControllerInfo->mObj); + mControllerInfo->mVariationShaderAnimFrame.init(0, "VariationShaderAnimFrame", "", + &mControllerInfo->mObj); + mControllerInfo->mCalcAABBASKey.init("Wait", "CalcAABBASKey", "", &mControllerInfo->mObj); + addObj(&mControllerInfo->mObj, sead::FormatFixedSafeString<128>("ControllerInfo")); + + mAttention->mIsEnableAttention.init(false, "IsEnableAttention", "", &mAttention->mObj); + mAttention->mLookAtBone.init("", "LookAtBone", "", &mAttention->mObj); + mAttention->mLookAtOffset.init(sead::Vector3f::zero, "LookAtOffset", "", &mAttention->mObj); + mAttention->mCursorOffsetY.init(0.0, "CursorOffsetY", "", &mAttention->mObj); + mAttention->mAIInfoOffsetY.init(0.0, "AIInfoOffsetY", "", &mAttention->mObj); + mAttention->mCutTargetBone.init("", "CutTargetBone", "", &mAttention->mObj); + mAttention->mCutTargetOffset.init(sead::Vector3f::zero, "CutTargetOffset", "", + &mAttention->mObj); + mAttention->mGameCameraBone.init("", "GameCameraBone", "", &mAttention->mObj); + mAttention->mGameCameraOffset.init(sead::Vector3f::zero, "GameCameraOffset", "", + &mAttention->mObj); + mAttention->mBowCameraBone.init("", "BowCameraBone", "", &mAttention->mObj); + mAttention->mBowCameraOffset.init(sead::Vector3f::zero, "BowCameraOffset", "", + &mAttention->mObj); + mAttention->mAttackTargetBone.init("", "AttackTargetBone", "", &mAttention->mObj); + mAttention->mAttackTargetOffset.init(sead::Vector3f::zero, "AttackTargetOffset", "", + &mAttention->mObj); + mAttention->mAttackTargetOffsetBack.init(0.0, "AttackTargetOffsetBack", "", &mAttention->mObj); + mAttention->mAtObstacleChkUseLookAtPos.init(true, "AtObstacleChkUseLookAtPos", "", + &mAttention->mObj); + mAttention->mAtObstacleChkOffsetBone.init("", "AtObstacleChkOffsetBone", "", &mAttention->mObj); + mAttention->mAtObstacleChkOffset.init(sead::Vector3f::zero, "AtObstacleChkOffset", "", + &mAttention->mObj); + mAttention->mCursorAIInfoBaseBone.init("", "CursorAIInfoBaseBone", "", &mAttention->mObj); + mAttention->mCursorAIInfoBaseOffset.init(sead::Vector3f::zero, "CursorAIInfoBaseOffset", "", + &mAttention->mObj); + addObj(&mAttention->mObj, sead::FormatFixedSafeString<128>("Attention")); + + if (data) { + applyResParameterArchive(agl::utl::ResParameterArchive{data}); + mRawData = data; + } + + return true; +} + +bool allocModelDataBuffer(sead::Buffer& buffer, int size, sead::Heap* heap, + int alignment = sizeof(void*)) { + return buffer.tryAllocBuffer(size, heap, alignment); +} + +bool ModelList::parseModelData(const agl::utl::ResParameterList& res, sead::Heap* heap) { + if (!allocModelDataBuffer(mModelData, res.getResParameterListNum() != 0, heap)) + return false; + + sead::FixedSafeString<32> list_name{str_ModelData}; + list_name.append("_"); + const auto list_name_base_len = list_name.calcLength(); + + for (auto it = mModelData.begin(), it_end = mModelData.end(); it != it_end; ++it) { + list_name.trim(list_name_base_len); + list_name.appendWithFormat("%d", it.getIndex()); + + it->folder.init("", "Folder", "", &it->base_obj); + it->list.addObj(&it->base_obj, "Base"); + + const auto unit_list = + agl::utl::getResParameterList(res.getResParameterList(it.getIndex()), str_Unit); + if (unit_list.ptr()) { + const u32 num_units = unit_list.getResParameterObjNum(); + if (num_units != 0) { + if (!it->units.tryAllocBuffer(std::min(num_units, NumUnitMax), heap)) + return false; + + sead::FixedSafeString<32> unit_name{str_Unit}; + unit_name.append("_"); + const auto unit_name_base_len = unit_name.calcLength(); + + for (auto unit = it->units.begin(), end = it->units.end(); unit != end; ++unit) { + unit_name.trim(unit_name_base_len); + unit_name.appendWithFormat("%d", unit.getIndex()); + + unit->unit_name.init("", "UnitName", "", &unit->obj); + unit->bind_bone.init("", "BindBone", "", &unit->obj); + it->unit_list.addObj(&unit->obj, unit_name); + } + } + } + + it->list.addList(&it->unit_list, str_Unit); + mModelDataList.addList(&it->list, list_name); + } + + return true; +} + +bool allocAnmTargetPartialBuffer(sead::Buffer& buffer, int size, + sead::Heap* heap, int alignment = sizeof(void*)) { + return buffer.tryAllocBuffer(size, heap, alignment); +} + +bool ModelList::parseAnmTarget(const agl::utl::ResParameterList& res, sead::Heap* heap) { + if (!mAnmTargets.tryAllocBuffer(std::min(res.getResParameterListNum(), NumUnitMax), heap)) + return false; + + sead::FixedSafeString<32> list_name{str_AnmTarget}; + list_name.append("_"); + const auto list_name_base_len = list_name.calcLength(); + + for (auto it = mAnmTargets.begin(), it_end = mAnmTargets.end(); it != it_end; ++it) { + list_name.trim(list_name_base_len); + list_name.appendWithFormat("%d", it.getIndex()); + + it->num_as_slot.init(0, "NumASSlot", "", &it->base_obj); + // "is particle enabled" (particle is misspelled as "partical" [sic]) + it->is_partical_enable.init(false, "IsParticalEnable", "", &it->base_obj); + it->target_type.init(0, "TargetType", "", &it->base_obj); + it->list.addObj(&it->base_obj, "Base"); + + const auto partials = + agl::utl::getResParameterList(res.getResParameterList(it.getIndex()), str_Partial); + if (partials.ptr() && partials.getResParameterObjNum() != 0) { + if (!allocAnmTargetPartialBuffer(it->partials, partials.getResParameterObjNum(), heap)) + return false; + + sead::FixedSafeString<32> partial_name{str_Partial}; + partial_name.append("_"); + const auto partial_name_base_len = partial_name.calcLength(); + + for (auto partial = it->partials.begin(), partial_end = it->partials.end(); + partial != partial_end; ++partial) { + partial_name.trim(partial_name_base_len); + partial_name.appendWithFormat("%d", partial.getIndex()); + + partial->bone.init("", "Bone", "", &partial->obj); + partial->bind_flag.init(0, "BindFlg", "", &partial->obj); + partial->recursible.init(true, "Recursible", "", &partial->obj); + it->partial_list.addObj(&partial->obj, partial_name); + } + } + + it->list.addList(&it->partial_list, str_Partial); + mAnmTargetList.addList(&it->list, list_name); + } + + return true; +} + +int ModelList::getNumAnmTargets() const { + return mAnmTargets.size(); +} + +void ModelList::getModelDataInfo(ModelList::ModelDataInfo* info) const { + *info = {}; + + if (mModelData.size() > 0) { + info->num_model_data = mModelData.size(); + for (auto it = mModelData.begin(), end = mModelData.end(); it != end; ++it) { + const s32 idx = it.getIndex(); + + info->folder_name[idx] = it->folder.ref().cstr(); + info->num_units[idx] = it->units.size(); + + for (auto unit = it->units.begin(), uend = it->units.end(); unit != uend; ++unit) { + const s32 unit_idx = unit.getIndex(); + info->unit_names[idx][unit_idx] = unit->unit_name.ref().cstr(); + info->unit_bind_bones[idx][unit_idx] = unit->bind_bone.ref().cstr(); + } + + if (info->unit_names[idx][0]) { + const char* name = ModelResourceDivide::instance()->getModelResource( + info->folder_name[idx], info->unit_names[idx][0]); + if (name) + info->folder_name[idx] = name; + } + } + } + + info->base_scale = mControllerInfo->mBaseScale.ref(); +} + +bool ModelList::getAttentionInfo(AttentionInfo* info) const { + if (!mAttention->mIsEnableAttention.ref()) { + info->look_at_bone = {}; + info->look_at_offset = sead::Vector3f::zero; + + info->cursor_offset_y = {}; + info->ai_info_offset_y = {}; + + info->cut_target_bone = {}; + info->cut_target_offset = sead::Vector3f::zero; + + info->game_camera_bone = {}; + info->game_camera_offset = sead::Vector3f::zero; + + info->bow_camera_bone = {}; + info->bow_camera_offset = sead::Vector3f::zero; + + info->attack_target_bone = {}; + info->attack_target_offset = sead::Vector3f::zero; + info->attack_target_offset_back = {}; + + info->cursor_ai_info_base_bone = {}; + info->cursor_ai_info_base_offset = sead::Vector3f::zero; + + return false; + } + + info->look_at_bone = mAttention->mLookAtBone.ref().cstr(); + info->look_at_offset = mAttention->mLookAtOffset.ref(); + + info->cursor_offset_y = mAttention->mCursorOffsetY.ref(); + info->ai_info_offset_y = mAttention->mAIInfoOffsetY.ref(); + + info->cut_target_bone = mAttention->mCutTargetBone.ref().cstr(); + info->cut_target_offset = mAttention->mCutTargetOffset.ref(); + + info->game_camera_bone = mAttention->mGameCameraBone.ref().cstr(); + info->game_camera_offset = mAttention->mGameCameraOffset.ref(); + + info->bow_camera_bone = mAttention->mBowCameraBone.ref().cstr(); + info->bow_camera_offset = mAttention->mBowCameraOffset.ref(); + + info->attack_target_bone = mAttention->mAttackTargetBone.ref().cstr(); + info->attack_target_offset = mAttention->mAttackTargetOffset.ref(); + info->attack_target_offset_back = mAttention->mAttackTargetOffsetBack.ref(); + + if (mAttention->mAtObstacleChkUseLookAtPos.ref()) { + info->at_obstacle_chk_bone = mAttention->mLookAtBone.ref().cstr(); + info->at_obstacle_chk_offset = mAttention->mLookAtOffset.ref(); + } else { + info->at_obstacle_chk_bone = mAttention->mAtObstacleChkOffsetBone.ref().cstr(); + info->at_obstacle_chk_offset = mAttention->mAtObstacleChkOffset.ref(); + } + + info->cursor_ai_info_base_bone = mAttention->mCursorAIInfoBaseBone.ref().cstr(); + info->cursor_ai_info_base_offset = mAttention->mCursorAIInfoBaseOffset.ref(); + + const auto clear_if_empty = [](const char** s) { + if (!(*s)[0]) + *s = nullptr; + }; + + clear_if_empty(&info->look_at_bone); + clear_if_empty(&info->cut_target_bone); + clear_if_empty(&info->game_camera_bone); + clear_if_empty(&info->bow_camera_bone); + clear_if_empty(&info->attack_target_bone); + clear_if_empty(&info->at_obstacle_chk_bone); + clear_if_empty(&info->cursor_ai_info_base_bone); + + return true; +} + +act::InfoData::Locator::Type ModelList::getLocatorTypeFromStr(const sead::SafeString& type) { + for (s32 i = 0; i < sLocatorTypes.size(); ++i) { + if (type == sLocatorTypes[i]) + return act::InfoData::Locator::Type(i); + } + return act::InfoData::Locator::Type::Invalid; +} + +// NON_MATCHING: weird unrolling and Vector3f store (str should be a stp) +bool ModelList::getLocatorInfo(act::InfoData::Locator* info, + act::InfoData::Locator::Type type) const { + agl::utl::ResParameterArchive archive{mRawData}; + const auto root = archive.getRootList(); + + for (int i = 0;; ++i) { + const auto obj = + agl::utl::getResParameterObj(root, sead::FormatFixedSafeString<32>("Locator_%d", i)); + if (!obj.ptr()) + return false; + + const char* expected_type_str = sLocatorTypes[u32(type)]; + + if (sead::SafeString(getString(obj, "Type", "")) != expected_type_str) + continue; + + info->pos = getVec3(obj, "Pos", sead::Vector3f::zero); + info->rot = getVec3(obj, "Rot", sead::Vector3f::zero); + info->type = type; + return true; + } + + return false; +} + +bool ModelList::isParticalEnable(int anm_target_idx) const { + return mAnmTargets[anm_target_idx].is_partical_enable.ref(); +} + +int ModelList::getNumASSlot(int anm_target_idx) const { + return mAnmTargets[anm_target_idx].num_as_slot.ref(); +} + +int ModelList::getNumPartials(int anm_target_idx) const { + return mAnmTargets[anm_target_idx].partials.size(); +} + +void ModelList::getPartialInfo(PartialInfo* info, int anm_target_idx, int partial_idx) const { + if (mAnmTargets.size() > 0) { + const auto& partial = mAnmTargets[anm_target_idx].partials[partial_idx]; + info->bone = partial.bone.ref(); + info->bind_flag = partial.bind_flag.ref(); + info->recursible = partial.recursible.ref(); + } else { + info->bone = ""; + info->bind_flag = 0; + info->recursible = true; + } +} + } // namespace ksys::res diff --git a/src/KingSystem/Resource/resResourceModelList.h b/src/KingSystem/Resource/resResourceModelList.h index 58038559..d614ade5 100644 --- a/src/KingSystem/Resource/resResourceModelList.h +++ b/src/KingSystem/Resource/resResourceModelList.h @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include "KingSystem/ActorSystem/actInfoData.h" #include "KingSystem/Resource/resResource.h" #include "KingSystem/Utils/ParamIO.h" @@ -14,39 +16,39 @@ class ModelList : public ParamIO, public Resource { SEAD_RTTI_OVERRIDE(ModelList, Resource) public: struct ControllerInfo { - agl::utl::Parameter _2b0; - agl::utl::Parameter _2d8; - agl::utl::ParameterObj mControllerInfo; + agl::utl::Parameter mAddColor; + agl::utl::Parameter mMulColor; + agl::utl::ParameterObj mObj; agl::utl::Parameter mBaseScale; - agl::utl::Parameter _358; - agl::utl::Parameter _380; - agl::utl::Parameter _3a0; - agl::utl::Parameter _3c8; - agl::utl::Parameter _3e8; + agl::utl::Parameter mVariationMatAnim; + agl::utl::Parameter mVariationMatAnimFrame; + agl::utl::Parameter mVariationShaderAnim; + agl::utl::Parameter mVariationShaderAnimFrame; + agl::utl::Parameter mCalcAABBASKey; }; KSYS_CHECK_SIZE_NX150(ControllerInfo, 0x160); struct Attention { - agl::utl::Parameter _0; - agl::utl::Parameter _20; - agl::utl::Parameter _48; - agl::utl::Parameter _70; - agl::utl::Parameter _90; - agl::utl::Parameter _b0; - agl::utl::Parameter _d8; - agl::utl::Parameter _100; - agl::utl::Parameter _128; - agl::utl::Parameter _150; - agl::utl::Parameter _178; - agl::utl::Parameter _1a0; - agl::utl::Parameter _1c8; - agl::utl::Parameter _1f0; - agl::utl::Parameter _210; - agl::utl::Parameter _238; - agl::utl::Parameter _260; - agl::utl::Parameter _280; - agl::utl::Parameter _2a8; - agl::utl::ParameterObj _2d0; + agl::utl::Parameter mIsEnableAttention; + agl::utl::Parameter mLookAtBone; + agl::utl::Parameter mLookAtOffset; + agl::utl::Parameter mCursorOffsetY; + agl::utl::Parameter mAIInfoOffsetY; + agl::utl::Parameter mCutTargetBone; + agl::utl::Parameter mCutTargetOffset; + agl::utl::Parameter mGameCameraBone; + agl::utl::Parameter mGameCameraOffset; + agl::utl::Parameter mBowCameraBone; + agl::utl::Parameter mBowCameraOffset; + agl::utl::Parameter mAttackTargetBone; + agl::utl::Parameter mAttackTargetOffset; + agl::utl::Parameter mAttackTargetOffsetBack; + agl::utl::Parameter mAtObstacleChkOffsetBone; + agl::utl::Parameter mAtObstacleChkOffset; + agl::utl::Parameter mAtObstacleChkUseLookAtPos; + agl::utl::Parameter mCursorAIInfoBaseBone; + agl::utl::Parameter mCursorAIInfoBaseOffset; + agl::utl::ParameterObj mObj; }; KSYS_CHECK_SIZE_NX150(Attention, 0x300); @@ -86,6 +88,44 @@ public: }; KSYS_CHECK_SIZE_NX150(AnmTarget, 0x130); + struct ModelDataInfo { + std::array, 1> unit_names; + std::array, 1> unit_bind_bones; + std::array num_units; + std::array folder_name; + int num_model_data; + sead::Vector3f base_scale; + }; + KSYS_CHECK_SIZE_NX150(ModelDataInfo, 0xa0); + + struct AttentionInfo { + const char* look_at_bone; + sead::Vector3f look_at_offset; + float cursor_offset_y; + float ai_info_offset_y; + const char* cut_target_bone; + sead::Vector3f cut_target_offset; + const char* game_camera_bone; + sead::Vector3f game_camera_offset; + const char* bow_camera_bone; + sead::Vector3f bow_camera_offset; + const char* attack_target_bone; + sead::Vector3f attack_target_offset; + float attack_target_offset_back; + const char* at_obstacle_chk_bone; + sead::Vector3f at_obstacle_chk_offset; + const char* cursor_ai_info_base_bone; + sead::Vector3f cursor_ai_info_base_offset; + }; + KSYS_CHECK_SIZE_NX150(AttentionInfo, 0xb0); + + struct PartialInfo { + sead::SafeString bone; + int bind_flag; + bool recursible; + }; + KSYS_CHECK_SIZE_NX150(PartialInfo, 0x18); + ModelList(); ~ModelList() override; @@ -99,9 +139,23 @@ public: const sead::Buffer& getAnmTargets() const { return mAnmTargets; } bool is7C8() const { return _7c8; } + int getNumAnmTargets() const; + void getModelDataInfo(ModelDataInfo* info) const; + bool getAttentionInfo(AttentionInfo* info) const; + bool getLocatorInfo(act::InfoData::Locator* info, act::InfoData::Locator::Type type) const; + bool isParticalEnable(int anm_target_idx) const; + int getNumASSlot(int anm_target_idx) const; + int getNumPartials(int anm_target_idx) const; + void getPartialInfo(PartialInfo* info, int anm_target_idx, int partial_idx) const; + + static act::InfoData::Locator::Type getLocatorTypeFromStr(const sead::SafeString& type); + private: - sead::StorageFor mControllerInfo{sead::ZeroInitializeTag{}}; - sead::StorageFor mAttention{sead::ZeroInitializeTag{}}; + bool parseModelData(const agl::utl::ResParameterList& res, sead::Heap* heap); + bool parseAnmTarget(const agl::utl::ResParameterList& res, sead::Heap* heap); + + sead::StorageFor mControllerInfo{sead::ZeroInitializeTag{}}; + sead::StorageFor mAttention{sead::ZeroInitializeTag{}}; u8* mRawData{}; sead::Buffer mModelData; agl::utl::ParameterList mModelDataList; diff --git a/src/KingSystem/Utils/CMakeLists.txt b/src/KingSystem/Utils/CMakeLists.txt index a7baab79..7efc89f2 100644 --- a/src/KingSystem/Utils/CMakeLists.txt +++ b/src/KingSystem/Utils/CMakeLists.txt @@ -70,6 +70,7 @@ target_sources(uking PRIVATE HeapUtil.cpp HeapUtil.h InitTimeInfo.h + ParamIO.cpp ParamIO.h SafeDelete.h StrTreeMap.h diff --git a/src/KingSystem/Utils/ParamIO.cpp b/src/KingSystem/Utils/ParamIO.cpp new file mode 100644 index 00000000..de9d0bc5 --- /dev/null +++ b/src/KingSystem/Utils/ParamIO.cpp @@ -0,0 +1,21 @@ +#include "KingSystem/Utils/ParamIO.h" +#include + +namespace ksys { + +const char* ParamIO::getString(const agl::utl::ResParameterObj& obj, const char* key, + const char* default_value, void*) const { + const auto param = agl::utl::getResParameter(obj, key); + if (!param.ptr()) + return default_value; + return param.getData(); +} + +// NON_MATCHING: how the default_value Vec3f is stored on the stack +sead::Vector3f ParamIO::getVec3(const agl::utl::ResParameterObj& obj, const char* key, + sead::Vector3f default_value, void*) const { + const auto param = agl::utl::getResParameter(obj, key); + return param.ptr() ? *param.getData() : default_value; +} + +} // namespace ksys diff --git a/src/KingSystem/Utils/ParamIO.h b/src/KingSystem/Utils/ParamIO.h index 820cdc76..b960f18f 100644 --- a/src/KingSystem/Utils/ParamIO.h +++ b/src/KingSystem/Utils/ParamIO.h @@ -2,6 +2,7 @@ #include #include +#include #include #include "KingSystem/Utils/Types.h" @@ -15,6 +16,11 @@ public: bool applyResourceUpdate(const char* data, const char* data1); + const char* getString(const agl::utl::ResParameterObj& obj, const char* key, + const char* default_value, void* = nullptr) const; + sead::Vector3f getVec3(const agl::utl::ResParameterObj& obj, const char* key, + sead::Vector3f default_value, void* = nullptr) const; + u32 getIdx() const { return mIdx; } sead::BufferedSafeString& getPath() { return mPath; } const sead::BufferedSafeString& getPath() const { return mPath; }