Skip to content

Commit

Permalink
🎮 Reloading vehicle now reloads resources, too.
Browse files Browse the repository at this point in the history
Reloading vehicle will now reload all it's resources (materials, textures, everything). Works both for zipped and unzipped mods.

The compromise is that all spawned actors using the same resource bundle must be deleted.
  • Loading branch information
ohlidalp authored and Petr Ohlídal committed Mar 13, 2021
1 parent a9c7924 commit 28f2cf0
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 22 deletions.
3 changes: 2 additions & 1 deletion source/main/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,13 @@ enum MsgType
// GUI
MSG_GUI_OPEN_MENU_REQUESTED,
MSG_GUI_CLOSE_MENU_REQUESTED,
MSG_GUI_OPEN_SELECTOR_REQUESTED, //!< Payload = LoaderType* (owner), Description = GUID | empty
MSG_GUI_OPEN_SELECTOR_REQUESTED, //!< Payload = LoaderType* (owner), Description = GUID | empty
MSG_GUI_CLOSE_SELECTOR_REQUESTED,
// Editing
MSG_EDI_MODIFY_GROUNDMODEL_REQUESTED, //!< Payload = ground_model_t* (weak)
MSG_EDI_ENTER_TERRN_EDITOR_REQUESTED,
MSG_EDI_LEAVE_TERRN_EDITOR_REQUESTED,
MSG_EDI_RELOAD_BUNDLE_REQUESTED, //!< Payload = RoR::CacheEntry* (weak)
};

enum class AppState
Expand Down
31 changes: 12 additions & 19 deletions source/main/GameContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,28 +279,21 @@ void GameContext::ModifyActor(ActorModifyRequest& rq)
return;
}

auto reload_pos = rq.amr_actor->getPosition();
auto reload_dir = Ogre::Quaternion(Ogre::Degree(270) - Ogre::Radian(m_player_actor->getRotation()), Ogre::Vector3::UNIT_Y);
auto debug_view = rq.amr_actor->GetGfxActor()->GetDebugView();
auto asr_config = rq.amr_actor->GetSectionConfig();
auto used_skin = rq.amr_actor->GetUsedSkin();

reload_pos.y = m_player_actor->GetMinHeight();

m_prev_player_actor = nullptr;
this->DeleteActor(rq.amr_actor);
entry->actor_def = nullptr;
App::GetCacheSystem()->ReLoadResource(*entry);

// Create spawn request while actor still exists
ActorSpawnRequest* srq = new ActorSpawnRequest;
srq->asr_position = reload_pos;
srq->asr_rotation = reload_dir;
srq->asr_config = asr_config;
srq->asr_skin_entry = used_skin;
srq->asr_position = Ogre::Vector3(rq.amr_actor->getPosition().x, rq.amr_actor->GetMinHeight(), rq.amr_actor->getPosition().z);
srq->asr_rotation = Ogre::Quaternion(Ogre::Degree(270) - Ogre::Radian(rq.amr_actor->getRotation()), Ogre::Vector3::UNIT_Y);
srq->asr_config = rq.amr_actor->GetSectionConfig();
srq->asr_skin_entry = rq.amr_actor->GetUsedSkin();
srq->asr_cache_entry= entry;
srq->asr_debugview = (int)debug_view;
srq->asr_debugview = (int)rq.amr_actor->GetGfxActor()->GetDebugView();
srq->asr_origin = ActorSpawnRequest::Origin::USER;
this->PushMessage(Message(MSG_SIM_SPAWN_ACTOR_REQUESTED, (void*)srq));

// This deletes all actors using the resource bundle, including the one we're reloading.
this->PushMessage(Message(MSG_EDI_RELOAD_BUNDLE_REQUESTED, (void*)entry));

// Load our actor again, but only after all actors are deleted.
this->ChainMessage(Message(MSG_SIM_SPAWN_ACTOR_REQUESTED, (void*)srq));
}
}

Expand Down
27 changes: 27 additions & 0 deletions source/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,33 @@ int main(int argc, char *argv[])
}
break;

case MSG_EDI_RELOAD_BUNDLE_REQUESTED:
{
// To reload the bundle, it's resource group must be destroyed and re-created. All actors using it must be deleted.
CacheEntry* entry = reinterpret_cast<CacheEntry*>(m.payload);
bool all_clear = true;
for (Actor* actor: App::GetGameContext()->GetActorManager()->GetActors())
{
if (actor->GetGfxActor()->GetResourceGroup() == entry->resource_group)
{
App::GetGameContext()->PushMessage(Message(MSG_SIM_DELETE_ACTOR_REQUESTED, actor));
all_clear = false;
}
}

if (all_clear)
{
// Nobody uses the RG anymore -> destroy and re-create it.
App::GetCacheSystem()->ReLoadResource(*entry);
}
else
{
// Re-post the same message again so that it's message chain is executed later.
App::GetGameContext()->PushMessage(m);
failed_m = true;
}
}

default:;
}

Expand Down
28 changes: 26 additions & 2 deletions source/main/resources/CacheSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1116,8 +1116,32 @@ void CacheSystem::ReLoadResource(CacheEntry& t)
return; // Not loaded - nothing to do
}

Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup(t.resource_group);
t.resource_group = "";
// IMPORTANT! No actors must use the bundle while reloading, use RoR::MsgType::MSG_EDI_RELOAD_BUNDLE_REQUESTED

this->UnLoadResource(t);
this->LoadResource(t); // Will create the same resource group again
}

void CacheSystem::UnLoadResource(CacheEntry& t)
{
if (t.resource_group == "")
{
return; // Not loaded - nothing to do
}

// IMPORTANT! No actors must use the bundle after reloading, use RoR::MsgType::MSG_EDI_RELOAD_BUNDLE_REQUESTED

std::string resource_group = t.resource_group; // Keep local copy, the CacheEntry will be blanked!
for (CacheEntry& i_entry: m_entries)
{
if (i_entry.resource_group == resource_group)
{
i_entry.actor_def = nullptr; // Delete cached truck file - force reload from disk
i_entry.resource_group = ""; // Mark as unloaded
}
}

Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup(resource_group);
this->LoadResource(t); // Will create the same resource group again
}

Expand Down
1 change: 1 addition & 0 deletions source/main/resources/CacheSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ class CacheSystem : public ZeroedMemoryAllocator
bool CheckResourceLoaded(Ogre::String &in_out_filename); //!< Finds + loads the associated resource bundle if not already done.
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(CacheEntry& t); //!< Forces reloading the associated bundle.
void UnLoadResource(CacheEntry& t); //!< Unloads associated bundle, destroying all spawned actors.

const std::vector<CacheEntry> &GetEntries() const { return m_entries; }
const CategoryIdNameMap &GetCategories() const { return m_categories; }
Expand Down

0 comments on commit 28f2cf0

Please # to comment.