From 0e2eea0fbfdadc2edc39f4c452f5bf1f86812b34 Mon Sep 17 00:00:00 2001 From: Petr Ohlidal Date: Mon, 11 Dec 2023 23:37:11 +0100 Subject: [PATCH] Tuning: improved UI overrides, separated from tuneups/unwants. All the UI overrides are now separate from any addonpart changes (tweaks or 'unwanted_*'). The 'protected' checkbox on the right just blocks addonpart changes, but isn't necessary for the UI overrides anymore. When you make an UI override, the respective widget will be outlined orange and a 'reset' button will be drawn. Internally, the UI overrides are called "force_*something*". CAUTION: Top menubar Tuning menu is only corrected for flexbodies, not props yet! Codechanges: * TuneupFileFormat.h: replaced shared 'remove_props/flexbodies' by dual 'unwanted_*' and 'force_remove_*'. Added helper funcs. * TuneupFileFormat.cpp: Updated parsing + exporting code. * CacheSystem.h: `enum ModifyProjectRequestType`: REMOVE fields renamed to FORCEREMOVE. `struct ModifyProjectRequest`: removed hacky field `mpr_subject_set_protected`. Added func `LoadSupplementaryDocuments()` * CacheSystem.cpp: updated and cleaned up `ModifyProject()` as the `mpr_subject_set_protected` hack isn't needed anymore. * AddonPartFileFormat.cpp: updated to set/reset `unwanted_` fields - cleaner. * GUI_TopMenubar.cpp - updated UI to signify overrided elements. --- source/main/gui/panels/GUI_TopMenubar.cpp | 82 +++++++++++++++---- source/main/resources/CacheSystem.cpp | 79 +++++++++--------- source/main/resources/CacheSystem.h | 17 ++-- .../AddonPartFileFormat.cpp | 25 ++---- .../tuneup_fileformat/TuneupFileFormat.cpp | 50 +++++++---- .../tuneup_fileformat/TuneupFileFormat.h | 29 ++++++- 6 files changed, 175 insertions(+), 107 deletions(-) diff --git a/source/main/gui/panels/GUI_TopMenubar.cpp b/source/main/gui/panels/GUI_TopMenubar.cpp index ec64e5ab0e..ce07cb284c 100644 --- a/source/main/gui/panels/GUI_TopMenubar.cpp +++ b/source/main/gui/panels/GUI_TopMenubar.cpp @@ -1648,7 +1648,7 @@ void TopMenubar::Draw(float dt) // Draw props size_t total_props = tuning_actor->GetGfxActor()->getProps().size(); - std::string props_title = fmt::format(_LC("TopMenubar", "Props ({})"), total_props); + std::string props_title = fmt::format(_LC("Tuning", "Props ({})"), total_props); if (ImGui::CollapsingHeader(props_title.c_str()) && tuneup_entry) { // Draw all props (those removed by addonparts are also present as placeholders) @@ -1660,14 +1660,13 @@ void TopMenubar::Draw(float dt) this->DrawTuningBoxedSubjectIdInline(p.pp_id); // Draw the checkbox for removing/remounting. - bool propEnabled = tuneup_entry->tuneup_def->remove_props.find(p.pp_id) == tuneup_entry->tuneup_def->remove_props.end(); + bool propEnabled = !tuneup_entry->tuneup_def->isPropUnwanted(p.pp_id) && !tuneup_entry->tuneup_def->isPropForceRemoved(p.pp_id); if (ImGui::Checkbox(p.pp_media[0].c_str(), &propEnabled)) { ModifyProjectRequest* req = new ModifyProjectRequest(); - req->mpr_type = ModifyProjectRequestType::TUNEUP_REMOVE_PROP_SET; + req->mpr_type = ModifyProjectRequestType::TUNEUP_FORCEREMOVE_PROP_SET; req->mpr_subject_id = p.pp_id; req->mpr_target_actor = tuning_actor; - req->mpr_subject_set_protected = true; // stop evaluating addonparts for the prop (that would undo the user selection). App::GetGameContext()->PushMessage(Message(MSG_EDI_MODIFY_PROJECT_REQUESTED, req)); } @@ -1709,7 +1708,7 @@ void TopMenubar::Draw(float dt) // Ditto for flexbodies size_t total_flexbodies = tuning_actor->GetGfxActor()->GetFlexbodies().size(); - std::string flexbodies_title = fmt::format(_LC("TopMenubar", "Flexbodies ({})"), total_flexbodies); + std::string flexbodies_title = fmt::format(_LC("Tuning", "Flexbodies ({})"), total_flexbodies); if (ImGui::CollapsingHeader(flexbodies_title.c_str()) && tuneup_entry) { // Draw all flexbodies (those removed by addonparts are also present as placeholders) @@ -1720,17 +1719,40 @@ void TopMenubar::Draw(float dt) this->DrawTuningBoxedSubjectIdInline(flexbody->getID()); - // Draw the checkbox for removing/remounting. - bool flexbodyEnabled = tuneup_entry->tuneup_def->remove_flexbodies.find(flexbody->getID()) == tuneup_entry->tuneup_def->remove_flexbodies.end(); - if (ImGui::Checkbox(flexbody->getOrigMeshName().c_str(), &flexbodyEnabled)) + // Draw the checkbox for force-removing. + bool flexbodyEnabled = !tuneup_entry->tuneup_def->isFlexbodyUnwanted(flexbody->getID()) && !tuneup_entry->tuneup_def->isFlexbodyForceRemoved(flexbody->getID()); + if (tuneup_entry->tuneup_def->isFlexbodyForceRemoved(flexbody->getID())) { + ImGui::PushStyleColor(ImGuiCol_Border, ORANGE_TEXT); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f); + } + bool chkPressed = ImGui::Checkbox(flexbody->getOrigMeshName().c_str(), &flexbodyEnabled); + bool resetPressed = false; + if (tuneup_entry->tuneup_def->isFlexbodyForceRemoved(flexbody->getID())) + { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text, GRAY_HINT_TEXT); + resetPressed = ImGui::SmallButton(_LC("Tuning", "Reset")); + ImGui::PopStyleColor(); //ImGuiCol_Text, GRAY_HINT_TEXT + ImGui::PopStyleVar(); //ImGuiStyleVar_FrameBorderSize, 1.f + ImGui::PopStyleColor(); //ImGuiCol_Border, ORANGE_TEXT + } - + // perform project modification if needed + if (chkPressed && !flexbodyEnabled) + { + ModifyProjectRequest* req = new ModifyProjectRequest(); + req->mpr_type = ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_SET; + req->mpr_subject_id = flexbody->getID(); + req->mpr_target_actor = tuning_actor; + App::GetGameContext()->PushMessage(Message(MSG_EDI_MODIFY_PROJECT_REQUESTED, req)); + } + else if ((chkPressed && flexbodyEnabled) || resetPressed) + { ModifyProjectRequest* req = new ModifyProjectRequest(); - req->mpr_type = ModifyProjectRequestType::TUNEUP_REMOVE_FLEXBODY_SET; + req->mpr_type = ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_RESET; req->mpr_subject_id = flexbody->getID(); req->mpr_target_actor = tuning_actor; - req->mpr_subject_set_protected = true; // stop evaluating addonparts for the flexbody (that would undo the user selection). App::GetGameContext()->PushMessage(Message(MSG_EDI_MODIFY_PROJECT_REQUESTED, req)); } @@ -1757,6 +1779,11 @@ void TopMenubar::Draw(float dt) this->DrawTuningBoxedSubjectIdInline(i); // Draw R/L radio buttons + if (tuneup_entry->tuneup_def->isWheelSideForced(i)) + { + ImGui::PushStyleColor(ImGuiCol_Border, ORANGE_TEXT); + ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f); + } const RoR::WheelSide active_side = TuneupUtil::getTweakedWheelSide(tuneup_entry, i, tuning_actor->GetGfxActor()->getWheelSide(i)); RoR::WheelSide selected_side = active_side; if (ImGui::RadioButton("##L", active_side == WheelSide::LEFT)) @@ -1767,7 +1794,25 @@ void TopMenubar::Draw(float dt) if (ImGui::RadioButton("##R", active_side == WheelSide::RIGHT)) selected_side = WheelSide::RIGHT; - // Apply selection + // Draw rim mesh name + ImGui::SameLine(); + ImGui::Text("%s", tuning_actor->GetGfxActor()->getWheelRimMeshName(i).c_str()); + + // Draw reset button + + bool resetPressed = false; + if (tuneup_entry->tuneup_def->isWheelSideForced(i)) + { + ImGui::SameLine(); + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text, GRAY_HINT_TEXT); + resetPressed = ImGui::SmallButton(_LC("Tuning", "Reset")); + ImGui::PopStyleColor(); //ImGuiCol_Text, GRAY_HINT_TEXT + ImGui::PopStyleVar(); //ImGuiStyleVar_FrameBorderSize, 1.f + ImGui::PopStyleColor(); //ImGuiCol_Border, ORANGE_TEXT + } + + // modify project if needed if (selected_side != active_side) { ModifyProjectRequest* req = new ModifyProjectRequest(); @@ -1775,13 +1820,16 @@ void TopMenubar::Draw(float dt) req->mpr_subject_id = i; req->mpr_value_int = (int)selected_side; req->mpr_target_actor = tuning_actor; - req->mpr_subject_set_protected = true; // stop evaluating addonparts for the wheel (that would undo the user selection). App::GetGameContext()->PushMessage(Message(MSG_EDI_MODIFY_PROJECT_REQUESTED, req)); } - - // Draw rim mesh name - ImGui::SameLine(); - ImGui::Text("%s", tuning_actor->GetGfxActor()->getWheelRimMeshName(i).c_str()); + else if (resetPressed) + { + ModifyProjectRequest* req = new ModifyProjectRequest(); + req->mpr_type = ModifyProjectRequestType::TUNEUP_FORCED_WHEEL_SIDE_RESET; + req->mpr_subject_id = i; + req->mpr_target_actor = tuning_actor; + App::GetGameContext()->PushMessage(Message(MSG_EDI_MODIFY_PROJECT_REQUESTED, req)); + } this->DrawTuningProtectedChkRightAligned( i, diff --git a/source/main/resources/CacheSystem.cpp b/source/main/resources/CacheSystem.cpp index e5e82e456b..539bf74c02 100644 --- a/source/main/resources/CacheSystem.cpp +++ b/source/main/resources/CacheSystem.cpp @@ -1234,6 +1234,27 @@ std::string CacheSystem::ComposeResourceGroupName(const CacheEntryPtr& entry) return fmt::format("{{bundle {}}}", name); } +void CacheSystem::LoadSupplementaryDocuments(CacheEntryPtr& entry) +{ + // Because we use one resource group per bundle and multiple entries can share the same bundle, + // we need to load the supplementary documents even if the bundle is already loaded. + // ------------------------------------------------------------------------------------------- + + if (!entry) + return; + + ROR_ASSERT(entry->resource_group != ""); + + if (entry->fext == "skin") + { + this->LoadAssociatedSkinDef(entry); + } + else if (entry->fext == "tuneup") + { + this->LoadAssociatedTuneupDef(entry); + } +} + void CacheSystem::LoadResource(CacheEntryPtr& entry) { if (!entry) @@ -1242,6 +1263,7 @@ void CacheSystem::LoadResource(CacheEntryPtr& entry) // Check if already loaded for this entry-> if (entry->resource_group != "") { + this->LoadSupplementaryDocuments(entry); return; } @@ -1294,15 +1316,7 @@ void CacheSystem::LoadResource(CacheEntryPtr& entry) ResourceGroupManager::getSingleton().initialiseResourceGroup(group); entry->resource_group = group; - // Attach supplementary documents - if (entry->fext == "skin") - { - this->LoadAssociatedSkinDef(entry); - } - else if (entry->fext == "tuneup") - { - this->LoadAssociatedTuneupDef(entry); - } + this->LoadSupplementaryDocuments(entry); // Inform other entries sharing this bundle (i.e. '.skin' entries in vehicle bundles) for (CacheEntryPtr& i_entry: m_entries) @@ -1392,7 +1406,6 @@ void CacheSystem::LoadAssociatedSkinDef(CacheEntryPtr& cache_entry) try { - App::GetCacheSystem()->LoadResource(cache_entry); // Load if not already Ogre::DataStreamPtr ds = Ogre::ResourceGroupManager::getSingleton() .openResource(cache_entry->fname, cache_entry->resource_group); @@ -1442,7 +1455,6 @@ void CacheSystem::LoadAssociatedTuneupDef(CacheEntryPtr& cache_entry) try { - App::GetCacheSystem()->LoadResource(cache_entry); // Load if not already Ogre::DataStreamPtr ds = Ogre::ResourceGroupManager::getSingleton() .openResource(cache_entry->fname, cache_entry->resource_group); @@ -1671,40 +1683,28 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request) tuneup_entry->tuneup_def->use_addonparts.erase(request->mpr_subject); break; - case ModifyProjectRequestType::TUNEUP_REMOVE_PROP_SET: - tuneup_entry->tuneup_def->remove_props.insert(request->mpr_subject_id); - if (request->mpr_subject_set_protected) - tuneup_entry->tuneup_def->protected_props.insert(request->mpr_subject_id); + case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_PROP_SET: + tuneup_entry->tuneup_def->force_remove_props.insert(request->mpr_subject_id); break; - case ModifyProjectRequestType::TUNEUP_REMOVE_PROP_RESET: - tuneup_entry->tuneup_def->remove_props.erase(request->mpr_subject_id); - if (request->mpr_subject_set_protected) - tuneup_entry->tuneup_def->protected_props.insert(request->mpr_subject_id); + case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_PROP_RESET: + tuneup_entry->tuneup_def->force_remove_props.erase(request->mpr_subject_id); break; - case ModifyProjectRequestType::TUNEUP_REMOVE_FLEXBODY_SET: - tuneup_entry->tuneup_def->remove_flexbodies.insert(request->mpr_subject_id); - if (request->mpr_subject_set_protected) - tuneup_entry->tuneup_def->protected_flexbodies.insert(request->mpr_subject_id); + case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_SET: + tuneup_entry->tuneup_def->force_remove_flexbodies.insert(request->mpr_subject_id); break; - case ModifyProjectRequestType::TUNEUP_REMOVE_FLEXBODY_RESET: - tuneup_entry->tuneup_def->remove_flexbodies.erase(request->mpr_subject_id); - if (request->mpr_subject_set_protected) - tuneup_entry->tuneup_def->protected_flexbodies.insert(request->mpr_subject_id); + case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_RESET: + tuneup_entry->tuneup_def->force_remove_flexbodies.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_FORCED_WHEEL_SIDE_SET: - tuneup_entry->tuneup_def->wheel_forced_sides[request->mpr_subject_id] = (WheelSide)request->mpr_value_int; - if (request->mpr_subject_set_protected) - tuneup_entry->tuneup_def->protected_wheels.insert(request->mpr_subject_id); + tuneup_entry->tuneup_def->force_wheel_sides[request->mpr_subject_id] = (WheelSide)request->mpr_value_int; break; case ModifyProjectRequestType::TUNEUP_FORCED_WHEEL_SIDE_RESET: - tuneup_entry->tuneup_def->wheel_forced_sides.erase(request->mpr_subject_id); - if (request->mpr_subject_set_protected) - tuneup_entry->tuneup_def->protected_wheels.insert(request->mpr_subject_id); + tuneup_entry->tuneup_def->force_wheel_sides.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_PROTECTED_PROP_SET: @@ -1729,7 +1729,6 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request) case ModifyProjectRequestType::TUNEUP_PROTECTED_WHEEL_RESET: tuneup_entry->tuneup_def->protected_wheels.erase(request->mpr_subject_id); - tuneup_entry->tuneup_def->wheel_forced_sides.erase(request->mpr_subject_id); // Unlike props and flexbodies, forced sides are not updated from addonparts - we must clear manually. break; case ModifyProjectRequestType::PROJECT_LOAD_TUNEUP: @@ -1746,10 +1745,10 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request) this->LoadResource(save_entry); ROR_ASSERT(save_entry->tuneup_def); - tuneup_entry->tuneup_def->remove_flexbodies.clear(); - tuneup_entry->tuneup_def->remove_flexbodies = save_entry->tuneup_def->remove_flexbodies; - tuneup_entry->tuneup_def->remove_props.clear(); - tuneup_entry->tuneup_def->remove_props = save_entry->tuneup_def->remove_props; + tuneup_entry->tuneup_def->unwanted_flexbodies.clear(); + tuneup_entry->tuneup_def->unwanted_flexbodies = save_entry->tuneup_def->unwanted_flexbodies; + tuneup_entry->tuneup_def->unwanted_props.clear(); + tuneup_entry->tuneup_def->unwanted_props = save_entry->tuneup_def->unwanted_props; tuneup_entry->tuneup_def->use_addonparts.clear(); tuneup_entry->tuneup_def->use_addonparts = save_entry->tuneup_def->use_addonparts; tuneup_entry->tuneup_def->wheel_tweaks.clear(); @@ -1760,8 +1759,8 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request) } case ModifyProjectRequestType::PROJECT_RESET_TUNEUP: - tuneup_entry->tuneup_def->remove_flexbodies.clear(); - tuneup_entry->tuneup_def->remove_props.clear(); + tuneup_entry->tuneup_def->unwanted_flexbodies.clear(); + tuneup_entry->tuneup_def->unwanted_props.clear(); tuneup_entry->tuneup_def->use_addonparts.clear(); tuneup_entry->tuneup_def->wheel_tweaks.clear(); tuneup_entry->tuneup_def->node_tweaks.clear(); diff --git a/source/main/resources/CacheSystem.h b/source/main/resources/CacheSystem.h index 0789d0093c..8bacb4cdaa 100644 --- a/source/main/resources/CacheSystem.h +++ b/source/main/resources/CacheSystem.h @@ -73,6 +73,7 @@ class CacheEntry: public RefCountingObject std::time_t addtimestamp; //!< timestamp when this file was added to the cache Ogre::String uniqueid; //!< file's unique id Ogre::String guid; //!< global unique id. Type "addonpart" leaves this empty. + std::set addonpart_guids; //!< GUIDs of all vehicles this addonpart is used in. Empty for non-addonpart entries. int version; //!< file's version std::string resource_bundle_type; //!< Archive type recognized by OGRE resource system: 'FileSystem' or 'Zip' @@ -86,10 +87,10 @@ class CacheEntry: public RefCountingObject Ogre::String resource_group; //!< Resource group of the loaded bundle. Empty if not loaded yet. - RigDef::DocumentPtr actor_def; //!< Cached actor definition (aka truckfile) after first spawn + RigDef::DocumentPtr actor_def; //!< Cached actor definition (aka truckfile) after first spawn. std::shared_ptr skin_def; //!< Cached skin info, added on first use or during cache rebuild RoR::TuneupDefPtr tuneup_def; //!< Cached tuning info, added on first use or during cache rebuild - std::set addonpart_guids; + // TBD: Make Terrn2Def a RefcountingObjectPtr<> and cache it here too. // following all TRUCK detail information: Ogre::String description; @@ -225,10 +226,10 @@ enum class ModifyProjectRequestType NONE, TUNEUP_USE_ADDONPART_SET, //!< 'subject' is addonpart filename. TUNEUP_USE_ADDONPART_RESET, //!< 'subject' is addonpart filename. - TUNEUP_REMOVE_PROP_SET, //!< 'subject_id' is prop ID. - TUNEUP_REMOVE_PROP_RESET, //!< 'subject_id' is prop ID. - TUNEUP_REMOVE_FLEXBODY_SET, //!< 'subject_id' is flexbody ID. - TUNEUP_REMOVE_FLEXBODY_RESET, //!< 'subject_id' is flexbody ID. + TUNEUP_FORCEREMOVE_PROP_SET, //!< 'subject_id' is prop ID. + TUNEUP_FORCEREMOVE_PROP_RESET, //!< 'subject_id' is prop ID. + TUNEUP_FORCEREMOVE_FLEXBODY_SET, //!< 'subject_id' is flexbody ID. + TUNEUP_FORCEREMOVE_FLEXBODY_RESET, //!< 'subject_id' is flexbody ID. TUNEUP_FORCED_WHEEL_SIDE_SET, //!< 'subject_id' is wheel ID, 'value_int' is RoR::WheelSide TUNEUP_FORCED_WHEEL_SIDE_RESET, //!< 'subject_id' is wheel ID. TUNEUP_PROTECTED_PROP_SET, //!< 'subject_id' is prop ID. @@ -250,9 +251,6 @@ struct ModifyProjectRequest std::string mpr_subject; // addonpart int mpr_subject_id = -1; // wheel, prop, flexbody, node int mpr_value_int; // forced wheel side - - // Protected state prevents addonparts from evaluating, which would undo user's selections. - bool mpr_subject_set_protected = false; }; /// A content database @@ -296,6 +294,7 @@ class CacheSystem bool CheckResourceLoaded(Ogre::String &in_out_filename, Ogre::String &out_group); //!< Finds given resource, outputs group name. Also loads the associated resource bundle if not already done. void ReLoadResource(CacheEntryPtr& t); //!< Forces reloading the associated bundle. void UnLoadResource(CacheEntryPtr& t); //!< Unloads associated bundle, destroying all spawned actors. + void LoadSupplementaryDocuments(CacheEntryPtr& t); //!< Loads the associated .truck*, .skin and .tuneup files. /// @} /// @name Loading diff --git a/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp b/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp index 442747cd6e..89c6274d74 100644 --- a/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp +++ b/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp @@ -162,27 +162,14 @@ void AddonPartUtility::ResolveUnwantedAndTweakedElements(TuneupDefPtr& tuneup, C } } -// Internal helper for `ResetUnwantedAndTweakedElements()` -template void EraseUnprotected(std::set& all, std::set& safe) -{ - auto itor = all.begin(); - while (itor != all.end()) - { - if (safe.find(*itor) == safe.end()) - itor = all.erase(itor); - else - ++itor; - } -} - void AddonPartUtility::ResetUnwantedAndTweakedElements(TuneupDefPtr& tuneup) { ROR_ASSERT(tuneup); - // Unwanted (These can be either from addonpart or UI, we must respect protected elements); - EraseUnprotected(tuneup->remove_flexbodies, tuneup->protected_flexbodies); - EraseUnprotected(tuneup->remove_props, tuneup->protected_props); - + // Unwanted + tuneup->unwanted_flexbodies.clear(); + tuneup->unwanted_props.clear(); + // Tweaked tuneup->node_tweaks.clear(); tuneup->wheel_tweaks.clear(); @@ -298,7 +285,7 @@ void AddonPartUtility::ProcessUnwantedProp() { if (!m_tuneup->isPropProtected((PropID_t)m_context->getTokFloat(1))) { - m_tuneup->remove_props.insert((PropID_t)m_context->getTokFloat(1)); + m_tuneup->unwanted_props.insert((PropID_t)m_context->getTokFloat(1)); LOG(fmt::format("[RoR|Addonpart] INFO: file '{}', element '{}': marking prop '{}' as REMOVED", m_addonpart_entry->fname, m_context->getTokKeyword(), (int)m_context->getTokFloat(1))); } @@ -322,7 +309,7 @@ void AddonPartUtility::ProcessUnwantedFlexbody() { if (!m_tuneup->isFlexbodyProtected((FlexbodyID_t)m_context->getTokFloat(1))) { - m_tuneup->remove_flexbodies.insert((FlexbodyID_t)m_context->getTokFloat(1)); + m_tuneup->unwanted_flexbodies.insert((FlexbodyID_t)m_context->getTokFloat(1)); LOG(fmt::format("[RoR|Addonpart] INFO: file '{}', element '{}': marking flexbody '{}' as REMOVED", m_addonpart_entry->fname, m_context->getTokKeyword(), (int)m_context->getTokFloat(1))); } diff --git a/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp b/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp index 6cce39b90a..f101f9376b 100644 --- a/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp +++ b/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp @@ -49,10 +49,10 @@ TuneupDefPtr TuneupDef::clone() ret->category_id = this->category_id ; //CacheCategoryId // Modding attributes - ret->use_addonparts = this->use_addonparts ; //std::set - ret->remove_props = this->remove_props ; //std::set - ret->remove_flexbodies = this->remove_flexbodies ; //std::set - ret->protected_props = this->protected_props ; //std::set + ret->use_addonparts = this->use_addonparts ; //std::set + ret->unwanted_props = this->unwanted_props ; //std::set + ret->unwanted_flexbodies = this->unwanted_flexbodies ; //std::set + ret->protected_props = this->protected_props ; //std::set ret->protected_flexbodies = this->protected_flexbodies ; //std::set return ret; @@ -131,8 +131,8 @@ WheelSide RoR::TuneupUtil::getTweakedWheelSide(CacheEntryPtr& tuneup_entry, int // First query the UI overrides { - auto itor = tuneup_entry->tuneup_def->wheel_forced_sides.find(wheel_id); - auto endi = tuneup_entry->tuneup_def->wheel_forced_sides.end(); + auto itor = tuneup_entry->tuneup_def->force_wheel_sides.find(wheel_id); + auto endi = tuneup_entry->tuneup_def->force_wheel_sides.end(); if (itor != endi) return itor->second; } @@ -171,7 +171,7 @@ bool RoR::TuneupUtil::isPropRemoved(ActorPtr& actor, PropID_t prop_id) { return actor->getUsedTuneupEntry() && actor->getUsedTuneupEntry()->tuneup_def - && actor->getUsedTuneupEntry()->tuneup_def->remove_props.find(prop_id) != actor->getUsedTuneupEntry()->tuneup_def->remove_props.end(); + && actor->getUsedTuneupEntry()->tuneup_def->unwanted_props.find(prop_id) != actor->getUsedTuneupEntry()->tuneup_def->unwanted_props.end(); } Ogre::Vector3 RoR::TuneupUtil::getTweakedPropOffset(CacheEntryPtr& tuneup_entry, PropID_t prop_id, Ogre::Vector3 orig_val) @@ -252,7 +252,7 @@ bool RoR::TuneupUtil::isFlexbodyRemoved(ActorPtr& actor, FlexbodyID_t flexbody_i { return actor->getUsedTuneupEntry() && actor->getUsedTuneupEntry()->tuneup_def - && actor->getUsedTuneupEntry()->tuneup_def->remove_flexbodies.find(flexbody_id) != actor->getUsedTuneupEntry()->tuneup_def->remove_flexbodies.end(); + && actor->getUsedTuneupEntry()->tuneup_def->unwanted_flexbodies.find(flexbody_id) != actor->getUsedTuneupEntry()->tuneup_def->unwanted_flexbodies.end(); } Ogre::Vector3 RoR::TuneupUtil::getTweakedFlexbodyOffset(CacheEntryPtr& tuneup_entry, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val) @@ -406,13 +406,17 @@ void RoR::TuneupUtil::ParseTuneupAttribute(const std::string& line, TuneupDefPtr if (attrib == "guid" && params.size() >= 2) { tuneup_def->guid = params[1]; Ogre::StringUtil::trim(tuneup_def->guid); Ogre::StringUtil::toLowerCase(tuneup_def->guid); return; } if (attrib == "name" && params.size() >= 2) { tuneup_def->name = params[1]; Ogre::StringUtil::trim(tuneup_def->name); return; } - // Modding attributes + // Addonparts and extracted data if (attrib == "use_addonpart" && params.size() == 2) { tuneup_def->use_addonparts.insert(params[1]); return; } - if (attrib == "remove_prop" && params.size() == 2) { tuneup_def->remove_props.insert(PARSEINT(params[1])); return; } - if (attrib == "remove_flexbody" && params.size() == 2) { tuneup_def->remove_flexbodies.insert(PARSEINT(params[1])); return; } + if (attrib == "unwanted_prop" && params.size() == 2) { tuneup_def->unwanted_props.insert(PARSEINT(params[1])); return; } + if (attrib == "unwanted_flexbody" && params.size() == 2) { tuneup_def->unwanted_flexbodies.insert(PARSEINT(params[1])); return; } if (attrib == "protected_prop" && params.size() == 2) { tuneup_def->protected_props.insert(PARSEINT(params[1])); return; } if (attrib == "protected_flexbody" && params.size() == 2) { tuneup_def->protected_flexbodies.insert(PARSEINT(params[1])); return; } - if (attrib == "forced_wheel_side" && params.size() == 3) { tuneup_def->wheel_forced_sides[PARSEINT(params[1])] = (WheelSide)PARSEINT(params[2]); return; } + + // UI overrides + if (attrib == "forced_wheel_side" && params.size() == 3) { tuneup_def->force_wheel_sides[PARSEINT(params[1])] = (WheelSide)PARSEINT(params[2]); return; } + if (attrib == "force_remove_prop" && params.size() == 2) { tuneup_def->force_remove_props.insert(PARSEINT(params[1])); return; } + if (attrib == "force_remove_flexbody" && params.size() == 2) { tuneup_def->force_remove_flexbodies.insert(PARSEINT(params[1])); return; } } void RoR::TuneupUtil::ExportTuneup(Ogre::DataStreamPtr& stream, TuneupDefPtr& tuneup) @@ -430,18 +434,18 @@ void RoR::TuneupUtil::ExportTuneup(Ogre::DataStreamPtr& stream, TuneupDefPtr& tu buf << "\tguid = " << tuneup->guid << "\n"; buf << "\n"; - // Modding attributes: + // Addonparts and extracted data: for (const std::string& addonpart: tuneup->use_addonparts) { buf << "\tuse_addonpart = " << addonpart << "\n"; } - for (PropID_t remove_prop: tuneup->remove_props) + for (PropID_t unwanted_prop: tuneup->unwanted_props) { - buf << "\tremove_prop = " << (int)remove_prop << "\n"; + buf << "\tunwanted_prop = " << (int)unwanted_prop << "\n"; } - for (FlexbodyID_t remove_flexbody: tuneup->remove_flexbodies) + for (FlexbodyID_t unwanted_flexbody: tuneup->unwanted_flexbodies) { - buf << "\tremove_flexbody = " << (int)remove_flexbody << "\n"; + buf << "\tunwanted_flexbody = " << (int)unwanted_flexbody << "\n"; } for (PropID_t protected_prop: tuneup->protected_props) { @@ -451,7 +455,17 @@ void RoR::TuneupUtil::ExportTuneup(Ogre::DataStreamPtr& stream, TuneupDefPtr& tu { buf << "\tprotected_flexbody = " << (int)protected_flexbody << "\n"; } - for (auto& pair: tuneup->wheel_forced_sides) + + // UI overrides: + for (PropID_t prop: tuneup->force_remove_props) + { + buf << "\tforce_remove_prop = " << (int)prop << "\n"; + } + for (FlexbodyID_t flexbody: tuneup->force_remove_flexbodies) + { + buf << "\tforce_remove_flexbody = " << (int)flexbody << "\n"; + } + for (auto& pair: tuneup->force_wheel_sides) { buf << "\tforced_wheel_side = " << pair.first << ", " << (int)pair.second << "\n"; } diff --git a/source/main/resources/tuneup_fileformat/TuneupFileFormat.h b/source/main/resources/tuneup_fileformat/TuneupFileFormat.h index c4c39c9227..9541ed9cfd 100644 --- a/source/main/resources/tuneup_fileformat/TuneupFileFormat.h +++ b/source/main/resources/tuneup_fileformat/TuneupFileFormat.h @@ -85,7 +85,7 @@ struct TuneupDef: public RefCountingObject CacheCategoryId category_id = CID_None; /// @} - /// @name Modding attributes and overrides + /// @name Addonparts and extracted data /// @{ std::set use_addonparts; //!< Addonpart filenames @@ -93,11 +93,19 @@ struct TuneupDef: public RefCountingObject std::map wheel_tweaks; //!< Mesh name and radius overrides via 'addonpart_tweak_wheel' std::map prop_tweaks; //!< Mesh name(s), offset and rotation overrides via 'addonpart_tweak_prop' std::map flexbody_tweaks; //!< Mesh name, offset and rotation overrides via 'addonpart_tweak_flexbody' + std::set unwanted_props; //!< 'addonpart_unwanted_prop' directives. + std::set unwanted_flexbodies; //!< 'addonpart_unwanted_flexbody' directives. + /// @} - std::set remove_props; //!< Either UI overrides or 'addonpart_unwanted_prop' directives. - std::set remove_flexbodies; //!< Either UI overrides or 'addonpart_unwanted_flexbody' directives. - std::map wheel_forced_sides; //!< UI overrides only, not affected by addonparts. + /// @name UI-controlled forced changes (override addonparts) + /// @{ + std::set force_remove_props; //!< UI overrides + std::set force_remove_flexbodies; //!< UI overrides + std::map force_wheel_sides; //!< UI overrides + /// @} + /// @name UI-controlled protection from addonpart tweaks + /// @{ std::set protected_nodes; //!< Nodes that cannot be altered via 'addonpart_tweak_node' std::set protected_wheels; //!< Wheels that cannot be altered via 'addonpart_tweak_wheel' std::set protected_props; //!< Props which cannot be altered via 'addonpart_tweak_prop' or 'addonpart_remove_prop' directive. @@ -113,6 +121,19 @@ struct TuneupDef: public RefCountingObject bool isWheelProtected(int wheelid) const { return protected_wheels.find(wheelid) != protected_wheels.end(); } bool isNodeProtected(NodeNum_t nodenum) const { return protected_nodes.find(nodenum) != protected_nodes.end(); } /// @} + + /// @name Unwanted-state helpers + /// @{ + bool isPropUnwanted(PropID_t propid) { return unwanted_props.find(propid) != unwanted_props.end(); } + bool isFlexbodyUnwanted(FlexbodyID_t flexbodyid) { return unwanted_flexbodies.find(flexbodyid) != unwanted_flexbodies.end(); } + /// @} + + /// @name Forced-state helpers + /// @{ + bool isPropForceRemoved(PropID_t propid) { return force_remove_props.find(propid) != force_remove_props.end(); } + bool isFlexbodyForceRemoved(FlexbodyID_t flexbodyid) { return force_remove_flexbodies.find(flexbodyid) != force_remove_flexbodies.end(); } + bool isWheelSideForced(int wheelid) const { return force_wheel_sides.find(wheelid) != force_wheel_sides.end(); } + /// @} }; class TuneupUtil