/* by korenkonder GitHub/GitLab: korenkonder */ #include "rob.hpp" #include "../../KKdLib/prj/algorithm.hpp" #include "../../KKdLib/str_utils.hpp" #include "../data.hpp" #include "../mdata_manager.hpp" #include "skin_param.hpp" struct osage_setting { std::map, osage_setting_osg_cat> cat; std::map obj; osage_setting(); ~osage_setting(); void clear(); const osage_setting_osg_cat* get_cat_value( object_info* obj_info, const char* root_node); void load(); void parse(key_val* kv); rob_osage_parts parse_parts_string(std::string& s); }; struct skin_param_file { p_file_handler* file_handler; item_id id; int32_t type; std::vector* data; rob_chara* rob_chr; skin_param_file(); ~skin_param_file(); }; struct skin_param_key { object_info obj_info; uint32_t motion_id; int32_t frame; inline skin_param_key() { motion_id = -1; frame = -1; } inline skin_param_key(object_info obj_info) { this->obj_info = obj_info; motion_id = -1; frame = -1; } inline skin_param_key(object_info obj_info, uint32_t motion_id) { this->obj_info = obj_info; this->motion_id = motion_id; frame = -1; } inline skin_param_key(object_info obj_info, uint32_t motion_id, int32_t frame) { this->obj_info = obj_info; this->motion_id = motion_id; this->frame = frame; } }; constexpr bool operator==(const skin_param_key& left, const skin_param_key& right) { return left.obj_info == right.obj_info && left.motion_id == right.motion_id && left.frame == right.frame; } constexpr bool operator!=(const skin_param_key& left, const skin_param_key& right) { return !(left == right); } constexpr bool operator<(const skin_param_key& left, const skin_param_key& right) { if (left.obj_info != right.obj_info) return left.obj_info < right.obj_info; else if (left.motion_id != right.motion_id) return left.motion_id < right.motion_id; else if (left.frame != right.frame) return left.frame < right.frame; else return false; } constexpr bool operator>(const skin_param_key& left, const skin_param_key& right) { return right < left; } constexpr bool operator<=(const skin_param_key& left, const skin_param_key& right) { return !(right < left); } constexpr bool operator>=(const skin_param_key& left, const skin_param_key& right) { return !(left < right); } struct SkinParamManager : public app::Task { int32_t state; uint8_t index; std::vector osage_init; std::map*> object_motion_frame; std::map*> object_motion; std::map*> object; std::list files; SkinParamManager(); virtual ~SkinParamManager() override; virtual bool init() override; virtual bool ctrl() override; virtual bool dest() override; virtual void disp() override; bool add_task(std::vector& vec); void AddFiles(); bool CtrlFiles(); int32_t GetExtSkpFile(const osage_init_data& osage_init, const std::string& dir, std::string& file, void* data, const motion_database* mot_db); std::vector* GetSkinParamFileData( object_info obj_info, uint32_t motion_id, int32_t frame); void Reset(); }; struct sp_skp_db { std::map>> pv; std::map>> motion; std::vector farc_list; size_t farc_list_count; sp_skp_db(); ~sp_skp_db(); void clear(); void load(); void parse(key_val* kv); int32_t get_ext_skp_file(const osage_init_data& osage_init, const object_info obj_info, std::string& file, std::string& farc, void* data, const motion_database* mot_db); }; static bool osage_setting_data_load_file(void* data, const char* dir, const char* file, uint32_t hash); static SkinParamManager* skin_param_manager_get(int32_t chara_id); static bool sp_skp_db_load_file(void* data, const char* dir, const char* file, uint32_t hash); osage_setting* osage_setting_data; sp_skp_db* sp_skp_db_data; SkinParamManager* skin_param_manager; std::map> skin_param_storage; SkinParam::CollisionParam::CollisionParam() : type(), node_idx(), pos() { radius = 0.2f; } skin_param_osage_root_normal_ref::skin_param_osage_root_normal_ref() { } skin_param_osage_root_normal_ref::~skin_param_osage_root_normal_ref() { } skin_param_osage_root_boc::skin_param_osage_root_boc() : ed_node(), st_node() { } skin_param_osage_root_boc::~skin_param_osage_root_boc() { } skin_param_osage_root::skin_param_osage_root() : field_0(), force(), force_gain(), rot_y(), rot_z(), init_rot_y(), init_rot_z(), coli_r(), yz_order(), stiffness() { air_res = 0.5f; hinge_y = 90.0f; hinge_z = 90.0f; name = "NO-PARAM"; friction = 1.0f; wind_afc = 0.5f; coli_type = SkinParam::RootCollisionTypeEnd; move_cancel = -0.01f; coli.resize(13); } skin_param_osage_root::~skin_param_osage_root() { } skin_param::skin_param() : friction(), wind_afc(), air_res(), rot(), init_rot(), coli_type(), stiffness(), move_cancel(), coli_r(), force(), force_gain(), colli_tgt_osg() { reset(); } skin_param::~skin_param() { } void skin_param::set_skin_param_osage_root(const skin_param_osage_root& skp_root) { coli.assign(skp_root.coli.begin(), skp_root.coli.end()); friction = skp_root.friction; wind_afc = skp_root.wind_afc; air_res = skp_root.air_res; rot.y = skp_root.rot_y * DEG_TO_RAD_FLOAT; rot.z = skp_root.rot_z * DEG_TO_RAD_FLOAT; init_rot.y = skp_root.init_rot_y * DEG_TO_RAD_FLOAT; init_rot.z = skp_root.init_rot_z * DEG_TO_RAD_FLOAT; coli_type = skp_root.coli_type; stiffness = skp_root.stiffness; move_cancel = skp_root.move_cancel; coli_r = skp_root.coli_r; hinge.ymin = -skp_root.hinge_y; hinge.ymax = skp_root.hinge_y; hinge.zmin = -skp_root.hinge_z; hinge.zmax = skp_root.hinge_z; hinge.limit(); force = skp_root.force; force_gain = skp_root.force_gain; } skin_param_file_data::skin_param_file_data() : field_88() { } skin_param_file_data::~skin_param_file_data() { } osage_setting_osg_cat::osage_setting_osg_cat() : exf() { parts = ROB_OSAGE_PARTS_NONE; } const osage_setting_osg_cat* osage_setting_data_get_cat_value( object_info* obj_info, const char* root_node) { return osage_setting_data->get_cat_value(obj_info, root_node); } bool osage_setting_data_obj_has_key(object_info key) { return osage_setting_data->obj.find(key) != osage_setting_data->obj.end(); } void skin_param_data_init() { if (!osage_setting_data) osage_setting_data = new osage_setting; if (!sp_skp_db_data) sp_skp_db_data = new sp_skp_db; if (!skin_param_manager) skin_param_manager = new SkinParamManager[ROB_CHARA_COUNT]; skin_param_storage = {}; } void skin_param_data_load() { osage_setting_data->load(); sp_skp_db_data->load(); } void skin_param_data_free() { skin_param_storage.clear(); if (skin_param_manager) { delete[] skin_param_manager; skin_param_manager = 0; } if (sp_skp_db_data) { delete sp_skp_db_data; sp_skp_db_data = 0; } if (osage_setting_data) { delete osage_setting_data; osage_setting_data = 0; } } bool skin_param_manager_array_check_task_ready() { bool ret = false; for (int32_t i = 0; i < ROB_CHARA_COUNT; i++) ret |= app::TaskWork::check_task_ready(&skin_param_manager[i]); return ret; } bool skin_param_manager_add_task(int32_t chara_id, std::vector& vec) { return skin_param_manager[chara_id].add_task(vec); } bool skin_param_manager_check_task_ready(int32_t chara_id) { return app::TaskWork::check_task_ready(skin_param_manager_get(chara_id)); } int32_t skin_param_manager_get_ext_skp_file( int32_t chara_id, const osage_init_data& osage_init, const std::string& dir, std::string& file, void* data, const motion_database* mot_db) { return skin_param_manager_get(chara_id)->GetExtSkpFile(osage_init, dir, file, data, mot_db); } std::vector* skin_param_manager_get_skin_param_file_data( int32_t chara_id, object_info obj_info, uint32_t motion_id, int32_t frame) { return skin_param_manager_get(chara_id)->GetSkinParamFileData(obj_info, motion_id, frame); } void skin_param_manager_reset(int32_t chara_id) { skin_param_manager_get(chara_id)->Reset(); } void skin_param_osage_node_parse(void* kv, const char* name, std::vector* vec, skin_param_osage_root& skp_root) { key_val* _kv = (key_val*)kv; if (!_kv->open_scope(name)) return; if (!_kv->open_scope("node")) { _kv->close_scope(); return; } int32_t count; if (_kv->read("length", count)) { size_t c = vec->size(); if (c < count) vec->resize(count); } else vec->clear(); int32_t j = 0; for (auto i = vec->begin(); i != vec->end(); i++, j++) { if (!_kv->open_scope_fmt(j)) continue; *i = skin_param_osage_node(); float_t coli_r = 0.0f; if (_kv->read("coli_r", coli_r)) i->coli_r = coli_r; float_t weight = 0.0f; if (_kv->read("weight", weight)) i->weight = weight; float_t inertial_cancel = 0.0f; if (_kv->read("inertial_cancel", inertial_cancel)) i->inertial_cancel = inertial_cancel; i->hinge.ymin = -skp_root.hinge_y; i->hinge.ymax = skp_root.hinge_y; i->hinge.zmin = -skp_root.hinge_z; i->hinge.zmax = skp_root.hinge_z; float_t hinge_ymax = 0.0f; if (_kv->read("hinge_ymax", hinge_ymax)) i->hinge.ymax = hinge_ymax; float_t hinge_ymin = 0.0f; if (_kv->read("hinge_ymin", hinge_ymin)) i->hinge.ymin = hinge_ymin; float_t hinge_zmax = 0.0f; if (_kv->read("hinge_zmax", hinge_zmax)) i->hinge.zmax = hinge_zmax; float_t hinge_zmin = 0.0f; if (_kv->read("hinge_zmin", hinge_zmin)) i->hinge.zmin = hinge_zmin; _kv->close_scope(); } _kv->close_scope(); _kv->close_scope(); } void skin_param_osage_root_parse(void* kv, const char* name, skin_param_osage_root& skp_root, const bone_database* bone_data) { key_val* _kv = (key_val*)kv; if (!_kv->open_scope(name)) return; int32_t node_length = 0; _kv->read("node.length", node_length); if (!_kv->open_scope("root")) { _kv->close_scope(); return; } float_t force = 0.0f; float_t force_gain = 0.0f; if (_kv->read("force", force) && _kv->read("force_gain", force_gain)) { skp_root.force = force; skp_root.force_gain = force_gain; } float_t air_res = 0.0f; if (_kv->read("air_res", air_res)) skp_root.air_res = min_def(air_res, 0.9f); float_t rot_y = 0.0f; float_t rot_z = 0.0f; if (_kv->read("rot_y", rot_y) && _kv->read("rot_z", rot_z)) { skp_root.rot_y = rot_y; skp_root.rot_z = rot_z; } float_t friction = 0.0f; if (_kv->read("friction", friction)) skp_root.friction = friction; float_t wind_afc = 0; if (_kv->read("wind_afc", wind_afc)) { skp_root.wind_afc = wind_afc; if (!str_utils_compare_length(name, utf8_length(name), "c_opa", 5)) skp_root.wind_afc = 0.0f; } int32_t coli_type = 0; if (_kv->read("coli_type", coli_type)) skp_root.coli_type = (SkinParam::RootCollisionType)coli_type; float_t init_rot_y = 0.0f; float_t init_rot_z = 0.0f; if (_kv->read("init_rot_y", init_rot_y) && _kv->read("init_rot_z", init_rot_z)) { skp_root.init_rot_y = init_rot_y; skp_root.init_rot_z = init_rot_z; } float_t hinge_y = 0.0f; float_t hinge_z = 0.0f; if (_kv->read("hinge_y", hinge_y) && _kv->read("hinge_z", hinge_z)) { skp_root.hinge_y = hinge_y; skp_root.hinge_z = hinge_z; } float_t coli_r = 0.0f; if (_kv->read("coli_r", coli_r)) skp_root.coli_r = coli_r; float_t stiffness = 0.0f; if (_kv->read("stiffness", stiffness)) skp_root.stiffness = stiffness; float_t move_cancel = 0.0f; if (_kv->read("move_cancel", move_cancel)) skp_root.move_cancel = move_cancel; int32_t count; if (_kv->read("coli", "length", count)) { std::vector& vc = skp_root.coli; for (int32_t i = 0; i < count; i++) { if (!_kv->open_scope_fmt(i)) continue; SkinParam::CollisionParam* c = &vc[i]; int32_t type = 0; if (!_kv->read("type", type)) { _kv->close_scope(); break; } c->type = (SkinParam::CollisionType)type; float_t radius = 0; if (!_kv->read("radius", radius)) { _kv->close_scope(); break; } c->radius = radius; const char* bone0_name; if (!_kv->read("bone.0.name", bone0_name)) { _kv->close_scope(); break; } c->node_idx[0] = bone_data->get_skeleton_object_bone_index( bone_database_skeleton_type_to_string(BONE_DATABASE_SKELETON_COMMON), bone0_name); vec3 bone0_pos = 0.0f; if (!_kv->read("bone.0.posx", bone0_pos.x) || !_kv->read("bone.0.posy", bone0_pos.y) || !_kv->read("bone.0.posz", bone0_pos.z)) { _kv->close_scope(); break; } c->pos[0] = bone0_pos; const char* bone1_name; if (_kv->read("bone.1.name", bone1_name)) { c->node_idx[1] = bone_data->get_skeleton_object_bone_index( bone_database_skeleton_type_to_string(BONE_DATABASE_SKELETON_COMMON), bone1_name); vec3 bone1_pos = 0.0f; if (!_kv->read("bone.1.posx", bone1_pos.x) || !_kv->read("bone.1.posy", bone1_pos.y) || !_kv->read("bone.1.posz", bone1_pos.z)) { _kv->close_scope(); break; } c->pos[1] = bone1_pos; } _kv->close_scope(); } _kv->close_scope(); } if (_kv->read("boc", "length", count)) { std::vector* vb = &skp_root.boc; vb->reserve(count); for (int32_t i = 0; i < count; i++) { if (!_kv->open_scope_fmt(i)) continue; int32_t st_node = 0; std::string ed_root; int32_t ed_node = 0; if (_kv->read("st_node", st_node) && st_node < node_length && _kv->read("ed_root", ed_root) && _kv->read("ed_node", ed_node) && ed_node < node_length) { vb->push_back({}); skin_param_osage_root_boc& b = vb->back(); b.st_node = st_node; b.ed_root.assign(ed_root); b.ed_node = ed_node; } _kv->close_scope(); } _kv->close_scope(); } std::string colli_tgt_osg; if (_kv->read("colli_tgt_osg", colli_tgt_osg)) skp_root.colli_tgt_osg.assign(colli_tgt_osg); if (_kv->read("normal_ref", "length", count)) { std::vector* vnr = &skp_root.normal_ref; vnr->reserve(count); for (int32_t i = 0; i < count; i++) { if (!_kv->open_scope_fmt(i)) continue; std::string n; if (_kv->read("N", n)) { vnr->push_back({}); skin_param_osage_root_normal_ref& nr = vnr->back(); nr.n.assign(n); _kv->read("U", nr.u); _kv->read("D", nr.d); _kv->read("L", nr.l); _kv->read("R", nr.r); } _kv->close_scope(); } _kv->close_scope(); } _kv->close_scope(); _kv->close_scope(); } key_val* skin_param_storage_get_key_val(object_info obj_info) { auto elem = skin_param_storage.find(obj_info); if (elem != skin_param_storage.end()) return elem->second.get(); return 0; } void skin_param_storage_load(std::vector& obj_infos, void* data, const object_database* obj_db) { prj::sort_unique(obj_infos); for (const object_info& i : obj_infos) { if (i.is_null()) continue; const char* obj_name = obj_db->get_object_name(i); if (!obj_name) continue; std::string buf = string_to_lower(sprintf_s_string("ext_skp_%s.txt", obj_name)); if (((data_struct*)data)->check_file_exists("rom/skin_param/", buf.c_str())) { prj::shared_ptr kv = prj::shared_ptr(new key_val); ((data_struct*)data)->load_file(kv.get(), "rom/skin_param/", buf.c_str(), key_val::load_file); skin_param_storage.insert({ i, kv }); } } } void skin_param_storage_reset() { skin_param_storage.clear(); } osage_setting::osage_setting() { } osage_setting::~osage_setting() { } void osage_setting::clear() { cat.clear(); obj.clear(); } const osage_setting_osg_cat* osage_setting::get_cat_value( object_info* obj_info, const char* root_node) { auto elem_obj = osage_setting_data->obj.find(*obj_info); if (elem_obj == osage_setting_data->obj.end()) return 0; auto elem_cat = osage_setting_data->cat.find({ elem_obj->second, root_node }); if (elem_cat == osage_setting_data->cat.end()) return 0; return &elem_cat->second; } void osage_setting::load() { clear(); data_struct* aft_data = &data_list[DATA_AFT]; for (const std::string& i : mdata_manager_get()->GetPrefixes()) { std::string file(i); file.append("osage_setting.txt"); aft_data->load_file(this, "rom/skin_param/", file.c_str(), osage_setting_data_load_file); } } void osage_setting::parse(key_val* kv) { int32_t count; if (kv->read("cat", "length", count)) { for (int32_t i = 0; i < count; i++) { if (!kv->open_scope_fmt(i)) continue; std::string name; kv->read("name", name); int32_t count; if (kv->read("osg", "length", count)) { for (int32_t j = 0; j < count; j++) { if (!kv->open_scope_fmt(j)) continue; int32_t exf = 0; kv->read("exf", exf); std::string parts; kv->read("parts", parts); std::string root; kv->read("root", root); std::pair key = { name, root }; auto elem = cat.find(key); if (elem == cat.end()) elem = cat.insert({ key, {} }).first; elem->second.exf = exf; elem->second.parts = parse_parts_string(parts); kv->close_scope(); } kv->close_scope(); } kv->close_scope(); } kv->close_scope(); } data_struct* aft_data = &data_list[DATA_AFT]; object_database* aft_obj_db = &aft_data->data_ft.obj_db; if (kv->read("obj", "length", count)) { for (int32_t i = 0; i < count; i++) { if (!kv->open_scope_fmt(i)) continue; std::string cat; kv->read("cat", cat); std::string name; kv->read("name", name); obj.insert_or_assign(aft_obj_db->get_object_info(name.c_str()), cat); kv->close_scope(); } kv->close_scope(); } } rob_osage_parts osage_setting::parse_parts_string(std::string& s) { static const char* parts_string_array[] = { "LEFT", "RIGHT", "CENTER", "LONG_C", "SHORT_L", "SHORT_R", "APPEND_L", "APPEND_R", "MUFFLER", "WHITE_ONE_L", "PONY", "ANGEL_L", "ANGEL_R", }; for (const char*& i : parts_string_array) if (!s.compare(i)) return (rob_osage_parts)(&i - parts_string_array); return ROB_OSAGE_PARTS_NONE; } skin_param_file::skin_param_file() : file_handler(), id(), type(), data(), rob_chr() { } skin_param_file::~skin_param_file() { if (file_handler) delete file_handler; } static uint8_t skin_param_manager_index = 0; SkinParamManager::SkinParamManager() { index = skin_param_manager_index++; state = 1; } SkinParamManager::~SkinParamManager() { state = 1; Reset(); } bool SkinParamManager::init() { state = 0; AddFiles(); return true; } bool SkinParamManager::ctrl() { switch (state) { case 0: if (CtrlFiles()) return false; state = 1; case 1: return true; default: return false; } } bool SkinParamManager::dest() { return true; } void SkinParamManager::disp() { } bool SkinParamManager::add_task(std::vector& vec) { if (app::TaskWork::check_task_ready(this) || !app::TaskWork::add_task(this, "SKIN_PARAM_MANAGER")) return false; osage_init.assign(vec.begin(), vec.end()); return true; } void SkinParamManager::AddFiles() { if (!osage_init.size()) return; data_struct* aft_data = &data_list[DATA_AFT]; motion_database* aft_mot_db = &aft_data->data_ft.mot_db; files.clear(); for (osage_init_data& i : osage_init) { rob_chara_item_equip* rob_itm_equip = i.rob_chr->item_equip; for (int32_t j = ITEM_KAMI; j < ITEM_MAX; j++) { object_info obj_info = rob_itm_equip->get_object_info((item_id)j); if (obj_info.is_null()) continue; const char* obj_name = object_storage_get_obj_name(obj_info); if (!obj_name) continue; obj_skin* skin = object_storage_get_obj_skin(obj_info); if (!skin || !skin->ex_data) return; obj_skin_ex_data* ex_data = skin->ex_data; int32_t osage_count = 0; int32_t cloth_count = 0; obj_skin_block* b = ex_data->block_array; for (int32_t k = ex_data->num_block; k; k--, b++) if (b->type == OBJ_SKIN_BLOCK_OSAGE) osage_count++; else if (b->type == OBJ_SKIN_BLOCK_CLOTH) cloth_count++; if (!ex_data || !(osage_count + cloth_count)) continue; std::string dir; std::string farc_file; std::string file; dir.assign("rom/skin_param/"); farc_file.assign(""); file.assign("ext_skp_"); file.append(obj_name); file.append(".txt"); skin_param_file* skp_file = new skin_param_file; if (!skp_file) continue; skp_file->id = (item_id)j; skp_file->rob_chr = i.rob_chr; skp_file->type = -1; if (i.dir.size()) { skp_file->type = GetExtSkpFile(i, i.dir, file, aft_data, aft_mot_db); if (skp_file->type != -1) dir.assign(i.dir); } bool read_farc = false; if (skp_file->type == -1) { skp_file->type = sp_skp_db_data->get_ext_skp_file(i, obj_info, file, farc_file, aft_data, aft_mot_db); if (skp_file->type == -1) { delete skp_file; continue; } switch (skp_file->type) { case 0: case 1: read_farc = true; break; } } std::vector* skp_file_data = 0; switch (skp_file->type) { case 0: { skin_param_key key(obj_info, i.motion_id, i.frame); auto elem = object_motion_frame.find(key); if (elem != object_motion_frame.end()) { delete skp_file; continue; } skp_file_data = new std::vector; object_motion_frame.insert({ key, skp_file_data }); } break; case 1: { skin_param_key key(obj_info, i.motion_id); auto elem = object_motion.find(key); if (elem != object_motion.end()) { delete skp_file; continue; } skp_file_data = new std::vector; object_motion.insert({ key, skp_file_data }); } break; case 2: { skin_param_key key(obj_info); auto elem = object.find(key); if (elem != object.end()) { delete skp_file; continue; } skp_file_data = new std::vector; object.insert({ key, skp_file_data }); } break; } if (!skp_file_data) { delete skp_file; continue; } skp_file_data->resize((size_t)cloth_count + osage_count); skp_file->data = skp_file_data; data_struct* aft_data = &data_list[DATA_AFT]; p_file_handler* pfhndl = new p_file_handler; if (read_farc) pfhndl->read_file(aft_data, dir.c_str(), farc_file.c_str(), file.c_str(), false); else pfhndl->read_file(aft_data, dir.c_str(), file.c_str()); skp_file->file_handler = pfhndl; files.push_back(skp_file); } } } bool SkinParamManager::CtrlFiles() { data_struct* aft_data = &data_list[DATA_AFT]; bone_database* aft_bone_data = &aft_data->data_ft.bone_data; for (auto i = files.begin(); i != files.end(); ) { skin_param_file* skp_file = *i; if (skp_file->file_handler->check_not_ready()) break; else if (skp_file->id <= ITEM_NONE || skp_file->id >= ITEM_MAX) { i = files.erase(i); continue; } rob_chara_item_equip* rob_itm_equip = skp_file->rob_chr->item_equip; key_val kv; kv.parse(skp_file->file_handler->get_data(), skp_file->file_handler->get_size()); object_info obj_info = rob_itm_equip->get_object_info(skp_file->id); if (!obj_info.not_null()) { i = files.erase(i); continue; } rob_chara_item_equip_object* itm_eq_obj = &rob_itm_equip->item_equip_object[skp_file->id]; skin_param_file_data* skp_file_data = skp_file->data->data(); for (ExNodeBlock* j : itm_eq_obj->node_blocks) { if (j->type != EX_OSAGE && j->type != EX_CLOTH) continue; const char* name = j->name; skin_param_osage_root root; skin_param_osage_root_parse(&kv, name, root, aft_bone_data); skp_file_data->skin_param.set_skin_param_osage_root(root); std::vector vec; skin_param_osage_node_parse(&kv, name, &vec, root); skp_file_data->nodes_data.resize(vec.size()); rob_itm_equip->skp_load(skp_file->id, root, vec, skp_file_data, aft_bone_data); skp_file_data++; } delete skp_file; i = files.erase(i); } return !!files.size(); } int32_t SkinParamManager::GetExtSkpFile(const osage_init_data& osage_init, const std::string& dir, std::string& file, void* data, const motion_database* mot_db) { if (!dir.size()) return -1; std::string buf1; std::string buf2; if (osage_init.motion_id != -1) { const char* motion_name = mot_db->get_motion_name(osage_init.motion_id); if (!motion_name) return -1; std::string buf; if (osage_init.frame > -1) { buf = sprintf_s_string("%s_%d_", motion_name, osage_init.frame); buf.append(file); } else { buf = sprintf_s_string("%s_", motion_name); buf.append(file); } buf = string_to_lower(buf); if (((data_struct*)data)->check_file_exists(dir.c_str(), buf.c_str())) { file.assign(buf); return 0; } } if (osage_init.pv_id > -1) { std::string buf = sprintf_s_string("pv%03d_", osage_init.pv_id); buf.append(file); buf = string_to_lower(buf); if (((data_struct*)data)->check_file_exists(dir.c_str(), buf.c_str())) { file.assign(buf.c_str()); return 1; } } if (((data_struct*)data)->check_file_exists(dir.c_str(), file.c_str())) return 2; return -1; } std::vector* SkinParamManager::GetSkinParamFileData( object_info obj_info, uint32_t motion_id, int32_t frame) { if (object_motion_frame.size()) { auto elem_frame = object_motion_frame.find({ obj_info, motion_id, frame }); if (elem_frame != object_motion_frame.end()) return elem_frame->second; auto elem = object_motion_frame.find({ obj_info, motion_id }); if (elem != object_motion_frame.end()) return elem->second; } if (object_motion.size()) { auto elem = object_motion.find({ obj_info, motion_id }); if (elem != object_motion.end()) return elem->second; } if (object.size()) { auto elem = object.find({ obj_info }); if (elem != object.end()) return elem->second; } return 0; } void SkinParamManager::Reset() { osage_init.clear(); for (auto i : object_motion_frame) { if (!i.second) continue; delete i.second; i.second = 0; } object_motion_frame.clear(); for (auto i : object_motion) { if (!i.second) continue; delete i.second; i.second = 0; } object_motion.clear(); for (auto i : object) { if (!i.second) continue; delete i.second; i.second = 0; } object.clear(); for (skin_param_file*& i : files) { if (i->file_handler) { delete i->file_handler; i->file_handler = 0; } delete i; } files.clear(); del(); } sp_skp_db::sp_skp_db() : farc_list_count() { } sp_skp_db::~sp_skp_db() { } void sp_skp_db::clear() { pv.clear(); motion.clear(); farc_list.clear(); farc_list.shrink_to_fit(); farc_list_count = 0; } void sp_skp_db::load() { data_struct* aft_data = &data_list[DATA_AFT]; for (const std::string& i : mdata_manager_get()->GetPrefixes()) { std::string file(i); file.append("sp_skp_db.txt"); aft_data->load_file(this, "rom/skin_param/", file.c_str(), sp_skp_db_load_file); } } void sp_skp_db::parse(key_val* kv) { data_struct* aft_data = &data_list[DATA_AFT]; object_database* aft_obj_db = &aft_data->data_ft.obj_db; size_t farc_list_count = this->farc_list_count; int32_t count; if (kv->read("motion", "length", count)) { for (int32_t i = 0; i < count; i++) { if (!kv->open_scope_fmt(i)) continue; std::string name; if (!kv->read("name", name)) continue; std::shared_ptr> skp = std::make_shared< std::map>(); motion.insert({ name, skp }); int32_t count; if (kv->read("skp", "length", count)) { for (int32_t j = 0; j < count; j++) { if (!kv->open_scope_fmt(j)) continue; const char* obj; int32_t farc; if (!kv->read("obj", obj) || !kv->read("farc", farc)) continue; skp->insert({ aft_obj_db->get_object_info(obj), (uint32_t)(farc_list_count + farc) }); kv->close_scope(); } kv->close_scope(); } kv->close_scope(); } kv->close_scope(); } if (kv->read("pv", "length", count)) { for (int32_t i = 0; i < count; i++) { if (!kv->open_scope_fmt(i)) continue; std::string name; if (!kv->read("name", name) || name.size() != 5) continue; std::shared_ptr> skp = std::make_shared< std::map>(); int32_t pv_id = (name[2] - '0') * 100; pv_id += (name[3] - '0') * 10; pv_id += name[4] - '0'; pv.insert({ pv_id, skp }); int32_t count; if (kv->read("skp", "length", count)) { for (int32_t j = 0; j < count; j++) { if (!kv->open_scope_fmt(j)) continue; const char* obj; int32_t farc; if (!kv->read("obj", obj) || !kv->read("farc", farc)) continue; skp->insert({ aft_obj_db->get_object_info(obj), (uint32_t)(farc_list_count + farc) }); kv->close_scope(); } kv->close_scope(); } kv->close_scope(); } kv->close_scope(); } if (kv->read("farc_list", "length", count)) { farc_list.resize(farc_list_count + count); std::string* vfl = farc_list.data(); for (int32_t i = 0; i < count; i++) { if (!kv->open_scope_fmt(i)) continue; kv->read(vfl[farc_list_count + i]); kv->close_scope(); } kv->close_scope(); this->farc_list_count = farc_list_count + count; } } int32_t sp_skp_db::get_ext_skp_file(const osage_init_data& osage_init, const object_info obj_info, std::string& file, std::string& farc, void* data, const motion_database* mot_db) { if (obj_info.is_null()) return 2; int32_t type = 2; farc.clear(); if (osage_init.pv_id > -1) { auto elem0 = pv.find(osage_init.pv_id); if (elem0 != pv.end()) { auto elem1 = elem0->second->find(obj_info); if (elem1 != elem0->second->end()) { type = 1; farc.assign(farc_list[elem1->second]); } } } if (osage_init.motion_id != -1) { const char* motion_name = mot_db->get_motion_name(osage_init.motion_id); if (motion_name) { std::string buf(motion_name); if (osage_init.frame > -1) buf = sprintf_s_string("%s_%d", motion_name, osage_init.frame); auto elem0 = motion.find(buf); if (elem0 != motion.end()) { auto elem1 = elem0->second->find(obj_info); if (elem1 != elem0->second->end()) { type = 0; farc.assign(farc_list[elem1->second]); } } } } const char* obj_name = object_storage_get_obj_name(obj_info); std::string skp_file = sprintf_s_string("ext_skp_%s.txt", obj_name); switch (type) { case 0: { std::string motion_name(mot_db->get_motion_name(osage_init.motion_id)); if (osage_init.frame > -1) motion_name = sprintf_s_string("%s_%d", motion_name.c_str(), osage_init.frame); std::string buf = sprintf_s_string("%s_", motion_name.c_str()); buf.append(skp_file); skp_file.assign(buf); } break; case 1: { std::string buf = sprintf_s_string("pv%03d_", osage_init.pv_id); buf.append(skp_file); skp_file.assign(buf); } break; } skp_file = string_to_lower(skp_file); if (type == 2 && !((data_struct*)data)->check_file_exists("rom/skin_param/", skp_file.c_str())) { file.clear(); type = -1; } else file.assign(skp_file); return type; } static bool osage_setting_data_load_file(void* data, const char* dir, const char* file, uint32_t hash) { key_val kv; if (key_val::load_file(&kv, dir, file, hash)) { ((osage_setting*)data)->parse(&kv); return true; } return false; } static SkinParamManager* skin_param_manager_get(int32_t chara_id) { if (chara_id < 0 || chara_id > 6) chara_id = 0; return &skin_param_manager[chara_id]; } static bool sp_skp_db_load_file(void* data, const char* dir, const char* file, uint32_t hash) { key_val kv; if (key_val::load_file(&kv, dir, file, hash)) { ((sp_skp_db*)data)->parse(&kv); return true; } return false; }