diff --git a/source/main/physics/ActorSpawner.cpp b/source/main/physics/ActorSpawner.cpp index 9fa6a7c89e..9264e610fa 100644 --- a/source/main/physics/ActorSpawner.cpp +++ b/source/main/physics/ActorSpawner.cpp @@ -379,7 +379,7 @@ void ActorSpawner::InitializeRig() m_flex_factory.CheckAndLoadFlexbodyCache(); - m_placeholder_managedmat = Ogre::MaterialManager::getSingleton().getByName("rigsofrods/managedmaterial-placeholder"); // Built-in + m_managedmat_placeholder_template = Ogre::MaterialManager::getSingleton().getByName("rigsofrods/managedmaterial-placeholder"); // Built-in m_apply_simple_materials = App::diag_simple_materials->getBool(); if (m_apply_simple_materials) @@ -1634,6 +1634,7 @@ void ActorSpawner::ProcessProp(RigDef::Prop & def) prop.pp_scene_node = App::GetGfxScene()->GetSceneManager()->getRootSceneNode()->createChildSceneNode(); const std::string instance_name = this->ComposeName("PropEntity", prop_index); + LOG(fmt::format("[RoR] DBG ActorSpawner::ProcessProp(): creating MeshObject '{}' in RG '{}'", def.mesh_name, resource_group)); prop.pp_mesh_obj = new MeshObject(def.mesh_name, resource_group, instance_name, prop.pp_scene_node); prop.pp_mesh_obj->setCastShadows(true); // Orig code {{ prop.pp_mesh_obj->setCastShadows(shadowmode != 0); }}, shadowmode has default value 1 and changes with undocumented directive 'set_shadows' @@ -2291,7 +2292,7 @@ Ogre::MaterialPtr ActorSpawner::InstantiateManagedMaterial(Ogre::String const & return Ogre::MaterialPtr(); } - return src_mat->clone(clone_name, true, m_custom_resource_group); + return src_mat->clone(clone_name); } void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) @@ -2324,12 +2325,17 @@ void ActorSpawner::ProcessManagedMaterial(RigDef::ManagedMaterial & def) def.specular_map = ""; } - // Create temporary placeholder + // Create fallback placeholders // This is necessary to load meshes with original material names (= unchanged managed mat names) // - if not found, OGRE substitutes them with 'BaseWhite' which breaks subsequent processing. if (Ogre::MaterialManager::getSingleton().getByName(def.name, resource_group).isNull()) { - m_placeholder_managedmat->clone(def.name, /*changeGroup=*/true, resource_group); + LOG(fmt::format("[RoR] DBG ActorSpawner::ProcessManagedMaterial(): Creating placeholder for material '{}' in group '{}'", def.name, resource_group)); + m_managedmat_placeholder_template->clone(def.name, /*changeGroup=*/true, resource_group); + } + else + { + LOG(fmt::format("[RoR] DBG ActorSpawner::ProcessManagedMaterial(): Placeholder already exists: '{}' in group '{}'", def.name, resource_group)); } std::string custom_name = def.name + ACTOR_ID_TOKEN + TOSTRING(m_actor->ar_instance_id); diff --git a/source/main/physics/ActorSpawner.h b/source/main/physics/ActorSpawner.h index 897b5aade4..53abbb43e1 100644 --- a/source/main/physics/ActorSpawner.h +++ b/source/main/physics/ActorSpawner.h @@ -473,7 +473,7 @@ class ActorSpawner RoR::FlexFactory m_flex_factory; std::map m_material_substitutions; //!< Maps original material names (shared) to their actor-specific substitutes; There's 1 substitute per 1 material, regardless of user count. std::map m_managed_materials; - Ogre::MaterialPtr m_placeholder_managedmat; + Ogre::MaterialPtr m_managedmat_placeholder_template; //!< An 'error marker' material (bright magenta) to generate managedmaterial placeholders from. Ogre::SceneNode* m_particles_parent_scenenode; Ogre::MaterialPtr m_cab_trans_material; Ogre::MaterialPtr m_simple_material_base; diff --git a/source/main/resources/CacheSystem.cpp b/source/main/resources/CacheSystem.cpp index 10c3e887ce..f2af9b09bd 100644 --- a/source/main/resources/CacheSystem.cpp +++ b/source/main/resources/CacheSystem.cpp @@ -1209,6 +1209,20 @@ bool CacheSystem::CheckResourceLoaded(Ogre::String & filename, Ogre::String& gro return false; } +std::string CacheSystem::ComposeResourceGroupName(const CacheEntryPtr& entry) +{ + // Compose group name as "{bundle }", + // where 'local path' means under 'Documenst\My Games\Rigs of Rods'. + // ----------------------------------------------------------------- + std::string name = entry->resource_bundle_path; // Start from full path + size_t prefix_pos = name.find_first_not_of(App::sys_user_dir->getStr()); + if (prefix_pos != std::string::npos) + { + name = name.substr(App::sys_user_dir->getStr().length()); + } + return fmt::format("{{bundle {}}}", name); +} + void CacheSystem::LoadResource(CacheEntryPtr& entry) { if (!entry) @@ -1220,7 +1234,7 @@ void CacheSystem::LoadResource(CacheEntryPtr& entry) return; } - Ogre::String group = "bundle " + entry->resource_bundle_path; // Compose group name from full path. + Ogre::String group = CacheSystem::ComposeResourceGroupName(entry); bool readonly = entry->resource_bundle_type == "Zip"; // Make "FileSystem" (directory) bundles writable. Default is read-only. bool recursive = false; diff --git a/source/main/resources/CacheSystem.h b/source/main/resources/CacheSystem.h index d42c981aa9..b60b2375d9 100644 --- a/source/main/resources/CacheSystem.h +++ b/source/main/resources/CacheSystem.h @@ -280,6 +280,7 @@ class CacheSystem static Ogre::String StripUIDfromString(Ogre::String uidstr); static Ogre::String StripSHA1fromString(Ogre::String sha1str); + static std::string ComposeResourceGroupName(const CacheEntryPtr& entry); void ParseZipArchives(Ogre::String group); bool ParseKnownFiles(Ogre::String group); // returns true if no known files are found