summaryrefslogtreecommitdiff
path: root/src/KingSystem/Resource/Actor/resResourceASSetting.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/KingSystem/Resource/Actor/resResourceASSetting.cpp')
-rw-r--r--src/KingSystem/Resource/Actor/resResourceASSetting.cpp472
1 files changed, 472 insertions, 0 deletions
diff --git a/src/KingSystem/Resource/Actor/resResourceASSetting.cpp b/src/KingSystem/Resource/Actor/resResourceASSetting.cpp
new file mode 100644
index 00000000..915bd1c4
--- /dev/null
+++ b/src/KingSystem/Resource/Actor/resResourceASSetting.cpp
@@ -0,0 +1,472 @@
+#include "KingSystem/Resource/Actor/resResourceASSetting.h"
+#include <container/seadSafeArray.h>
+#include <optional>
+#include <prim/seadSafeString.h>
+#include "KingSystem/Resource/Actor/resResourceASResourceExtension.h"
+#include "KingSystem/Resource/Actor/resResourceASSettingMgr.h"
+#include "KingSystem/Resource/resLoadRequest.h"
+
+namespace ksys::res {
+
+bool ASFrameCtrlParser::parse(const ASParamParser::ParseArgs& args) {
+ mRate.init(1.0, "Rate", "再生速度", "Min=0.f,Max=10.f", &mObj);
+ mStartFrame.init(0.0, "StartFrame", "開始フレーム", "Min=0.f,Max=100.f", &mObj);
+ mEndFrame.init(-1.0, "EndFrame", "終了フレーム", "Min=-1.f,Max=100.f", &mObj);
+ mLoopStopCount.init(-1.0, "LoopStopCount", "ループ停止回数", "Min=-1.f,Max=10.f", &mObj);
+ mLoopStopCountRandom.init(0.0, "LoopStopCountRandom", "ランダムループ追加回数",
+ "Min=0.f,Max=10.f", &mObj);
+ mReversePlay.init(false, "ReversePlay", "逆再生", "", &mObj);
+ mUseGlobalFrame.init(false, "UseGlobalFrame", "グローバルフレーム使う", "", &mObj);
+ mFootType.init(0, "FootType", "足解決", "", &mObj);
+ mConnect.init(false, "Connect", "接続", "", &mObj);
+ mAnmLoop.init(0, "AnmLoop", "ループ設定", "", &mObj);
+
+ mList.addObj(&mObj, "FrameCtrl0");
+ return true;
+}
+
+bool ASTriggerEventsParser::parse(const ASParamParser::ParseArgs& args) {
+ const int num_objs = args.res_list.getResParameterObjNum();
+ if (num_objs == 0)
+ return true;
+
+ if (!mEvents.tryAllocBuffer(num_objs, args.heap))
+ return false;
+
+ auto it = mEvents.begin();
+ const auto end = mEvents.end();
+
+ sead::FixedSafeString<32> obj_name{"Event"};
+ const auto obj_name_prefix_len = obj_name.calcLength();
+
+ auto res_it = args.res_list.objBegin();
+ const auto res_end = args.res_list.objEnd();
+
+ while (res_it != res_end && it != end) {
+ u32 type_index = -1;
+ const auto TypeIndex = agl::utl::getResParameter(res_it.getObj(), "TypeIndex");
+ if (TypeIndex.ptr())
+ type_index = *TypeIndex.getData<int>();
+
+ // TODO: add a TypeIndex enum
+ it->type_index = type_index > 33 ? 88 : int(type_index) + 54;
+
+ it->frame.init(0.0, "Frame", "フレーム", "Min=0.f,Max=100.f", &it->obj);
+ it->value.init("", "Value", "値", "", &it->obj);
+
+ obj_name.trim(obj_name_prefix_len);
+ obj_name.appendWithFormat("%d", it.getIndex());
+ mList.addObj(&it->obj, obj_name);
+
+ ++res_it;
+ ++it;
+ }
+
+ return true;
+}
+
+bool ASHoldEventsParser::parse(const ASParamParser::ParseArgs& args) {
+ const int num_objs = args.res_list.getResParameterObjNum();
+ if (num_objs == 0)
+ return true;
+
+ if (!mEvents.tryAllocBuffer(num_objs, args.heap))
+ return false;
+
+ auto it = mEvents.begin();
+ const auto end = mEvents.end();
+
+ sead::FixedSafeString<32> obj_name{"Event"};
+ const auto obj_name_prefix_len = obj_name.calcLength();
+
+ auto res_it = args.res_list.objBegin();
+ const auto res_end = args.res_list.objEnd();
+
+ while (res_it != res_end && it != end) {
+ u32 type_index = -1;
+ const auto TypeIndex = agl::utl::getResParameter(res_it.getObj(), "TypeIndex");
+ if (TypeIndex.ptr())
+ type_index = *TypeIndex.getData<int>();
+
+ // TODO: add a TypeIndex enum
+ it->type_index = type_index > 53 ? 88 : int(type_index);
+
+ it->start_frame.init(0.0, "StartFrame", "開始フレーム", "Min=0.f,Max=100.f", &it->obj);
+ it->end_frame.init(0.0, "EndFrame", "終了フレーム", "Min=0.f,Max=100.f", &it->obj);
+ it->value.init("", "Value", "値", "", &it->obj);
+
+ obj_name.trim(obj_name_prefix_len);
+ obj_name.appendWithFormat("%d", it.getIndex());
+ mList.addObj(&it->obj, obj_name);
+
+ ++res_it;
+ ++it;
+ }
+
+ return true;
+}
+
+bool ASStringArrayParser::parse(const ASParamParser::ParseArgs& args) {
+ const int size = args.res_list.getResParameterObj(0).getNum();
+ if (size != 0) {
+ if (!mValues.tryAllocBuffer(size, args.heap))
+ return false;
+
+ sead::FixedSafeString<32> param_name{"Value"};
+ const auto param_name_prefix_len = param_name.calcLength();
+
+ for (int i = 0; i < size; ++i) {
+ param_name.trim(param_name_prefix_len);
+ param_name.appendWithFormat("%d", i);
+ mValues[i].value.init("", param_name, "値", "", &mObj);
+ }
+ }
+
+ mList.addObj(&mObj, "StringArray0");
+ return true;
+}
+
+bool ASRangesParser::parse(const ASParamParser::ParseArgs& args) {
+ const int num_objs = args.res_list.getResParameterObjNum();
+ if (num_objs == 0)
+ return true;
+
+ if (!mRanges.tryAllocBuffer(num_objs, args.heap))
+ return false;
+
+ auto it = mRanges.begin();
+ const auto end = mRanges.end();
+
+ sead::FixedSafeString<32> obj_name{"Range"};
+ const auto obj_name_prefix_len = obj_name.calcLength();
+
+ auto res_it = args.res_list.objBegin();
+ const auto res_end = args.res_list.objEnd();
+
+ while (res_it != res_end && it != end) {
+ obj_name.trim(obj_name_prefix_len);
+ obj_name.appendWithFormat("%d", it.getIndex());
+
+ it->start.init(0.0, "Start", "開始", "Min=0.f,Max=1.f", &it->obj);
+ it->end.init(0.0, "End", "終了", "Min=0.f,Max=1.f", &it->obj);
+
+ mList.addObj(&it->obj, obj_name);
+
+ ++res_it;
+ ++it;
+ }
+
+ return true;
+}
+
+bool ASFloatArrayParser::parse(const ASParamParser::ParseArgs& args) {
+ const int size = args.res_list.getResParameterObj(0).getNum();
+ if (size != 0) {
+ if (!mValues.tryAllocBuffer(size, args.heap))
+ return false;
+
+ sead::FixedSafeString<32> param_name{"Value"};
+ const auto param_name_prefix_len = param_name.calcLength();
+
+ for (int i = 0; i < size; ++i) {
+ param_name.trim(param_name_prefix_len);
+ param_name.appendWithFormat("%d", i);
+ mValues[i].value.init(1.0, param_name, "値", "", &mObj);
+ }
+ }
+
+ mList.addObj(&mObj, "FloatArray0");
+ return true;
+}
+
+bool ASIntArrayParser::parse(const ASParamParser::ParseArgs& args) {
+ const int size = args.res_list.getResParameterObj(0).getNum();
+ if (size != 0) {
+ if (!mValues.tryAllocBuffer(size, args.heap))
+ return false;
+
+ sead::FixedSafeString<32> param_name{"Value"};
+ const auto param_name_prefix_len = param_name.calcLength();
+
+ for (int i = 0; i < size; ++i) {
+ param_name.trim(param_name_prefix_len);
+ param_name.appendWithFormat("%d", i);
+ mValues[i].value.init(1, param_name, "値", "", &mObj);
+ }
+ }
+
+ mList.addObj(&mObj, "IntArray0");
+ return true;
+}
+
+bool ASBitIndexParser::parse(const ASParamParser::ParseArgs& args) {
+ const auto obj = args.res_list.getResParameterObj(0);
+ if (obj.getNum() < 1)
+ return true;
+
+ const auto TypeIndex = agl::utl::getResParameter(obj, "TypeIndex");
+ if (!TypeIndex.ptr())
+ return true;
+
+ mTypeIndex = *TypeIndex.getData<int>();
+ return true;
+}
+
+bool ASSetting::BoneParams::parse(const ASParamParser::ParseArgs& args) {
+ const auto num_objects = args.res_list.getResParameterObjNum();
+ if (num_objects == 0)
+ return true;
+
+ if (!mBuffer.tryAllocBuffer(num_objects, args.heap))
+ return false;
+
+ auto it = mBuffer.begin();
+ const auto end = mBuffer.end();
+
+ sead::FixedSafeString<32> obj_name{"BoneParam"};
+ const auto obj_name_base_len = obj_name.calcLength();
+
+ auto res_it = args.res_list.objBegin();
+ const auto res_end = args.res_list.objEnd();
+
+ for (; it != end && res_it != res_end; ++it, ++res_it) {
+ it->mBone.init("", "Bone", "ボーン名", "", &it->mObj);
+ it->mWeight.init(0.0, "Weight", "ウェイト値", "Min=0.f,Max=1.f", &it->mObj);
+
+ obj_name.trim(obj_name_base_len);
+ obj_name.appendWithFormat("%d", res_it.getIndex());
+ mList.addObj(&it->mObj, obj_name);
+ }
+
+ return true;
+}
+
+f32 ASSetting::BoneParams::getBoneWeight(const sead::SafeString& name) const {
+ for (const auto& param : mBuffer) {
+ if (name == *param.mBone)
+ return *param.mWeight;
+ }
+ return 1.0;
+}
+
+namespace {
+struct Factory {
+ const char* name;
+ ASParamParser* (*make)(sead::Heap* heap);
+};
+
+extern sead::SafeArray<Factory, ASParamParser::NumTypes> sASFactories;
+} // namespace
+
+ASExtensions::~ASExtensions() {
+ for (auto*& parser : mParsers) {
+ if (parser && parser->getType() != ASParamParser::Type::BlenderBone)
+ delete parser;
+ parser = nullptr;
+ }
+ mParsers.freeBuffer();
+}
+
+bool ASExtensions::parse(const ASExtensions::ParseArgs& args) {
+ const auto Extend = agl::utl::getResParameterList(args.res_list, "Extend");
+ if (!Extend)
+ return true;
+
+ const auto num_extensions = Extend.getResParameterListNum();
+ if (num_extensions == 0)
+ return true;
+
+ if (!mParsers.tryAllocBuffer(num_extensions, args.heap))
+ return false;
+ mParsers.fill(nullptr);
+
+ auto it = mParsers.begin();
+ const auto end = mParsers.end();
+
+ ASParamParser::ParseArgs parse_args{};
+ parse_args.list = &mList;
+ parse_args.heap = args.heap;
+
+ auto res_it = Extend.listBegin();
+ const auto res_end = Extend.listEnd();
+
+ for (; it != end && res_it != res_end; ++it, ++res_it) {
+ parse_args.res_list = res_it.getList();
+ *it = makeParser(parse_args);
+
+ constexpr int bone = int(ASParamParser::Type::BlenderBone);
+ if (*it == nullptr && parse_args.res_list.getParameterListNameHash() !=
+ agl::utl::ParameterBase::calcHash(sASFactories[bone].name)) {
+ return false;
+ }
+ }
+
+ args.list->addList(&mList, "Extend");
+ return true;
+}
+
+ASParamParser* ASExtensions::makeParser(const ASParamParser::ParseArgs& args) const {
+ const auto is_factory = [&args](int i) {
+ return args.res_list.getParameterListNameHash() ==
+ agl::utl::ParameterBase::calcHash(sASFactories[i].name);
+ };
+
+ std::optional<int> type;
+ for (int i = 0; i < ASParamParser::NumTypes - 1; ++i) {
+ if (!is_factory(i))
+ continue;
+ type = i;
+ break;
+ }
+
+ if (!type.has_value() && is_factory(int(ASParamParser::Type::BlenderBone))) {
+ const auto obj = args.res_list.getResParameterObj(0);
+ if (obj.getNum() > 0) {
+ const sead::SafeString name = obj.getResParameter(0).getData<const char>();
+ return ASSettingMgr::instance()->getBoneParams(name);
+ }
+ }
+
+ if (!type.has_value())
+ return nullptr;
+
+ const auto& factory = sASFactories[*type];
+
+ auto* parser = factory.make(args.heap);
+ if (!parser)
+ return nullptr;
+
+ if (!parser->parse(args)) {
+ delete parser;
+ return nullptr;
+ }
+
+ args.list->addList(&parser->getList(), factory.name);
+ return parser;
+}
+
+// NON_MATCHING: sead::DirectResource to res::ASSetting cast nullptr check; branching for the return
+ASParamParser* ASSettingMgr::getBoneParams(const sead::SafeString& key) const {
+ auto* res = sead::DynamicCast<ASSetting>(mHandle.getResource());
+ if (!res)
+ return nullptr;
+
+ for (auto& bones : res->getBlenderBones()) {
+ if (key == bones.mKeyName.ref())
+ return &bones.mBoneParams;
+ }
+ return nullptr;
+}
+
+ASParamParser* ASExtensions::getParser(ASParamParser::Type type) const {
+ for (int i = 0, n = mParsers.size(); i < n; ++i) {
+ auto* parser = mParsers[i];
+ if (parser && parser->getType() == type)
+ return parser;
+ }
+ return nullptr;
+}
+
+ASSetting::ASSetting() {
+ mType = "assetting";
+ mVersion = 0;
+}
+
+ASSetting::~ASSetting() {
+ mBlenderBones.freeBuffer();
+}
+
+void ASSetting::doCreate_(u8* buffer, u32 buffer_size, sead::Heap* heap) {}
+
+bool allocBlenderBones(sead::Buffer<ASSetting::BlenderBone>& buffer, int size, sead::Heap* heap,
+ int align = sizeof(void*));
+
+bool ASSetting::parse_(u8* data, size_t size, sead::Heap* heap) {
+ if (!data)
+ return true;
+
+ agl::utl::ResParameterArchive archive{data};
+ const auto root = archive.getRootList();
+
+ addList(&mBlenderBoneList, "BlenderBone");
+
+ const auto lists = agl::utl::getResParameterList(root, "BlenderBone");
+ if (!lists.ptr())
+ return true;
+
+ const auto num_blender_bones = lists.getResParameterListNum();
+ if (num_blender_bones == 0)
+ return true;
+
+ if (!allocBlenderBones(mBlenderBones, num_blender_bones, heap))
+ return false;
+
+ auto res_it = lists.listBegin();
+ const auto res_it_end = lists.listEnd();
+ sead::FixedSafeString<32> list_name{"BlenderBone"};
+ const auto list_name_base_len = list_name.calcLength();
+
+ ASParamParser::ParseArgs args;
+ args.res_list = {};
+ args.heap = heap;
+
+ auto it = mBlenderBones.begin();
+ const auto end = mBlenderBones.end();
+ for (; it != end && res_it != res_it_end; ++it, ++res_it) {
+ list_name.trim(list_name_base_len);
+ list_name.appendWithFormat("%d", it.getIndex());
+ mBlenderBoneList.addList(&it->mList, list_name);
+
+ it->mKeyName.init("", "KeyName", "キー名", "", &it->mNameParamObj);
+ it->mList.addObj(&it->mNameParamObj, "NameParam");
+ it->mList.addList(&it->mBoneParams.getList(), "BoneParam");
+
+ const auto list = *res_it;
+ args.list = &it->mList;
+ args.res_list = agl::utl::getResParameterList(list, "BoneParam");
+ if (!it->mBoneParams.parse(args))
+ return false;
+ }
+
+ applyResParameterArchive(archive);
+ return true;
+}
+
+bool allocBlenderBones(sead::Buffer<ASSetting::BlenderBone>& buffer, int size, sead::Heap* heap,
+ int align) {
+ return buffer.tryAllocBuffer(size, heap, align);
+}
+
+SEAD_SINGLETON_DISPOSER_IMPL(ASSettingMgr)
+
+void ASSettingMgr::init(const sead::SafeString& config_path, sead::Heap* heap) {
+ LoadRequest req;
+ req.mRequester = "ASSetting";
+ req._22 = true;
+ mHandle.load(config_path, &req);
+}
+
+template <typename T>
+static ASParamParser* factoryImpl_(sead::Heap* heap) {
+ return new (heap) T;
+}
+
+static ASParamParser* dummyASParserFactoryImpl_(sead::Heap*) {
+ return nullptr;
+}
+
+namespace {
+sead::SafeArray<Factory, ASParamParser::NumTypes> sASFactories{{
+ {"FrameCtrl", factoryImpl_<ASFrameCtrlParser>},
+ {"TriggerEvents", factoryImpl_<ASTriggerEventsParser>},
+ {"HoldEvents", factoryImpl_<ASHoldEventsParser>},
+ {"StringArray", factoryImpl_<ASStringArrayParser>},
+ {"Ranges", factoryImpl_<ASRangesParser>},
+ {"FloatArray", factoryImpl_<ASFloatArrayParser>},
+ {"IntArray", factoryImpl_<ASIntArrayParser>},
+ {"BitIndex", factoryImpl_<ASBitIndexParser>},
+ {"BlenderBone", dummyASParserFactoryImpl_},
+}};
+} // namespace
+
+} // namespace ksys::res