diff --git a/source/main/ForwardDeclarations.h b/source/main/ForwardDeclarations.h index 012ca5e42a..941e9712b3 100644 --- a/source/main/ForwardDeclarations.h +++ b/source/main/ForwardDeclarations.h @@ -46,6 +46,9 @@ namespace RoR typedef int RefelemID_t; //!< index to `PointColDetector::m_ref_list`, use `RoR::REFELEMID_INVALID` as empty value. static const RefelemID_t REFELEMID_INVALID = -1; + typedef int CacheEntryID_t; //!< index to `CacheSystem::m_cache_entries`, use `RoR::CACHEENTRYNUM_INVALID` as empty value. + static const CacheEntryID_t CACHEENTRYID_INVALID = -1; + typedef uint16_t NodeNum_t; //!< Node position within `Actor::ar_nodes`; use RoR::NODENUM_INVALID as empty value. static const NodeNum_t NODENUM_INVALID = std::numeric_limits::max(); diff --git a/source/main/GameContext.cpp b/source/main/GameContext.cpp index b3b6aebbbf..f0bed0922d 100644 --- a/source/main/GameContext.cpp +++ b/source/main/GameContext.cpp @@ -189,38 +189,9 @@ ActorPtr GameContext::SpawnActor(ActorSpawnRequest& rq) { m_last_cache_selection = rq.asr_cache_entry; m_last_skin_selection = rq.asr_skin_entry; + m_last_tuneup_selection = rq.asr_tuneup_entry; m_last_section_config = rq.asr_config; - // Make sure the actor has a default .tuneup project assigned. If not, create it. - if (App::sim_tuning_enabled->getBool()) - { - CacheQuery query; - query.cqy_filter_type = LT_Tuneup; - query.cqy_filter_category_id = CID_TuneupsAuto; - query.cqy_filter_guid = rq.asr_cache_entry->guid; - if (App::GetCacheSystem()->Query(query) > 0) - { - rq.asr_tuneup_entry = query.cqy_results[0].cqr_entry; - } - else - { - CreateProjectRequest req; - req.cpr_type = CreateProjectRequestType::CREATE_TUNEUP; - req.cpr_source_entry = rq.asr_cache_entry; - req.cpr_name = fmt::format("tuned_{}", rq.asr_cache_entry->fname); - req.cpr_description = fmt::format("Customized {}", rq.asr_cache_entry->dname); - - rq.asr_tuneup_entry = App::GetCacheSystem()->CreateProject(&req); // Do it synchronously - - if (!rq.asr_tuneup_entry) - { - Str<500> msg; msg <<"Cannot spawn actor; .tuneup project could not be created."; - App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_ACTOR, Console::CONSOLE_SYSTEM_ERROR, msg.ToCStr()); - return nullptr; - } - } - } - if (rq.asr_spawnbox == nullptr) { if (m_player_actor != nullptr) @@ -267,12 +238,15 @@ ActorPtr GameContext::SpawnActor(ActorSpawnRequest& rq) } } - if (rq.asr_tuneup_entry) + if (App::sim_tuning_enabled->getBool()) { - App::GetCacheSystem()->LoadResource(rq.asr_tuneup_entry); // Also loads associated .tuneup file. - if (!rq.asr_tuneup_entry->tuneup_def) // Make sure .tuneup was loaded OK. + if (rq.asr_tuneup_entry) { - rq.asr_tuneup_entry = nullptr; // Error already logged + App::GetCacheSystem()->LoadResource(rq.asr_tuneup_entry); // Also loads associated .tuneup file. + if (!rq.asr_tuneup_entry->tuneup_def) + { + rq.asr_tuneup_entry = nullptr; // Error already logged + } } } @@ -413,7 +387,7 @@ void GameContext::ModifyActor(ActorModifyRequest& rq) srq->asr_rotation = Ogre::Quaternion(Ogre::Degree(270) - Ogre::Radian(actor->getRotation()), Ogre::Vector3::UNIT_Y); srq->asr_config = actor->getSectionConfig(); srq->asr_skin_entry = actor->getUsedSkinEntry(); - srq->asr_tuneup_entry = actor->getUsedTuneupEntry(); + srq->asr_working_tuneup = actor->getWorkingTuneupDef(); srq->asr_cache_entry= entry; srq->asr_debugview = (int)actor->GetGfxActor()->GetDebugView(); srq->asr_origin = ActorSpawnRequest::Origin::USER; diff --git a/source/main/GameContext.h b/source/main/GameContext.h index e991f255a7..013aa3ed51 100644 --- a/source/main/GameContext.h +++ b/source/main/GameContext.h @@ -196,6 +196,7 @@ class GameContext CacheEntryPtr m_last_cache_selection; //!< Vehicle/load CacheEntryPtr m_last_skin_selection; + CacheEntryPtr m_last_tuneup_selection; Ogre::String m_last_section_config; ActorSpawnRequest m_current_selection; //!< Context of the loader UI CacheEntryPtr m_dummy_cache_selection; diff --git a/source/main/gui/panels/GUI_TopMenubar.cpp b/source/main/gui/panels/GUI_TopMenubar.cpp index d0556a6a54..641826f3f9 100644 --- a/source/main/gui/panels/GUI_TopMenubar.cpp +++ b/source/main/gui/panels/GUI_TopMenubar.cpp @@ -1449,12 +1449,8 @@ void TopMenubar::Draw(float dt) else { ROR_ASSERT(tuning_actor->getUsedActorEntry()); - CacheEntryPtr& tuneup_entry = tuning_actor->getUsedTuneupEntry(); - if (tuneup_entry) - { - ROR_ASSERT(tuneup_entry->resource_group != ""); - ROR_ASSERT(tuneup_entry->tuneup_def != nullptr); - } + TuneupDefPtr& tuneup_def = tuning_actor->getWorkingTuneupDef(); + // KILL SWITCH @@ -1594,13 +1590,13 @@ void TopMenubar::Draw(float dt) ImGui::SetNextItemOpen(true, ImGuiCond_FirstUseEver); std::string addonparts_title = fmt::format(_LC("TopMenubar", "Addon parts ({})"), tuning_addonparts.size()); - if (ImGui::CollapsingHeader(addonparts_title.c_str()) && tuneup_entry) + if (ImGui::CollapsingHeader(addonparts_title.c_str())) { for (CacheEntryPtr& addonpart_entry: tuning_addonparts) { ImGui::PushID(addonpart_entry->fname.c_str()); - bool used = tuneup_entry->tuneup_def->use_addonparts.count(addonpart_entry->fname) > 0; + bool used = TuneupUtil::isAddonPartUsed(tuneup_def, addonpart_entry->fname); if (ImGui::Checkbox(addonpart_entry->dname.c_str(), &used)) { ModifyProjectRequest* req = new ModifyProjectRequest(); @@ -1624,7 +1620,7 @@ void TopMenubar::Draw(float dt) srq->asr_rotation = Ogre::Quaternion(Ogre::Degree(270) - Ogre::Radian(tuning_actor->getRotation()), Ogre::Vector3::UNIT_Y); srq->asr_config = tuning_actor->getSectionConfig(); srq->asr_skin_entry = tuning_actor->getUsedSkinEntry(); - srq->asr_tuneup_entry = tuneup_entry; + srq->asr_working_tuneup = tuning_actor->getWorkingTuneupDef(); srq->asr_cache_entry = tuning_actor->getUsedActorEntry(); srq->asr_debugview = (int)tuning_actor->GetGfxActor()->GetDebugView(); srq->asr_origin = ActorSpawnRequest::Origin::USER; @@ -1649,7 +1645,7 @@ void TopMenubar::Draw(float dt) // Draw props size_t total_props = tuning_actor->GetGfxActor()->getProps().size(); std::string props_title = fmt::format(_LC("Tuning", "Props ({})"), total_props); - if (ImGui::CollapsingHeader(props_title.c_str()) && tuneup_entry) + if (ImGui::CollapsingHeader(props_title.c_str())) { // Draw all props (those removed by addonparts are also present as placeholders) for (Prop const& p: tuning_actor->GetGfxActor()->getProps()) @@ -1662,8 +1658,8 @@ void TopMenubar::Draw(float dt) this->DrawTuningForceRemoveControls( p.pp_id, p.pp_media[0], - tuneup_entry->tuneup_def->isPropUnwanted(p.pp_id), - tuneup_entry->tuneup_def->isPropForceRemoved(p.pp_id), + tuneup_def && tuneup_def->isPropUnwanted(p.pp_id), + tuneup_def && tuneup_def->isPropForceRemoved(p.pp_id), ModifyProjectRequestType::TUNEUP_FORCEREMOVE_PROP_SET, ModifyProjectRequestType::TUNEUP_FORCEREMOVE_PROP_RESET); @@ -1694,7 +1690,7 @@ void TopMenubar::Draw(float dt) this->DrawTuningProtectedChkRightAligned( p.pp_id, - tuneup_entry->tuneup_def->isPropProtected(p.pp_id), + tuneup_def && tuneup_def->isPropProtected(p.pp_id), ModifyProjectRequestType::TUNEUP_PROTECTED_PROP_SET, ModifyProjectRequestType::TUNEUP_PROTECTED_PROP_RESET); @@ -1707,7 +1703,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("Tuning", "Flexbodies ({})"), total_flexbodies); - if (ImGui::CollapsingHeader(flexbodies_title.c_str()) && tuneup_entry) + if (ImGui::CollapsingHeader(flexbodies_title.c_str())) { // Draw all flexbodies (those removed by addonparts are also present as placeholders) for (FlexBody* flexbody: tuning_actor->GetGfxActor()->GetFlexbodies()) @@ -1720,14 +1716,14 @@ void TopMenubar::Draw(float dt) this->DrawTuningForceRemoveControls( flexbody->getID(), flexbody->getOrigMeshName(), - tuneup_entry->tuneup_def->isFlexbodyUnwanted(flexbody->getID()), - tuneup_entry->tuneup_def->isFlexbodyForceRemoved(flexbody->getID()), + tuneup_def && tuneup_def->isFlexbodyUnwanted(flexbody->getID()), + tuneup_def && tuneup_def->isFlexbodyForceRemoved(flexbody->getID()), ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_SET, ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_RESET); this->DrawTuningProtectedChkRightAligned( flexbody->getID(), - tuneup_entry->tuneup_def->isFlexbodyProtected(flexbody->getID()), + tuneup_def && tuneup_def->isFlexbodyProtected(flexbody->getID()), ModifyProjectRequestType::TUNEUP_PROTECTED_FLEXBODY_SET, ModifyProjectRequestType::TUNEUP_PROTECTED_FLEXBODY_RESET); @@ -1738,7 +1734,7 @@ void TopMenubar::Draw(float dt) // Draw wheels const int total_wheels = tuning_actor->ar_num_wheels; std::string wheels_title = fmt::format(_LC("TopMenubar", "Wheels ({})"), total_wheels); - if (ImGui::CollapsingHeader(wheels_title.c_str()) && tuneup_entry) + if (ImGui::CollapsingHeader(wheels_title.c_str())) { for (WheelID_t i = 0; i < total_wheels; i++) { @@ -1748,12 +1744,13 @@ void TopMenubar::Draw(float dt) this->DrawTuningBoxedSubjectIdInline(i); // Draw R/L radio buttons - if (tuneup_entry->tuneup_def->isWheelSideForced(i)) + WheelSide forced_side = WheelSide::INVALID; + if (tuneup_def && tuneup_def->isWheelSideForced(i, /*[out]*/forced_side)) { 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)); + const RoR::WheelSide active_side = TuneupUtil::getTweakedWheelSide(tuneup_def, i, tuning_actor->GetGfxActor()->getWheelSide(i)); RoR::WheelSide selected_side = active_side; if (ImGui::RadioButton("##L", active_side == WheelSide::LEFT)) selected_side = WheelSide::LEFT; @@ -1770,7 +1767,7 @@ void TopMenubar::Draw(float dt) // Draw reset button bool resetPressed = false; - if (tuneup_entry->tuneup_def->isWheelSideForced(i)) + if (tuneup_def && tuneup_def->isWheelSideForced(i, forced_side)) { ImGui::SameLine(); ImGui::SameLine(); @@ -1802,7 +1799,7 @@ void TopMenubar::Draw(float dt) this->DrawTuningProtectedChkRightAligned( i, - tuneup_entry->tuneup_def->isWheelProtected(i), + tuneup_def && tuneup_def->isWheelProtected(i), ModifyProjectRequestType::TUNEUP_PROTECTED_WHEEL_SET, ModifyProjectRequestType::TUNEUP_PROTECTED_WHEEL_RESET); @@ -2268,10 +2265,11 @@ void TopMenubar::GetPresets() void TopMenubar::RefreshTuningMenu() { const ActorPtr& current_actor = App::GetGameContext()->GetPlayerActor(); - if (App::sim_tuning_enabled->getBool() && current_actor && (tuning_actor != current_actor || tuning_force_refresh)) + if (App::sim_tuning_enabled->getBool() + && current_actor + && (tuning_actor != current_actor || tuning_force_refresh)) { ROR_ASSERT(current_actor->getUsedActorEntry()); - ROR_ASSERT(current_actor->getUsedTuneupEntry()); tuning_addonparts.clear(); tuning_saves.resetResults(); @@ -2290,21 +2288,24 @@ void TopMenubar::RefreshTuningMenu() } // Addonparts force-installed via [browse all] button; watch for duplicates. - for (std::string const& use_addonpart_fname: current_actor->getUsedTuneupEntry()->tuneup_def->use_addonparts) + if (current_actor->getWorkingTuneupDef()) { - CacheEntryPtr entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, use_addonpart_fname); - if (entry) + for (std::string const& use_addonpart_fname: current_actor->getWorkingTuneupDef()->use_addonparts) { - if (std::find(tuning_addonparts.begin(), tuning_addonparts.end(), entry) == tuning_addonparts.end()) + CacheEntryPtr entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, use_addonpart_fname); + if (entry) { - tuning_addonparts.push_back(entry); + if (std::find(tuning_addonparts.begin(), tuning_addonparts.end(), entry) == tuning_addonparts.end()) + { + tuning_addonparts.push_back(entry); + } } } } tuning_saves.cqy_filter_type = LT_Tuneup; tuning_saves.cqy_filter_guid = current_actor->getUsedActorEntry()->guid; - tuning_saves.cqy_filter_category_id = CID_TuneupsUser; // Exclude auto-generated entries + tuning_saves.cqy_filter_category_id = CID_Tuneups; // Exclude auto-generated entries tuning_saves.resetResults(); App::GetCacheSystem()->Query(tuning_saves); diff --git a/source/main/physics/Actor.cpp b/source/main/physics/Actor.cpp index 0bfc107fa9..ca7d7d94a6 100644 --- a/source/main/physics/Actor.cpp +++ b/source/main/physics/Actor.cpp @@ -62,6 +62,7 @@ #include "SlideNode.h" #include "SoundScriptManager.h" #include "Terrain.h" +#include "TuneupFileFormat.h" #include "TurboJet.h" #include "TurboProp.h" #include "Utils.h" @@ -4329,7 +4330,7 @@ Actor::Actor( , m_section_config(rq.asr_config) , m_used_actor_entry(rq.asr_cache_entry) , m_used_skin_entry(rq.asr_skin_entry) - , m_used_tuneup_entry(rq.asr_tuneup_entry) + , m_working_tuneup_def(rq.asr_working_tuneup) // Public bit flags , ar_update_physics(false) @@ -4590,7 +4591,15 @@ CacheEntryPtr& Actor::getUsedSkinEntry() return m_used_skin_entry; } -CacheEntryPtr& Actor::getUsedTuneupEntry() +TuneupDefPtr& Actor::getWorkingTuneupDef() { - return m_used_tuneup_entry; -} \ No newline at end of file + return m_working_tuneup_def; +} + +void Actor::ensureWorkingTuneupDef() +{ + if (!m_working_tuneup_def) + { + m_working_tuneup_def = new TuneupDef(); + } +} diff --git a/source/main/physics/Actor.h b/source/main/physics/Actor.h index 6dfdba9b62..18efa4a158 100644 --- a/source/main/physics/Actor.h +++ b/source/main/physics/Actor.h @@ -219,7 +219,8 @@ class Actor : public RefCountingObject // not exported to scripting: CacheEntryPtr& getUsedActorEntry(); //!< The actor entry itself. CacheEntryPtr& getUsedSkinEntry(); - CacheEntryPtr& getUsedTuneupEntry(); + TuneupDefPtr& getWorkingTuneupDef(); + void ensureWorkingTuneupDef(); bool isPreloadedWithTerrain() const { return m_preloaded_with_terrain; }; std::vector getAuthors(); std::vector getDescription(); @@ -296,7 +297,7 @@ class Actor : public RefCountingObject std::vector ar_initial_node_positions; std::vector> ar_initial_beam_defaults; std::vector ar_wheeldetachers; -ActorPtrVec ar_linked_actors; //!< Sim state; other actors linked using 'hooks' + ActorPtrVec ar_linked_actors; //!< Sim state; other actors linked using 'hooks' std::vector> ar_node_to_node_connections; std::vector> ar_node_to_beam_connections; std::vector ar_collision_bounding_boxes; //!< smart bounding boxes, used for determining the state of an actor (every box surrounds only a subset of nodes) @@ -569,7 +570,7 @@ ActorPtrVec ar_linked_actors; //!< Sim state std::unique_ptr m_buoyance; //!< Physics CacheEntryPtr m_used_actor_entry; CacheEntryPtr m_used_skin_entry; //!< Graphics - CacheEntryPtr m_used_tuneup_entry; + TuneupDefPtr m_working_tuneup_def; //!< Each actor gets unique instance, even if loaded from .tuneup file in modcache. Skidmark* m_skid_trails[MAX_WHEELS*2] = {}; bool m_antilockbrake = false; //!< GUI state bool m_tractioncontrol = false; //!< GUI state diff --git a/source/main/physics/ActorManager.cpp b/source/main/physics/ActorManager.cpp index 84e9a2b755..f6f2851562 100644 --- a/source/main/physics/ActorManager.cpp +++ b/source/main/physics/ActorManager.cpp @@ -51,6 +51,7 @@ #include "SoundScriptManager.h" #include "Terrain.h" #include "ThreadPool.h" +#include "TuneupFileFormat.h" #include "Utils.h" #include "VehicleAI.h" @@ -88,7 +89,7 @@ ActorPtr ActorManager::CreateNewActor(ActorSpawnRequest rq, RigDef::DocumentPtr ActorSpawner spawner; spawner.ConfigureSections(actor->m_section_config, def); - spawner.ConfigureAddonParts(actor->m_used_tuneup_entry); + spawner.ConfigureAddonParts(actor->m_working_tuneup_def); spawner.ProcessNewActor(actor, rq, def); if (App::diag_actor_dump->getBool()) diff --git a/source/main/physics/ActorSpawner.cpp b/source/main/physics/ActorSpawner.cpp index d40f147f28..e725b44aae 100644 --- a/source/main/physics/ActorSpawner.cpp +++ b/source/main/physics/ActorSpawner.cpp @@ -108,23 +108,19 @@ void ActorSpawner::ConfigureSections(Ogre::String const & sectionconfig, RigDef: } } -void ActorSpawner::ConfigureAddonParts(CacheEntryPtr& tuneup_entry) +void ActorSpawner::ConfigureAddonParts(TuneupDefPtr& tuneup_def) { - if (tuneup_entry) + if (tuneup_def) { - App::GetCacheSystem()->LoadResource(tuneup_entry); - ROR_ASSERT(tuneup_entry->resource_group != ""); - ROR_ASSERT(tuneup_entry->tuneup_def != nullptr); + AddonPartUtility::ResetUnwantedAndTweakedElements(tuneup_def); - AddonPartUtility::ResetUnwantedAndTweakedElements(tuneup_entry->tuneup_def); - - for (const std::string& addonpart: tuneup_entry->tuneup_def->use_addonparts) + for (const std::string& addonpart: tuneup_def->use_addonparts) { CacheEntryPtr addonpart_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, addonpart); if (addonpart_entry) { AddonPartUtility util; - util.ResolveUnwantedAndTweakedElements(tuneup_entry->tuneup_def, addonpart_entry); + util.ResolveUnwantedAndTweakedElements(tuneup_def, addonpart_entry); auto module = util.TransformToRigDefModule(addonpart_entry); if (module) { @@ -1497,7 +1493,7 @@ void ActorSpawner::ProcessFlexbody(RigDef::Flexbody& def) const FlexbodyID_t flexbody_id = (FlexbodyID_t)m_actor->m_gfx_actor->m_flexbodies.size(); // Check if disabled by .tuneup mod. - if (TuneupUtil::isFlexbodyAnyhowRemoved(m_actor, flexbody_id)) + if (TuneupUtil::isFlexbodyAnyhowRemoved(m_actor->getWorkingTuneupDef(), flexbody_id)) { // Create placeholder m_actor->m_gfx_actor->m_flexbodies.emplace_back(new FlexBody(FlexBody::TUNING_PLACEHOLDER, flexbody_id, def.mesh_name)); @@ -1530,17 +1526,17 @@ void ActorSpawner::ProcessFlexbody(RigDef::Flexbody& def) try { - std::string mesh_rg = (def._mesh_rg_override != "") ? def._mesh_rg_override : m_actor->GetGfxActor()->GetResourceGroup(); + std::string mesh_rg = (def._mesh_rg_override != "") ? def._mesh_rg_override : m_actor->getTruckFileResourceGroup(); auto* flexbody = m_flex_factory.CreateFlexBody( (FlexbodyID_t)m_actor->m_gfx_actor->m_flexbodies.size(), this->GetNodeIndexOrThrow(def.reference_node), this->GetNodeIndexOrThrow(def.x_axis_node), this->GetNodeIndexOrThrow(def.y_axis_node), - TuneupUtil::getTweakedFlexbodyOffset(m_actor->getUsedTuneupEntry(), flexbody_id, def.offset), - TuneupUtil::getTweakedFlexbodyRotation(m_actor->getUsedTuneupEntry(), flexbody_id, def.rotation), + TuneupUtil::getTweakedFlexbodyOffset(m_actor->getWorkingTuneupDef(), flexbody_id, def.offset), + TuneupUtil::getTweakedFlexbodyRotation(m_actor->getWorkingTuneupDef(), flexbody_id, def.rotation), node_indices, - TuneupUtil::getTweakedFlexbodyMedia(m_actor->getUsedTuneupEntry(), flexbody_id, 0, def.mesh_name), - TuneupUtil::getTweakedFlexbodyMediaRG(m_actor, flexbody_id, 0, mesh_rg) + TuneupUtil::getTweakedFlexbodyMedia(m_actor->getWorkingTuneupDef(), flexbody_id, 0, def.mesh_name), + TuneupUtil::getTweakedFlexbodyMediaRG(m_actor->getWorkingTuneupDef(), flexbody_id, 0, mesh_rg) ); if (flexbody == nullptr) @@ -1568,13 +1564,13 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) PropID_t prop_id = static_cast(m_actor->m_gfx_actor->m_props.size()); // Check if removed via .tuneup - if (TuneupUtil::isPropAnyhowRemoved(m_actor, prop_id)) + if (TuneupUtil::isPropAnyhowRemoved(m_actor->getWorkingTuneupDef(), prop_id)) { RoR::Prop pprop; // placeholder pprop.pp_id = prop_id; pprop.pp_camera_mode_orig = CAMERA_MODE_ALWAYS_HIDDEN; pprop.pp_camera_mode_active = CAMERA_MODE_ALWAYS_HIDDEN; - pprop.pp_media[0] = TuneupUtil::getTweakedPropMedia(m_actor->getUsedTuneupEntry(), prop_id, 0, def.mesh_name); + pprop.pp_media[0] = TuneupUtil::getTweakedPropMedia(m_actor->getWorkingTuneupDef(), prop_id, 0, def.mesh_name); m_actor->m_gfx_actor->m_props.push_back(pprop); return; } @@ -1584,9 +1580,9 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) prop.pp_node_ref = this->GetNodeIndexOrThrow(def.reference_node); prop.pp_node_x = this->GetNodeIndexOrThrow(def.x_axis_node); prop.pp_node_y = this->GetNodeIndexOrThrow(def.y_axis_node); - prop.pp_offset = TuneupUtil::getTweakedPropOffset(m_actor->getUsedTuneupEntry(), prop_id, def.offset); + prop.pp_offset = TuneupUtil::getTweakedPropOffset(m_actor->getWorkingTuneupDef(), prop_id, def.offset); prop.pp_offset_orig = prop.pp_offset; - prop.pp_rota = TuneupUtil::getTweakedPropRotation(m_actor->getUsedTuneupEntry(), prop_id, def.rotation); + prop.pp_rota = TuneupUtil::getTweakedPropRotation(m_actor->getWorkingTuneupDef(), prop_id, def.rotation); prop.pp_rot = Ogre::Quaternion(Ogre::Degree(prop.pp_rota.z), Ogre::Vector3::UNIT_Z) * Ogre::Quaternion(Ogre::Degree(prop.pp_rota.y), Ogre::Vector3::UNIT_Y) * Ogre::Quaternion(Ogre::Degree(prop.pp_rota.x), Ogre::Vector3::UNIT_X); @@ -1624,14 +1620,14 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) { steering_wheel_offset = def.special_prop_dashboard.offset; } - std::string media1_rg = (def._mesh_rg_override != "") ? def._mesh_rg_override : m_actor->GetGfxActor()->GetResourceGroup(); + std::string media1_rg = (def._mesh_rg_override != "") ? def._mesh_rg_override : m_actor->getTruckFileResourceGroup(); prop.pp_wheel_rot_degree = def.special_prop_dashboard.rotation_angle; prop.pp_wheel_scene_node = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode(); prop.pp_wheel_pos = steering_wheel_offset; - prop.pp_media[1] = TuneupUtil::getTweakedPropMedia(m_actor->getUsedTuneupEntry(), prop_id, 1, def.special_prop_dashboard.mesh_name); + prop.pp_media[1] = TuneupUtil::getTweakedPropMedia(m_actor->getWorkingTuneupDef(), prop_id, 1, def.special_prop_dashboard.mesh_name); prop.pp_wheel_mesh_obj = new MeshObject( prop.pp_media[1], - TuneupUtil::getTweakedPropMediaRG(m_actor, prop_id, 1, media1_rg), + TuneupUtil::getTweakedPropMediaRG(m_actor->getWorkingTuneupDef(), prop_id, 1, media1_rg), this->ComposeName("SteeringWheelPropEntity", prop_id), prop.pp_wheel_scene_node ); @@ -1639,12 +1635,12 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) } /* CREATE THE PROP */ - std::string media0_rg = (def._mesh_rg_override != "") ? def._mesh_rg_override : m_actor->GetGfxActor()->GetResourceGroup(); + std::string media0_rg = (def._mesh_rg_override != "") ? def._mesh_rg_override : m_actor->getTruckFileResourceGroup(); prop.pp_scene_node = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode(); - prop.pp_media[0] = TuneupUtil::getTweakedPropMedia(m_actor->getUsedTuneupEntry(), prop_id, 0, def.mesh_name); + prop.pp_media[0] = TuneupUtil::getTweakedPropMedia(m_actor->getWorkingTuneupDef(), prop_id, 0, def.mesh_name); prop.pp_mesh_obj = new MeshObject(//def.mesh_name, resource_group, instance_name, prop.pp_scene_node); prop.pp_media[0], - TuneupUtil::getTweakedPropMediaRG(m_actor, prop_id, 1, media0_rg), + TuneupUtil::getTweakedPropMediaRG(m_actor->getWorkingTuneupDef(), prop_id, 1, media0_rg), this->ComposeName("PropEntity", prop_id), prop.pp_scene_node); @@ -1702,7 +1698,7 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) pp_beacon_light->setCastShadows(false); pp_beacon_light->setVisible(false); /* the flare billboard */ - prop.pp_media[1] = TuneupUtil::getTweakedPropMedia(m_actor->getUsedTuneupEntry(), prop_id, 1, def.special_prop_beacon.flare_material_name); + prop.pp_media[1] = TuneupUtil::getTweakedPropMedia(m_actor->getWorkingTuneupDef(), prop_id, 1, def.special_prop_beacon.flare_material_name); auto flare_scene_node = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode(); auto flare_billboard_sys = App::GetGfxScene()->GetSceneManager()->createBillboardSet(1); //(propname,1); if (flare_billboard_sys) @@ -4119,8 +4115,8 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) } // Tweaks - float override_rim_radius = TuneupUtil::getTweakedWheelRimRadius(m_actor->getUsedTuneupEntry(), wheel_id, def.rim_radius); - float override_tire_radius = TuneupUtil::getTweakedWheelTireRadius(m_actor->getUsedTuneupEntry(), wheel_id, def.tyre_radius); + float override_rim_radius = TuneupUtil::getTweakedWheelRimRadius(m_actor->getWorkingTuneupDef(), wheel_id, def.rim_radius); + float override_tire_radius = TuneupUtil::getTweakedWheelTireRadius(m_actor->getWorkingTuneupDef(), wheel_id, def.tyre_radius); // Node&beam generation Ogre::Vector3 axis_vector = axis_node_2->RelPosition - axis_node_1->RelPosition; @@ -4349,11 +4345,11 @@ void ActorSpawner::ProcessFlexBodyWheel(RigDef::FlexBodyWheel & def) axis_node_2->pos, def.num_rays, override_rim_radius, - TuneupUtil::getTweakedWheelSide(m_actor->getUsedTuneupEntry(), wheel_id, def.side), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 0, def.rim_mesh_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 0), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 1, def.tyre_mesh_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 1) + TuneupUtil::getTweakedWheelSide(m_actor->getWorkingTuneupDef(), wheel_id, def.side), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 0, def.rim_mesh_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 0, m_actor->getTruckFileResourceGroup()), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 1, def.tyre_mesh_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 1, m_actor->getTruckFileResourceGroup()) ); // Commit the wheel @@ -4408,7 +4404,7 @@ void ActorSpawner::ProcessMeshWheel(RigDef::MeshWheel & meshwheel_def) GetNodePointer(meshwheel_def.reference_arm_node), /*optional*/ meshwheel_def.num_rays * 2, meshwheel_def.num_rays * 8, - TuneupUtil::getTweakedWheelTireRadius(m_actor->getUsedTuneupEntry(), wheel_id, meshwheel_def.tyre_radius), + TuneupUtil::getTweakedWheelTireRadius(m_actor->getWorkingTuneupDef(), wheel_id, meshwheel_def.tyre_radius), meshwheel_def.propulsion, meshwheel_def.braking, meshwheel_def.node_defaults, @@ -4434,11 +4430,11 @@ void ActorSpawner::ProcessMeshWheel(RigDef::MeshWheel & meshwheel_def) axis_node_1->pos, axis_node_2->pos, meshwheel_def.num_rays, - TuneupUtil::getTweakedWheelSide(m_actor->getUsedTuneupEntry(), wheel_id, meshwheel_def.side), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 0, meshwheel_def.mesh_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 0), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 1, meshwheel_def.material_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 1), + TuneupUtil::getTweakedWheelSide(m_actor->getWorkingTuneupDef(), wheel_id, meshwheel_def.side), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 0, meshwheel_def.mesh_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 0, m_actor->getTruckFileResourceGroup()), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 1, meshwheel_def.material_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 1, m_actor->getTruckFileResourceGroup()), meshwheel_def.rim_radius ); @@ -4465,7 +4461,7 @@ void ActorSpawner::ProcessMeshWheel2(RigDef::MeshWheel2 & def) GetNodePointer(def.reference_arm_node), def.num_rays * 2, def.num_rays * 8, - TuneupUtil::getTweakedWheelTireRadius(m_actor->getUsedTuneupEntry(), wheel_id, def.tyre_radius), + TuneupUtil::getTweakedWheelTireRadius(m_actor->getWorkingTuneupDef(), wheel_id, def.tyre_radius), def.propulsion, def.braking, def.node_defaults, @@ -4499,11 +4495,11 @@ void ActorSpawner::ProcessMeshWheel2(RigDef::MeshWheel2 & def) axis_node_1->pos, axis_node_2->pos, def.num_rays, - TuneupUtil::getTweakedWheelSide(m_actor->getUsedTuneupEntry(), wheel_id, def.side), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 0, def.mesh_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 0), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 1, def.material_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 1), + TuneupUtil::getTweakedWheelSide(m_actor->getWorkingTuneupDef(), wheel_id, def.side), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 0, def.mesh_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 0, m_actor->getTruckFileResourceGroup()), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 1, def.material_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 1, m_actor->getTruckFileResourceGroup()), def.rim_radius ); @@ -4729,7 +4725,7 @@ WheelID_t ActorSpawner::AddWheel(RigDef::Wheel & wheel_def) GetNodePointer(wheel_def.reference_arm_node), wheel_def.num_rays * 2, wheel_def.num_rays * 8, - TuneupUtil::getTweakedWheelTireRadius(m_actor->getUsedTuneupEntry(), wheel_id, wheel_def.radius), + TuneupUtil::getTweakedWheelTireRadius(m_actor->getWorkingTuneupDef(), wheel_id, wheel_def.radius), wheel_def.propulsion, wheel_def.braking, wheel_def.node_defaults, @@ -4754,10 +4750,10 @@ WheelID_t ActorSpawner::AddWheel(RigDef::Wheel & wheel_def) wheel_id, base_node_index, wheel_def.num_rays, - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 0, wheel_def.face_material_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 0), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 1, wheel_def.band_material_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 1), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 0, wheel_def.face_material_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 0, m_actor->getTruckFileResourceGroup()), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 1, wheel_def.band_material_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 1, m_actor->getTruckFileResourceGroup()), /*separate_rim:*/false ); @@ -4795,8 +4791,8 @@ WheelID_t ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) } // Tweaks - float override_rim_radius = TuneupUtil::getTweakedWheelRimRadius(m_actor->getUsedTuneupEntry(), wheel_id, wheel_2_def.rim_radius); - float override_tire_radius = TuneupUtil::getTweakedWheelTireRadius(m_actor->getUsedTuneupEntry(), wheel_id, wheel_2_def.tyre_radius); + float override_rim_radius = TuneupUtil::getTweakedWheelRimRadius(m_actor->getWorkingTuneupDef(), wheel_id, wheel_2_def.rim_radius); + float override_tire_radius = TuneupUtil::getTweakedWheelTireRadius(m_actor->getWorkingTuneupDef(), wheel_id, wheel_2_def.tyre_radius); /* Node&beam generation */ wheel_t& wheel = m_actor->ar_wheels[wheel_id]; @@ -4984,10 +4980,10 @@ WheelID_t ActorSpawner::AddWheel2(RigDef::Wheel2 & wheel_2_def) wheel_id, base_node_index, wheel_2_def.num_rays, - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 0, wheel_2_def.face_material_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 0), - TuneupUtil::getTweakedWheelMedia(m_actor->getUsedTuneupEntry(), wheel_id, 1, wheel_2_def.band_material_name), - TuneupUtil::getTweakedWheelMediaRG(m_actor, wheel_id, 1), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 0, wheel_2_def.face_material_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 0, m_actor->getTruckFileResourceGroup()), + TuneupUtil::getTweakedWheelMedia(m_actor->getWorkingTuneupDef(), wheel_id, 1, wheel_2_def.band_material_name), + TuneupUtil::getTweakedWheelMediaRG(m_actor->getWorkingTuneupDef(), wheel_id, 1, m_actor->getTruckFileResourceGroup()), /*separate_rim:*/true, /*rim_ratio:*/override_rim_radius / override_tire_radius ); @@ -5069,7 +5065,7 @@ void ActorSpawner::CreateFlexBodyWheelVisuals( rim_mesh_name, rim_mesh_rg, "tracks/trans", // Use a builtin transparent material for the generated tire mesh, to effectively disable it. - m_actor->GetGfxActor()->GetResourceGroup(), + m_actor->getTruckFileResourceGroup(), radius ); @@ -5798,7 +5794,7 @@ void ActorSpawner::ProcessNode(RigDef::Node & def) node.pos = inserted_node.first; /* Node index */ /* Positioning */ - Ogre::Vector3 node_position = m_spawn_position + TuneupUtil::getTweakedNodePosition(m_actor->getUsedTuneupEntry(), node.pos, def.position); + Ogre::Vector3 node_position = m_spawn_position + TuneupUtil::getTweakedNodePosition(m_actor->getWorkingTuneupDef(), node.pos, def.position); ROR_ASSERT(!isnan(node_position.x)); ROR_ASSERT(!isnan(node_position.y)); ROR_ASSERT(!isnan(node_position.z)); diff --git a/source/main/physics/ActorSpawner.h b/source/main/physics/ActorSpawner.h index acec756137..7821edb7d4 100644 --- a/source/main/physics/ActorSpawner.h +++ b/source/main/physics/ActorSpawner.h @@ -95,7 +95,7 @@ class ActorSpawner /// @name Processing /// @{ void ConfigureSections(Ogre::String const & sectionconfig, RigDef::DocumentPtr def); - void ConfigureAddonParts(CacheEntryPtr& tuneup_entry); + void ConfigureAddonParts(TuneupDefPtr& tuneup_def); void ProcessNewActor(ActorPtr actor, ActorSpawnRequest rq, RigDef::DocumentPtr def); static void SetupDefaultSoundSources(ActorPtr const& actor); /// @} diff --git a/source/main/physics/Savegame.cpp b/source/main/physics/Savegame.cpp index e3f5a69321..8ef53219a8 100644 --- a/source/main/physics/Savegame.cpp +++ b/source/main/physics/Savegame.cpp @@ -39,6 +39,7 @@ #include "Skidmark.h" #include "SkyManager.h" #include "Terrain.h" +#include "TuneupFileFormat.h" #include #include @@ -235,11 +236,11 @@ void GameContext::HandleSavegameHotkeys() // -------------------------------- // ActorManager functions -bool ActorManager::LoadScene(Ogre::String filename) +bool ActorManager::LoadScene(Ogre::String save_filename) { // Read from disk rapidjson::Document j_doc; - if (!App::GetContentManager()->LoadAndParseJson(filename, RGN_SAVEGAMES, j_doc) || + if (!App::GetContentManager()->LoadAndParseJson(save_filename, RGN_SAVEGAMES, j_doc) || !j_doc.IsObject() || !j_doc.HasMember("format_version") || !j_doc["format_version"].IsNumber()) { App::GetConsole()->putMessage( @@ -258,7 +259,7 @@ bool ActorManager::LoadScene(Ogre::String filename) if (App::mp_state->getEnum() == RoR::MpState::CONNECTED) { - if (filename == "autosave.sav") + if (save_filename == "autosave.sav") return false; if (terrain_name != App::sim_terrain_name->getStr()) { @@ -302,10 +303,10 @@ bool ActorManager::LoadScene(Ogre::String filename) std::vector x_actors = GetLocalActors(); for (rapidjson::Value& j_entry: j_doc["actors"].GetArray()) { - String filename = j_entry["filename"].GetString(); - if (!App::GetCacheSystem()->CheckResourceLoaded(filename)) + String rigdef_filename = j_entry["filename"].GetString(); + if (!App::GetCacheSystem()->CheckResourceLoaded(rigdef_filename)) { - Str<600> msg; msg << _L("Error while loading scene: Missing content (probably not installed)") << " '" << filename << "'"; + Str<600> msg; msg << _L("Error while loading scene: Missing content (probably not installed)") << " '" << rigdef_filename << "'"; App::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_ACTOR, Console::CONSOLE_SYSTEM_ERROR, msg.ToCStr()); actors.push_back(nullptr); continue; @@ -317,6 +318,17 @@ bool ActorManager::LoadScene(Ogre::String filename) skin = App::GetCacheSystem()->FetchSkinByName(j_entry["skin"].GetString()); } + TuneupDefPtr working_tuneup = nullptr; + if (j_entry.HasMember("tuneup_document")) + { + const char* tuneup_str = j_entry["tuneup_document"].GetString(); + size_t tuneup_len = j_entry["tuneup_document"].GetStringLength(); + Ogre::DataStreamPtr datastream(new Ogre::MemoryDataStream((void*)tuneup_str, tuneup_len)); + std::vector tuneups = TuneupUtil::ParseTuneups(datastream); + ROR_ASSERT(tuneups.size() > 0); + working_tuneup = tuneups[0]; + } + String section_config = j_entry["section_config"].GetString(); ActorPtr actor = nullptr; @@ -350,12 +362,13 @@ bool ActorManager::LoadScene(Ogre::String filename) bool preloaded = j_entry["preloaded_with_terrain"].GetBool(); ActorSpawnRequest* rq = new ActorSpawnRequest; - rq->asr_filename = filename; + rq->asr_filename = rigdef_filename; rq->asr_position.x = j_entry["position"][0].GetFloat(); rq->asr_position.y = preloaded ? j_entry["position"][1].GetFloat() : j_entry["min_height"].GetFloat(); rq->asr_position.z = j_entry["position"][2].GetFloat(); rq->asr_rotation = Quaternion(Degree(270) - Radian(j_entry["rotation"].GetFloat()), Vector3::UNIT_Y); rq->asr_skin_entry = skin; + rq->asr_working_tuneup = working_tuneup; rq->asr_config = section_config; rq->asr_origin = preloaded ? ActorSpawnRequest::Origin::TERRN_DEF : ActorSpawnRequest::Origin::SAVEGAME; rq->asr_free_position = preloaded; @@ -396,7 +409,7 @@ bool ActorManager::LoadScene(Ogre::String filename) this->RestoreSavedState(actor, j_entry); } - if (filename != "autosave.sav") + if (save_filename != "autosave.sav") { App::GetConsole()->putMessage( Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("Scene loaded")); @@ -490,6 +503,17 @@ bool ActorManager::SaveScene(Ogre::String filename) j_entry.AddMember("skin", rapidjson::StringRef(actor->m_used_skin_entry->dname.c_str()), j_doc.GetAllocator()); } + if (actor->getWorkingTuneupDef()) + { + // Include the entire .tuneup file in the savegame. + rapidjson::Value j_tuneup_document(rapidjson::kStringType); + Str tuneup_buf; // `Ogre::MemoryDataStream` doesn't zero-out the buffer it creates; we must supply our own zeroed memory. + Ogre::DataStreamPtr datastream(new Ogre::MemoryDataStream(tuneup_buf.GetBuffer(), tuneup_buf.GetCapacity())); + TuneupUtil::ExportTuneup(datastream, actor->getWorkingTuneupDef()); + j_tuneup_document.SetString(datastream->getAsString().c_str(), j_doc.GetAllocator()); + j_entry.AddMember("tuneup_document", j_tuneup_document, j_doc.GetAllocator()); + } + j_entry.AddMember("section_config", rapidjson::StringRef(actor->m_section_config.c_str()), j_doc.GetAllocator()); // Engine, anti-lock brake, traction control diff --git a/source/main/physics/SimData.cpp b/source/main/physics/SimData.cpp index 027a021db8..9fdf81ad68 100644 --- a/source/main/physics/SimData.cpp +++ b/source/main/physics/SimData.cpp @@ -23,17 +23,20 @@ #include "Actor.h" #include "CacheSystem.h" +#include "TuneupFileFormat.h" using namespace RoR; ActorSpawnRequest::ActorSpawnRequest() { // Constructs `CacheEntryPtr` - doesn't compile without `#include CacheSystem.h` - not pretty if in header (even if auto-generated by C++). + // Also `TuneupDefPtr` which needs `#include TuneupFileFormat.h` } ActorSpawnRequest::~ActorSpawnRequest() { // Destructs `CacheEntryPtr` - doesn't compile without `#include CacheSystem.h` - not pretty if in header (even if auto-generated by C++). + // Also `TuneupDefPtr` which needs `#include TuneupFileFormat.h` } beam_t::beam_t() diff --git a/source/main/physics/SimData.h b/source/main/physics/SimData.h index cb4c9eb9f6..342806a6d0 100644 --- a/source/main/physics/SimData.h +++ b/source/main/physics/SimData.h @@ -809,7 +809,8 @@ struct ActorSpawnRequest Ogre::Quaternion asr_rotation = Ogre::Quaternion::ZERO; collision_box_t* asr_spawnbox = nullptr; CacheEntryPtr asr_skin_entry; - CacheEntryPtr asr_tuneup_entry; + CacheEntryPtr asr_tuneup_entry; //!< Only filled when user selected a saved/downloaded .tuneup mod in SelectorUI. + TuneupDefPtr asr_working_tuneup; //!< Only filled when editing tuneup via Tuning menu. Origin asr_origin = Origin::UNKNOWN; int asr_debugview = 0; //(int)DebugViewType::DEBUGVIEW_NONE; Ogre::UTFString asr_net_username; diff --git a/source/main/resources/CacheSystem.cpp b/source/main/resources/CacheSystem.cpp index 539bf74c02..399206a0b8 100644 --- a/source/main/resources/CacheSystem.cpp +++ b/source/main/resources/CacheSystem.cpp @@ -1520,17 +1520,11 @@ CacheEntryPtr CacheSystem::CreateProject(CreateProjectRequest* request) // Create preliminary cache entry CacheEntryPtr project_entry = new CacheEntry(); - - if (request->cpr_type == CreateProjectRequestType::CREATE_TUNEUP) - { - project_entry->fext = "tuneup"; // Tell modcache what it is. - project_entry->categoryid = CID_TuneupsAuto; // For auto-loading on future spawns of the vehicle. - project_entry->guid = request->cpr_source_entry->guid; // For lookup of tuneups by vehicle GUID. - } - else if (request->cpr_type == CreateProjectRequestType::SAVE_TUNEUP) + + if (request->cpr_type == CreateProjectRequestType::SAVE_TUNEUP) { project_entry->fext = "tuneup"; // Tell modcache what it is. - project_entry->categoryid = CID_TuneupsUser; // For display in modcache + project_entry->categoryid = CID_Tuneups; // For display in modcache project_entry->guid = request->cpr_source_entry->guid; // For lookup of tuneups by vehicle GUID. } else @@ -1547,30 +1541,20 @@ CacheEntryPtr CacheSystem::CreateProject(CreateProjectRequest* request) project_entry->number = static_cast(m_entries.size() + 1); // Let's number mods from 1 this->LoadResource(project_entry); // This fills `entry.resource_group` - if (request->cpr_type == CreateProjectRequestType::CREATE_TUNEUP || - request->cpr_type == CreateProjectRequestType::SAVE_TUNEUP) + if (request->cpr_type == CreateProjectRequestType::SAVE_TUNEUP) { // Tuneup projects don't contain any media, just the .tuneup file which lists addonparts to use. // Prepare the .tuneup document - TuneupDefPtr tuneup; - if (request->cpr_type == CreateProjectRequestType::SAVE_TUNEUP) - { - ROR_ASSERT(request->cpr_source_actor); - ROR_ASSERT(request->cpr_source_actor->getUsedTuneupEntry()); - tuneup = request->cpr_source_actor->getUsedTuneupEntry()->tuneup_def->clone(); - } - else - { - tuneup = new TuneupDef(); - } + ROR_ASSERT(request->cpr_source_actor); + ROR_ASSERT(request->cpr_source_actor->getWorkingTuneupDef()); + + TuneupDefPtr tuneup = request->cpr_source_actor->getWorkingTuneupDef()->clone(); tuneup->guid = request->cpr_source_entry->guid; // For lookup of tuneups by vehicle GUID. tuneup->name = request->cpr_name; tuneup->description = request->cpr_description; tuneup->thumbnail = request->cpr_source_entry->filecachename; tuneup->category_id = (CacheCategoryId)project_entry->categoryid; - - // Write out the .tuneup file. Ogre::DataStreamPtr datastream = Ogre::ResourceGroupManager::getSingleton().createResource(project_entry->fname, project_entry->resource_group); @@ -1668,67 +1652,78 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request) { ROR_ASSERT(request->mpr_target_actor); ROR_ASSERT(request->mpr_target_actor->ar_state != ActorState::DISPOSED); - CacheEntryPtr tuneup_entry = request->mpr_target_actor->getUsedTuneupEntry(); - ROR_ASSERT(tuneup_entry); - ROR_ASSERT(tuneup_entry->tuneup_def); - ROR_ASSERT(tuneup_entry->categoryid == CID_TuneupsAuto); // We never want to modify saved tuneups, only the working (auto-generated) one. + switch (request->mpr_type) { case ModifyProjectRequestType::TUNEUP_USE_ADDONPART_SET: - tuneup_entry->tuneup_def->use_addonparts.insert(request->mpr_subject); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->use_addonparts.insert(request->mpr_subject); break; case ModifyProjectRequestType::TUNEUP_USE_ADDONPART_RESET: - tuneup_entry->tuneup_def->use_addonparts.erase(request->mpr_subject); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->use_addonparts.erase(request->mpr_subject); break; case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_PROP_SET: - tuneup_entry->tuneup_def->force_remove_props.insert(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->force_remove_props.insert(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_PROP_RESET: - tuneup_entry->tuneup_def->force_remove_props.erase(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->force_remove_props.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_SET: - tuneup_entry->tuneup_def->force_remove_flexbodies.insert(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->force_remove_flexbodies.insert(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_FORCEREMOVE_FLEXBODY_RESET: - tuneup_entry->tuneup_def->force_remove_flexbodies.erase(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->force_remove_flexbodies.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_FORCED_WHEEL_SIDE_SET: - tuneup_entry->tuneup_def->force_wheel_sides[request->mpr_subject_id] = (WheelSide)request->mpr_value_int; + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->force_wheel_sides[request->mpr_subject_id] = (WheelSide)request->mpr_value_int; break; case ModifyProjectRequestType::TUNEUP_FORCED_WHEEL_SIDE_RESET: - tuneup_entry->tuneup_def->force_wheel_sides.erase(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->force_wheel_sides.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_PROTECTED_PROP_SET: - tuneup_entry->tuneup_def->protected_props.insert(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->protected_props.insert(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_PROTECTED_PROP_RESET: - tuneup_entry->tuneup_def->protected_props.erase(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->protected_props.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_PROTECTED_FLEXBODY_SET: - tuneup_entry->tuneup_def->protected_flexbodies.insert(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->protected_flexbodies.insert(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_PROTECTED_FLEXBODY_RESET: - tuneup_entry->tuneup_def->protected_flexbodies.erase(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->protected_flexbodies.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_PROTECTED_WHEEL_SET: - tuneup_entry->tuneup_def->protected_wheels.insert(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->protected_wheels.insert(request->mpr_subject_id); break; case ModifyProjectRequestType::TUNEUP_PROTECTED_WHEEL_RESET: - tuneup_entry->tuneup_def->protected_wheels.erase(request->mpr_subject_id); + request->mpr_target_actor->ensureWorkingTuneupDef(); + request->mpr_target_actor->getWorkingTuneupDef()->protected_wheels.erase(request->mpr_subject_id); break; case ModifyProjectRequestType::PROJECT_LOAD_TUNEUP: @@ -1744,44 +1739,21 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request) } this->LoadResource(save_entry); ROR_ASSERT(save_entry->tuneup_def); - - 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(); - tuneup_entry->tuneup_def->wheel_tweaks = save_entry->tuneup_def->wheel_tweaks; - tuneup_entry->tuneup_def->node_tweaks.clear(); - tuneup_entry->tuneup_def->node_tweaks = save_entry->tuneup_def->node_tweaks; + request->mpr_target_actor->getWorkingTuneupDef() = save_entry->tuneup_def->clone(); + ROR_ASSERT(request->mpr_target_actor->getWorkingTuneupDef()); break; } case ModifyProjectRequestType::PROJECT_RESET_TUNEUP: - 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(); - tuneup_entry->tuneup_def->protected_flexbodies.clear(); - tuneup_entry->tuneup_def->protected_props.clear(); - tuneup_entry->tuneup_def->protected_wheels.clear(); + request->mpr_target_actor->ensureWorkingTuneupDef(); + ROR_ASSERT(request->mpr_target_actor->getWorkingTuneupDef()); + request->mpr_target_actor->getWorkingTuneupDef()->reset(); break; default: break; } - // Update the .tuneup file (rembember this is the 'working' aka 'autogenerated' tuneup) - Ogre::DataStreamPtr datastream = Ogre::ResourceGroupManager::getSingleton().createResource(tuneup_entry->fname, tuneup_entry->resource_group, /*overwrite:*/true); - Str<200> header; - header - << "// This is a '.tuneup' mod - it's similar to '.skin' mod but deals with '.addonpart' mods.\n" - << "// See https://github.com/RigsOfRods/rigs-of-rods/pull/3096#issuecomment-1783976601\n\n"; - datastream->write(header.GetBuffer(), header.GetLength()); - RoR::TuneupUtil::ExportTuneup(datastream, tuneup_entry->tuneup_def); - // Create spawn request while actor still exists // Note we don't use `ActorModifyRequest::Type::RELOAD` because we don't need the bundle reloaded. ActorSpawnRequest* srq = new ActorSpawnRequest; @@ -1789,7 +1761,7 @@ void CacheSystem::ModifyProject(ModifyProjectRequest* request) srq->asr_rotation = Ogre::Quaternion(Ogre::Degree(270) - Ogre::Radian(request->mpr_target_actor->getRotation()), Ogre::Vector3::UNIT_Y); srq->asr_config = request->mpr_target_actor->getSectionConfig(); srq->asr_skin_entry = request->mpr_target_actor->getUsedSkinEntry(); - srq->asr_tuneup_entry = tuneup_entry; + srq->asr_working_tuneup = request->mpr_target_actor->getWorkingTuneupDef(); srq->asr_cache_entry = request->mpr_target_actor->getUsedActorEntry(); srq->asr_debugview = (int)request->mpr_target_actor->GetGfxActor()->GetDebugView(); srq->asr_origin = ActorSpawnRequest::Origin::USER; diff --git a/source/main/resources/CacheSystem.h b/source/main/resources/CacheSystem.h index 8bacb4cdaa..a0153cf80e 100644 --- a/source/main/resources/CacheSystem.h +++ b/source/main/resources/CacheSystem.h @@ -61,6 +61,8 @@ class CacheEntry: public RefCountingObject CacheEntry(); ~CacheEntry(); + CacheEntryID_t number; //!< Sequential number, assigned internally, used by Selector-GUI + Ogre::String fpath; //!< filepath relative to the .zip file Ogre::String fname; //!< filename Ogre::String fname_without_uid; //!< filename @@ -78,7 +80,7 @@ class CacheEntry: public RefCountingObject std::string resource_bundle_type; //!< Archive type recognized by OGRE resource system: 'FileSystem' or 'Zip' std::string resource_bundle_path; //!< Path of ZIP or directory which contains the media. Shared between CacheEntries, loaded only once. - int number; //!< Sequential number, assigned internally, used by Selector-GUI + std::time_t filetime; //!< filetime bool deleted; //!< is this mod deleted? int usagecounter; //!< how much it was used already @@ -140,8 +142,7 @@ enum CacheCategoryId CID_None = 0, CID_Projects = 8000, //!< For truck files under 'projects/' directory, to allow listing from editors. - CID_TuneupsAuto = 8100, //!< Auto-created when top menubar 'Tuning' menu is first used. Automatically loaded on next sessions. - CID_TuneupsUser = 8101, //!< Saved by user via GUI, can be loaded via GUI. + CID_Tuneups = 8001, //!< For unsorted tuneup files. CID_Max = 9000, //!< SPECIAL VALUE - Maximum allowed to be present in any mod files. CID_Unsorted = 9990, @@ -203,8 +204,7 @@ enum class CreateProjectRequestType { NONE, DEFAULT, //!< Copy files from source mod. Source mod Determines mod file extension. - CREATE_TUNEUP, //!< Overrides project type to "tuneup", adds a blank .tuneup file with `CID_TuneupAuto`. - SAVE_TUNEUP, //!< Dumps .tuneup file with `CID_TuneupUser` from source actor, will not overwrite existing. + SAVE_TUNEUP, //!< Dumps .tuneup file with `CID_Tuneup` from source actor, will not overwrite existing unless explicitly instructed. }; /// Creates subdirectory in 'My Games\Rigs of Rods\projects', pre-populates it with files and adds modcache entry. @@ -411,8 +411,7 @@ class CacheSystem {5001, _LC("ModCategory", "Night Terrains")}, {CID_Projects, _LC("ModCategory", "Projects")}, - {CID_TuneupsAuto, _LC("ModCategory", "Tuneups (auto-generated)")}, - {CID_TuneupsUser, _LC("ModCategory", "Tuneups (saved by user)")}, + {CID_Tuneups, _LC("ModCategory", "Tuneups")}, // do not use category numbers above 9000! {CID_Unsorted, _LC("ModCategory", "Unsorted")}, diff --git a/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp b/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp index 4d9cc528cc..9779635130 100644 --- a/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp +++ b/source/main/resources/addonpart_fileformat/AddonPartFileFormat.cpp @@ -66,26 +66,34 @@ std::shared_ptr AddonPartUtility::TransformToRigDefModule(Cach if (m_context->isTokKeyword()) { // (ignore 'addonpart_*' directives) - if (m_context->getTokKeyword().find("addonpart_") == std::string::npos) + if (m_context->getTokKeyword().find("addonpart_") != std::string::npos) { - keyword = Parser::IdentifyKeyword(m_context->getTokKeyword()); - switch (keyword) + m_context->seekNextLine(); + continue; + } + + keyword = Parser::IdentifyKeyword(m_context->getTokKeyword()); + if (keyword != Keyword::INVALID) + { + if (keyword == Keyword::SET_MANAGEDMATERIALS_OPTIONS) { - // Handle blocks (data start on next line) - case Keyword::MANAGEDMATERIALS: - case Keyword::PROPS: - case Keyword::FLEXBODIES: - block = keyword; - break; - - // Handle directives (data are on the same line) - case Keyword::SET_MANAGEDMATERIALS_OPTIONS: - this->ProcessDirectiveSetManagedMaterialsOptions(); - break; + this->ProcessDirectiveSetManagedMaterialsOptions(); + m_context->seekNextLine(); + continue; } + else if (keyword == Keyword::MANAGEDMATERIALS + || keyword == Keyword::PROPS + || keyword == Keyword::FLEXBODIES) + { + block = keyword; + m_context->seekNextLine(); + continue; + } + } } - else if (block != Keyword::INVALID && !m_context->isTokComment() && !m_context->isTokLineBreak()) + + if (block != Keyword::INVALID && !m_context->isTokComment() && !m_context->isTokLineBreak()) { switch (block) { diff --git a/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp b/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp index 77b0ab16a6..a787e7e351 100644 --- a/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp +++ b/source/main/resources/tuneup_fileformat/TuneupFileFormat.cpp @@ -2,7 +2,7 @@ This source file is part of Rigs of Rods Copyright 2005-2012 Pierre-Michel Ricordel Copyright 2007-2012 Thomas Fischer - Copyright 2013-2023 Petr Ohlidal + Copyright 2013-2024 Petr Ohlidal For more information, see http://www.rigsofrods.org/ @@ -48,285 +48,408 @@ TuneupDefPtr TuneupDef::clone() ret->author_id = this->author_id ; //int ret->category_id = this->category_id ; //CacheCategoryId - // Modding attributes - 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 - + // addonparts + ret->use_addonparts = this->use_addonparts ; + + // props + ret->protected_props = this->protected_props; + ret->unwanted_props = this->unwanted_props; + ret->force_remove_props = this->force_remove_props; + ret->prop_tweaks = this->prop_tweaks; + + // flexbodies + ret->protected_flexbodies = this->protected_flexbodies; + ret->unwanted_flexbodies = this->unwanted_flexbodies; + ret->force_remove_flexbodies = this->force_remove_flexbodies; + ret->flexbody_tweaks = this->flexbody_tweaks; + + // wheels + ret->protected_wheels = this->protected_wheels; + ret->force_wheel_sides = this->force_wheel_sides; + ret->wheel_tweaks = this->wheel_tweaks; + + // nodes + ret->protected_nodes = this->protected_nodes; + ret->node_tweaks = this->node_tweaks; + return ret; } - // Tweaking helpers - -float RoR::TuneupUtil::getTweakedWheelTireRadius(CacheEntryPtr& tuneup_entry, int wheel_id, float orig_val) +void TuneupDef::reset() { - if (!tuneup_entry) - return orig_val; + // addonparts + this->use_addonparts.clear(); + + // props + this->protected_props.clear(); + this->unwanted_props.clear(); + this->force_remove_props.clear(); + this->prop_tweaks.clear(); + + // flexbodies + this->protected_flexbodies.clear(); + this->unwanted_flexbodies.clear(); + this->force_remove_flexbodies.clear(); + this->flexbody_tweaks.clear(); + + // wheels + this->protected_wheels.clear(); + this->force_wheel_sides.clear(); + this->wheel_tweaks.clear(); + + // nodes + this->protected_nodes.clear(); + this->node_tweaks.clear(); + +} - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->wheel_tweaks.find(wheel_id); - auto endi = tuneup_entry->tuneup_def->wheel_tweaks.end(); - return (itor != endi && itor->second.twt_tire_radius > 0) - ? itor->second.twt_tire_radius : orig_val; +bool TuneupDef::isWheelSideForced(WheelID_t wheelid, WheelSide& out_val) const +{ + auto itor = force_wheel_sides.find(wheelid); + if (itor != force_wheel_sides.end()) + { + out_val = itor->second; + return true; + } + else + { + return false; + } } -float RoR::TuneupUtil::getTweakedWheelRimRadius(CacheEntryPtr& tuneup_entry, int wheel_id, float orig_val) + // Tweaking helpers + +float RoR::TuneupUtil::getTweakedWheelTireRadius(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, float orig_val) { - if (!tuneup_entry) + TuneupWheelTweak* tweak = nullptr; + if (TuneupUtil::isWheelTweaked(tuneup_def, wheel_id, /*out:*/ tweak)) + { + ROR_ASSERT(tweak); + return (tweak->twt_tire_radius > 0) ? tweak->twt_tire_radius : orig_val; + } + else + { return orig_val; - - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->wheel_tweaks.find(wheel_id); - auto endi = tuneup_entry->tuneup_def->wheel_tweaks.end(); - return (itor != endi && itor->second.twt_rim_radius > 0) - ? itor->second.twt_rim_radius : orig_val; + } } -std::string RoR::TuneupUtil::getTweakedWheelMedia(CacheEntryPtr& tuneup_entry, int wheel_id, int media_idx, const std::string& orig_val) +float RoR::TuneupUtil::getTweakedWheelRimRadius(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, float orig_val) { - if (!tuneup_entry) + TuneupWheelTweak* tweak = nullptr; + if (TuneupUtil::isWheelTweaked(tuneup_def, wheel_id, tweak)) + { + ROR_ASSERT(tweak); + return (tweak->twt_rim_radius > 0) ? tweak->twt_rim_radius : orig_val; + } + else + { return orig_val; - - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->wheel_tweaks.find(wheel_id); - auto endi = tuneup_entry->tuneup_def->wheel_tweaks.end(); - return (itor != endi && itor->second.twt_media[media_idx] != "") - ? itor->second.twt_media[media_idx] : orig_val; + } } -std::string RoR::TuneupUtil::getTweakedWheelMediaRG(ActorPtr& actor, int wheel_id, int media_idx) +std::string RoR::TuneupUtil::getTweakedWheelMedia(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, int media_idx, const std::string& orig_val) { - // Check there's a tuneup at all - ROR_ASSERT(actor); - if (!actor->getUsedTuneupEntry()) - return actor->GetGfxActor()->GetResourceGroup(); - - // Check there's a tweak - TuneupDefPtr& doc = actor->getUsedTuneupEntry()->tuneup_def; - ROR_ASSERT(doc); - auto itor = doc->wheel_tweaks.find(wheel_id); - auto endi = doc->wheel_tweaks.end(); - if (itor == endi || itor->second.twt_media[media_idx] == "") - return actor->GetGfxActor()->GetResourceGroup(); - - // Find the tweak addonpart - CacheEntryPtr addonpart_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, itor->second.twt_origin); - if (addonpart_entry) - return addonpart_entry->resource_group; + TuneupWheelTweak* tweak = nullptr; + if (TuneupUtil::isWheelTweaked(tuneup_def, wheel_id, tweak)) + { + ROR_ASSERT(tweak); + ROR_ASSERT(tweak->twt_media.size() > media_idx); + return (tweak->twt_media[media_idx] != "") ? tweak->twt_media[media_idx] : orig_val; + } else { - LOG(fmt::format("[RoR|Tuneup] WARN Addonpart '{}' not found in modcache!", itor->second.twt_origin)); - return actor->GetGfxActor()->GetResourceGroup(); + return orig_val; } } -WheelSide RoR::TuneupUtil::getTweakedWheelSide(CacheEntryPtr& tuneup_entry, int wheel_id, WheelSide orig_val) +std::string RoR::TuneupUtil::getTweakedWheelMediaRG(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, int media_idx, const std::string& orig_val) { - if (!tuneup_entry) - return orig_val; + TuneupWheelTweak* tweak = nullptr; + if (TuneupUtil::isWheelTweaked(tuneup_def, wheel_id, tweak)) + { + ROR_ASSERT(tweak); + ROR_ASSERT(tweak->twt_media.size() > media_idx); + if (tweak->twt_media[media_idx] != "") + { + // Find the tweak addonpart + CacheEntryPtr addonpart_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*'partial':*/false, tweak->twt_origin); + if (addonpart_entry) + { + return addonpart_entry->resource_group; + } + else + { + LOG(fmt::format("[RoR|Tuneup] WARN Addonpart '{}' not found in modcache!", tweak->twt_origin)); + return orig_val; + } + } + } + + return orig_val; + +} - ROR_ASSERT(tuneup_entry->tuneup_def); +WheelSide RoR::TuneupUtil::getTweakedWheelSide(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, WheelSide orig_val) +{ + - // First query the UI overrides + if (tuneup_def) { - 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; + WheelSide forced_side = WheelSide::INVALID; + if (tuneup_def->isWheelSideForced(wheel_id, forced_side)) + { + return forced_side; + } + + TuneupWheelTweak* tweak = nullptr; + if (TuneupUtil::isWheelTweaked(tuneup_def, wheel_id, tweak)) + { + ROR_ASSERT(tweak); + if (tweak->twt_side != WheelSide::INVALID) + { + return tweak->twt_side; + } + } } + + return orig_val; +} + +bool RoR::TuneupUtil::isWheelTweaked(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, TuneupWheelTweak*& out_tweak) +{ - // Then query tweaks + + if (tuneup_def) { - auto itor = tuneup_entry->tuneup_def->wheel_tweaks.find(wheel_id); - auto endi = tuneup_entry->tuneup_def->wheel_tweaks.end(); - if (itor != endi && itor->second.twt_side != WheelSide::INVALID) - return itor->second.twt_side; + auto itor = tuneup_def->wheel_tweaks.find(wheel_id); + if (itor != tuneup_def->wheel_tweaks.end()) + { + out_tweak = &itor->second; + return true; + } } - return orig_val; + return false; } -Ogre::Vector3 RoR::TuneupUtil::getTweakedNodePosition(CacheEntryPtr& tuneup_entry, NodeNum_t nodenum, Ogre::Vector3 orig_val) +Ogre::Vector3 RoR::TuneupUtil::getTweakedNodePosition(TuneupDefPtr& tuneup_def, NodeNum_t nodenum, Ogre::Vector3 orig_val) { - if (!tuneup_entry) + TuneupNodeTweak* tweak = nullptr; + if (TuneupUtil::isNodeTweaked(tuneup_def, nodenum, tweak)) + { + ROR_ASSERT(tweak); + return tweak->tnt_pos; + } + else + { return orig_val; + } +} - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->node_tweaks.find(nodenum); - if (itor == tuneup_entry->tuneup_def->node_tweaks.end()) - return orig_val; +bool RoR::TuneupUtil::isNodeTweaked(TuneupDefPtr& tuneup_def, NodeNum_t nodenum, TuneupNodeTweak*& out_tweak) +{ + if (tuneup_def) + { + auto itor = tuneup_def->node_tweaks.find(nodenum); + if (itor != tuneup_def->node_tweaks.end()) + { + out_tweak = &itor->second; + return true; + } + } - Ogre::Vector3 retval = itor->second.tnt_pos; - ROR_ASSERT(!isnan(retval.x)); - ROR_ASSERT(!isnan(retval.y)); - ROR_ASSERT(!isnan(retval.z)); - return retval; + return false; } // > prop -bool RoR::TuneupUtil::isPropAnyhowRemoved(ActorPtr& actor, PropID_t prop_id) -{ - return actor->getUsedTuneupEntry() - && actor->getUsedTuneupEntry()->tuneup_def - && (actor->getUsedTuneupEntry()->tuneup_def->isPropUnwanted(prop_id) || actor->getUsedTuneupEntry()->tuneup_def->isPropForceRemoved(prop_id)); +bool RoR::TuneupUtil::isPropAnyhowRemoved(TuneupDefPtr& tuneup_def, PropID_t prop_id) +{ + return tuneup_def + && (tuneup_def->isPropUnwanted(prop_id) || tuneup_def->isPropForceRemoved(prop_id)); } -Ogre::Vector3 RoR::TuneupUtil::getTweakedPropOffset(CacheEntryPtr& tuneup_entry, PropID_t prop_id, Ogre::Vector3 orig_val) +Ogre::Vector3 RoR::TuneupUtil::getTweakedPropOffset(TuneupDefPtr& tuneup_def, PropID_t prop_id, Ogre::Vector3 orig_val) { - if (!tuneup_entry) - return orig_val; - - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->prop_tweaks.find(prop_id); - if (itor == tuneup_entry->tuneup_def->prop_tweaks.end()) + TuneupPropTweak* tweak = nullptr; + if (TuneupUtil::isPropTweaked(tuneup_def, prop_id, tweak)) + { + ROR_ASSERT(tweak); + return tweak->tpt_offset; + } + else + { return orig_val; - - Ogre::Vector3 retval = itor->second.tpt_offset; - ROR_ASSERT(!isnan(retval.x)); - ROR_ASSERT(!isnan(retval.y)); - ROR_ASSERT(!isnan(retval.z)); - return retval; + } } -Ogre::Vector3 RoR::TuneupUtil::getTweakedPropRotation(CacheEntryPtr& tuneup_entry, PropID_t prop_id, Ogre::Vector3 orig_val) +Ogre::Vector3 RoR::TuneupUtil::getTweakedPropRotation(TuneupDefPtr& tuneup_def, PropID_t prop_id, Ogre::Vector3 orig_val) { - if (!tuneup_entry) + TuneupPropTweak* tweak = nullptr; + if (TuneupUtil::isPropTweaked(tuneup_def, prop_id, tweak)) + { + ROR_ASSERT(tweak); + return tweak->tpt_rotation; + } + else + { return orig_val; + } +} - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->prop_tweaks.find(prop_id); - if (itor == tuneup_entry->tuneup_def->prop_tweaks.end()) +std::string RoR::TuneupUtil::getTweakedPropMedia(TuneupDefPtr& tuneup_def, PropID_t prop_id, int media_idx, const std::string& orig_val) +{ + TuneupPropTweak* tweak = nullptr; + if (TuneupUtil::isPropTweaked(tuneup_def, prop_id, tweak)) + { + ROR_ASSERT(tweak); + ROR_ASSERT(tweak->tpt_media.size() > media_idx); + return (tweak->tpt_media[media_idx] != "") ? tweak->tpt_media[media_idx] : orig_val; + } + else + { return orig_val; - - Ogre::Vector3 retval = itor->second.tpt_rotation; - ROR_ASSERT(!isnan(retval.x)); - ROR_ASSERT(!isnan(retval.y)); - ROR_ASSERT(!isnan(retval.z)); - return retval; + } } -std::string RoR::TuneupUtil::getTweakedPropMedia(CacheEntryPtr& tuneup_entry, PropID_t prop_id, int media_idx, const std::string& orig_val) +std::string RoR::TuneupUtil::getTweakedPropMediaRG(TuneupDefPtr& tuneup_def, PropID_t prop_id, int media_idx, const std::string& orig_val) { - if (!tuneup_entry) - return orig_val; + TuneupPropTweak* tweak = nullptr; + if (TuneupUtil::isPropTweaked(tuneup_def, prop_id, tweak)) + { + ROR_ASSERT(tweak); + ROR_ASSERT(tweak->tpt_media.size() > media_idx); + if (tweak->tpt_media[media_idx] != "") + { + // Find the tweak addonpart + CacheEntryPtr addonpart_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, tweak->tpt_origin); + if (addonpart_entry) + { + return addonpart_entry->resource_group; + } + else + { + LOG(fmt::format("[RoR|Tuneup] WARN Addonpart '{}' not found in modcache!", tweak->tpt_origin)); + } + } + } - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->prop_tweaks.find(prop_id); - auto endi = tuneup_entry->tuneup_def->prop_tweaks.end(); - return (itor != endi && itor->second.tpt_media[media_idx] != "") - ? itor->second.tpt_media[media_idx] : orig_val; + return orig_val; } -std::string RoR::TuneupUtil::getTweakedPropMediaRG(ActorPtr& actor, PropID_t prop_id, int media_idx, const std::string& orig_val) +bool RoR::TuneupUtil::isPropTweaked(TuneupDefPtr& tuneup_def, PropID_t prop_id, TuneupPropTweak*& out_tweak) { - // Check there's a tuneup at all - ROR_ASSERT(actor); - if (!actor->getUsedTuneupEntry()) - return orig_val; - - // Check there's a tweak - TuneupDefPtr& doc = actor->getUsedTuneupEntry()->tuneup_def; - ROR_ASSERT(doc); - auto itor = doc->prop_tweaks.find(prop_id); - auto endi = doc->prop_tweaks.end(); - if (itor == endi || itor->second.tpt_media[media_idx] == "") - return orig_val; + - // Find the tweak addonpart - CacheEntryPtr addonpart_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, itor->second.tpt_origin); - if (addonpart_entry) - return addonpart_entry->resource_group; - else + if (tuneup_def) { - LOG(fmt::format("[RoR|Tuneup] WARN Addonpart '{}' not found in modcache!", itor->second.tpt_origin)); - return orig_val; + auto itor = tuneup_def->prop_tweaks.find(prop_id); + if (itor != tuneup_def->prop_tweaks.end()) + { + out_tweak = &itor->second; + return true; + } } -} + return false; +} // > flexbody -bool RoR::TuneupUtil::isFlexbodyAnyhowRemoved(ActorPtr& actor, FlexbodyID_t flexbody_id) +bool RoR::TuneupUtil::isFlexbodyAnyhowRemoved(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id) { - return actor->getUsedTuneupEntry() - && actor->getUsedTuneupEntry()->tuneup_def - && (actor->getUsedTuneupEntry()->tuneup_def->isFlexbodyUnwanted(flexbody_id) || actor->getUsedTuneupEntry()->tuneup_def->isFlexbodyForceRemoved(flexbody_id)); + return tuneup_def && + (tuneup_def->isFlexbodyUnwanted(flexbody_id) || tuneup_def->isFlexbodyForceRemoved(flexbody_id)); } -Ogre::Vector3 RoR::TuneupUtil::getTweakedFlexbodyOffset(CacheEntryPtr& tuneup_entry, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val) +Ogre::Vector3 RoR::TuneupUtil::getTweakedFlexbodyOffset(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val) { - if (!tuneup_entry) - return orig_val; - - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->flexbody_tweaks.find(flexbody_id); - if (itor == tuneup_entry->tuneup_def->flexbody_tweaks.end()) + TuneupFlexbodyTweak* tweak = nullptr; + if (TuneupUtil::isFlexbodyTweaked(tuneup_def, flexbody_id, tweak)) + { + ROR_ASSERT(tweak); + return tweak->tft_offset; + } + else + { return orig_val; - - Ogre::Vector3 retval = itor->second.tft_offset; - ROR_ASSERT(!isnan(retval.x)); - ROR_ASSERT(!isnan(retval.y)); - ROR_ASSERT(!isnan(retval.z)); - return retval; + } } -Ogre::Vector3 RoR::TuneupUtil::getTweakedFlexbodyRotation(CacheEntryPtr& tuneup_entry, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val) +Ogre::Vector3 RoR::TuneupUtil::getTweakedFlexbodyRotation(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val) { - if (!tuneup_entry) + TuneupFlexbodyTweak* tweak = nullptr; + if (TuneupUtil::isFlexbodyTweaked(tuneup_def, flexbody_id, tweak)) + { + ROR_ASSERT(tweak); + return tweak->tft_rotation; + } + else + { return orig_val; + } +} - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->flexbody_tweaks.find(flexbody_id); - if (itor == tuneup_entry->tuneup_def->flexbody_tweaks.end()) +std::string RoR::TuneupUtil::getTweakedFlexbodyMedia(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val) +{ + TuneupFlexbodyTweak* tweak = nullptr; + if (TuneupUtil::isFlexbodyTweaked(tuneup_def, flexbody_id, tweak)) + { + ROR_ASSERT(tweak); + return (tweak->tft_media != "") ? tweak->tft_media : orig_val; + } + else + { return orig_val; - - Ogre::Vector3 retval = itor->second.tft_rotation; - ROR_ASSERT(!isnan(retval.x)); - ROR_ASSERT(!isnan(retval.y)); - ROR_ASSERT(!isnan(retval.z)); - return retval; + } } -std::string RoR::TuneupUtil::getTweakedFlexbodyMedia(CacheEntryPtr& tuneup_entry, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val) +std::string RoR::TuneupUtil::getTweakedFlexbodyMediaRG(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val) { - if (!tuneup_entry) - return orig_val; + TuneupFlexbodyTweak* tweak = nullptr; + if (TuneupUtil::isFlexbodyTweaked(tuneup_def, flexbody_id, tweak)) + { + ROR_ASSERT(tweak); + if (tweak->tft_media != "") + { + // Find the tweak addonpart + CacheEntryPtr addonpart_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, tweak->tft_origin); + if (addonpart_entry) + { + return addonpart_entry->resource_group; + } + else + { + LOG(fmt::format("[RoR|Tuneup] WARN Addonpart '{}' not found in modcache!", tweak->tft_origin)); + return orig_val; + } + } + } - ROR_ASSERT(tuneup_entry->tuneup_def); - auto itor = tuneup_entry->tuneup_def->flexbody_tweaks.find(flexbody_id); - auto endi = tuneup_entry->tuneup_def->flexbody_tweaks.end(); - return (itor != endi && itor->second.tft_media != "") - ? itor->second.tft_media : orig_val; + return orig_val; } -std::string RoR::TuneupUtil::getTweakedFlexbodyMediaRG(ActorPtr& actor, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val) +bool RoR::TuneupUtil::isFlexbodyTweaked(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id, TuneupFlexbodyTweak*& out_tweak) { - // Check there's a tuneup at all - ROR_ASSERT(actor); - if (!actor->getUsedTuneupEntry()) - return orig_val; - - // Check there's a tweak - TuneupDefPtr& doc = actor->getUsedTuneupEntry()->tuneup_def; - ROR_ASSERT(doc); - auto itor = doc->flexbody_tweaks.find(flexbody_id); - auto endi = doc->flexbody_tweaks.end(); - if (itor == endi || itor->second.tft_media == "") - return orig_val; + - // Find the tweak addonpart - CacheEntryPtr addonpart_entry = App::GetCacheSystem()->FindEntryByFilename(LT_AddonPart, /*partial:*/false, itor->second.tft_origin); - if (addonpart_entry) - return addonpart_entry->resource_group; - else + if (tuneup_def) { - LOG(fmt::format("[RoR|Tuneup] WARN Addonpart '{}' not found in modcache!", itor->second.tft_origin)); - return orig_val; + auto itor = tuneup_def->flexbody_tweaks.find(flexbody_id); + if (itor != tuneup_def->flexbody_tweaks.end()) + { + out_tweak = &itor->second; + return true; + } } + + return false; } +bool RoR::TuneupUtil::isAddonPartUsed(TuneupDefPtr& tuneup_entry, const std::string& filename) +{ + return tuneup_entry + && tuneup_entry->use_addonparts.find(filename) != tuneup_entry->use_addonparts.end(); +} std::vector RoR::TuneupUtil::ParseTuneups(Ogre::DataStreamPtr& stream) { @@ -421,7 +544,7 @@ void RoR::TuneupUtil::ParseTuneupAttribute(const std::string& line, TuneupDefPtr void RoR::TuneupUtil::ExportTuneup(Ogre::DataStreamPtr& stream, TuneupDefPtr& tuneup) { - Str<2000> buf; + Str buf; buf << tuneup->name << "\n"; buf << "{\n"; diff --git a/source/main/resources/tuneup_fileformat/TuneupFileFormat.h b/source/main/resources/tuneup_fileformat/TuneupFileFormat.h index a7584f28fd..092ad50394 100644 --- a/source/main/resources/tuneup_fileformat/TuneupFileFormat.h +++ b/source/main/resources/tuneup_fileformat/TuneupFileFormat.h @@ -2,7 +2,7 @@ This source file is part of Rigs of Rods Copyright 2005-2012 Pierre-Michel Ricordel Copyright 2007-2012 Thomas Fischer - Copyright 2013-2023 Petr Ohlidal + Copyright 2013-2024 Petr Ohlidal For more information, see http://www.rigsofrods.org/ @@ -21,6 +21,11 @@ #pragma once +/** @file +* @brief The vehicle tuning system; applies addonparts and user overrides to vehicles. +* @see `RoR::ActorSpawner::ConfigureAddonParts()` +*/ + #include "Application.h" #include "CacheSystem.h" #include "RefCountingObject.h" @@ -34,6 +39,8 @@ namespace RoR { +const size_t TUNEUP_BUF_SIZE = 2000; + struct TuneupNodeTweak //!< Data of 'addonpart_tweak_node ' { NodeNum_t tnt_nodenum = NODENUM_INVALID; //!< Arg#1, required @@ -57,7 +64,7 @@ struct TuneupWheelTweak //!< Data of 'addonpart_tweak_wheel struct TuneupPropTweak //!< Data of 'addonpart_tweak_prop ' { PropID_t tpt_prop_id = PROPID_INVALID; - std::string tpt_media[2]; //!< Media1 = prop mesh; Media2: Steering wheel mesh or beacon flare material. + std::array tpt_media; //!< Media1 = prop mesh; Media2: Steering wheel mesh or beacon flare material. Ogre::Vector3 tpt_offset = Ogre::Vector3::ZERO; Ogre::Vector3 tpt_rotation = Ogre::Vector3::ZERO; std::string tpt_origin; //!< Addonpart filename @@ -113,6 +120,7 @@ struct TuneupDef: public RefCountingObject /// @} TuneupDefPtr clone(); + void reset(); /// @name Protection helpers /// @{ @@ -132,7 +140,7 @@ struct TuneupDef: public RefCountingObject /// @{ 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(); } + bool isWheelSideForced(WheelID_t wheelid, WheelSide& out_val) const; /// @} }; @@ -143,36 +151,45 @@ class TuneupUtil static std::vector ParseTuneups(Ogre::DataStreamPtr& stream); static void ExportTuneup(Ogre::DataStreamPtr& stream, TuneupDefPtr& tuneup); + /// @name AddonPart helpers + /// @{ + static bool isAddonPartUsed(TuneupDefPtr& tuneup_entry, const std::string& filename); + /// @} + /// @name Wheel helpers /// @{ - static float getTweakedWheelTireRadius(CacheEntryPtr& tuneup_entry, int wheel_id, float orig_val); - static float getTweakedWheelRimRadius(CacheEntryPtr& tuneup_entry, int wheel_id, float orig_val); - static std::string getTweakedWheelMedia(CacheEntryPtr& tuneup_entry, int wheel_id, int media_idx, const std::string& orig_val); - static std::string getTweakedWheelMediaRG(ActorPtr& actor, int wheel_id, int media_idx); - static WheelSide getTweakedWheelSide(CacheEntryPtr& tuneup_entry, int wheel_id, WheelSide orig_val); + static float getTweakedWheelTireRadius(TuneupDefPtr& tuneup_entry, WheelID_t wheel_id, float orig_val); + static float getTweakedWheelRimRadius(TuneupDefPtr& tuneup_entry, WheelID_t wheel_id, float orig_val); + static std::string getTweakedWheelMedia(TuneupDefPtr& tuneup_entry, WheelID_t wheel_id, int media_idx, const std::string& orig_val); + static std::string getTweakedWheelMediaRG(TuneupDefPtr& tuneup_def, WheelID_t wheel_id, int media_idx, const std::string& orig_val); + static WheelSide getTweakedWheelSide(TuneupDefPtr& tuneup_entry, WheelID_t wheel_id, WheelSide orig_val); + static bool isWheelTweaked(TuneupDefPtr& tuneup_entry, WheelID_t wheel_id, TuneupWheelTweak*& out_tweak); /// @} /// @name Node helpers /// @{ - static Ogre::Vector3 getTweakedNodePosition(CacheEntryPtr& tuneup_entry, NodeNum_t nodenum, Ogre::Vector3 orig_val); + static Ogre::Vector3 getTweakedNodePosition(TuneupDefPtr& tuneup_entry, NodeNum_t nodenum, Ogre::Vector3 orig_val); + static bool isNodeTweaked(TuneupDefPtr& tuneup_entry, NodeNum_t nodenum, TuneupNodeTweak*& out_tweak); /// @} /// @name Prop helpers /// @{ - static bool isPropAnyhowRemoved(ActorPtr& actor, PropID_t prop_id); - static Ogre::Vector3 getTweakedPropOffset(CacheEntryPtr& tuneup_entry, PropID_t prop_id, Ogre::Vector3 orig_val); - static Ogre::Vector3 getTweakedPropRotation(CacheEntryPtr& tuneup_entry, PropID_t prop_id, Ogre::Vector3 orig_val); - static std::string getTweakedPropMedia(CacheEntryPtr& tuneup_entry, PropID_t prop_id, int media_idx, const std::string& orig_val); - static std::string getTweakedPropMediaRG(ActorPtr& actor, PropID_t prop_id, int media_idx, const std::string& orig_val); + static bool isPropAnyhowRemoved(TuneupDefPtr& tuneup_def, PropID_t prop_id); + static Ogre::Vector3 getTweakedPropOffset(TuneupDefPtr& tuneup_entry, PropID_t prop_id, Ogre::Vector3 orig_val); + static Ogre::Vector3 getTweakedPropRotation(TuneupDefPtr& tuneup_entry, PropID_t prop_id, Ogre::Vector3 orig_val); + static std::string getTweakedPropMedia(TuneupDefPtr& tuneup_entry, PropID_t prop_id, int media_idx, const std::string& orig_val); + static std::string getTweakedPropMediaRG(TuneupDefPtr& tuneup_def, PropID_t prop_id, int media_idx, const std::string& orig_val); + static bool isPropTweaked(TuneupDefPtr& tuneup_entry, PropID_t flexbody_id, TuneupPropTweak*& out_tweak); /// @} /// @name Flexbody helpers /// @{ - static bool isFlexbodyAnyhowRemoved(ActorPtr& actor, FlexbodyID_t flexbody_id); - static Ogre::Vector3 getTweakedFlexbodyOffset(CacheEntryPtr& tuneup_entry, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val); - static Ogre::Vector3 getTweakedFlexbodyRotation(CacheEntryPtr& tuneup_entry, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val); - static std::string getTweakedFlexbodyMedia(CacheEntryPtr& tuneup_entry, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val); - static std::string getTweakedFlexbodyMediaRG(ActorPtr& actor, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val); + static bool isFlexbodyAnyhowRemoved(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id); + static Ogre::Vector3 getTweakedFlexbodyOffset(TuneupDefPtr& tuneup_entry, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val); + static Ogre::Vector3 getTweakedFlexbodyRotation(TuneupDefPtr& tuneup_entry, FlexbodyID_t flexbody_id, Ogre::Vector3 orig_val); + static std::string getTweakedFlexbodyMedia(TuneupDefPtr& tuneup_entry, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val); + static std::string getTweakedFlexbodyMediaRG(TuneupDefPtr& tuneup_def, FlexbodyID_t flexbody_id, int media_idx, const std::string& orig_val); + static bool isFlexbodyTweaked(TuneupDefPtr& tuneup_entry, FlexbodyID_t flexbody_id, TuneupFlexbodyTweak*& out_tweak); /// @} private: