feat: Implement lazy loading for dungeon rooms and refactor room graphics handling
- Introduced lazy loading for room data to optimize performance and reduce initial load times. - Updated DungeonEditor and DungeonRoomLoader to handle room graphics rendering directly from room objects. - Refactored methods to accept room references instead of IDs for better clarity and type safety. - Enhanced tab management in the DungeonEditor UI for improved user experience.
This commit is contained in:
@@ -371,7 +371,7 @@ void DungeonEditor::DrawCanvasAndPropertiesPanel() {
|
||||
gui::InputHexByte("Palette", &room.palette);
|
||||
|
||||
if (ImGui::Button("Reload Room Graphics")) {
|
||||
(void)LoadAndRenderRoomGraphics(current_room);
|
||||
(void)LoadAndRenderRoomGraphics(room);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,7 +555,7 @@ void DungeonEditor::DrawDungeonCanvas(int room_id) {
|
||||
SameLine();
|
||||
|
||||
if (Button("Load Room Graphics")) {
|
||||
(void)LoadAndRenderRoomGraphics(room_id);
|
||||
(void)LoadAndRenderRoomGraphics(rooms_[room_id]);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
@@ -701,7 +701,7 @@ void DungeonEditor::DrawDungeonCanvas(int room_id) {
|
||||
if (is_loaded_) {
|
||||
// Automatically load room graphics if not already loaded
|
||||
if (rooms_[room_id].blocks().empty()) {
|
||||
(void)LoadAndRenderRoomGraphics(room_id);
|
||||
(void)LoadAndRenderRoomGraphics(rooms_[room_id]);
|
||||
}
|
||||
|
||||
// Load room objects if not already loaded
|
||||
@@ -761,7 +761,7 @@ void DungeonEditor::UpdateObjectEditor() {
|
||||
|
||||
// Load room graphics if not already loaded (this populates arena buffers)
|
||||
if (room.blocks().empty()) {
|
||||
auto status = LoadAndRenderRoomGraphics(room_id);
|
||||
auto status = LoadAndRenderRoomGraphics(room);
|
||||
if (!status.ok()) {
|
||||
// Log error but continue
|
||||
return;
|
||||
@@ -829,18 +829,15 @@ void DungeonEditor::DrawObjectEditorPanels() {
|
||||
}
|
||||
|
||||
// Legacy method implementations that delegate to components
|
||||
absl::Status DungeonEditor::LoadAndRenderRoomGraphics(int room_id) {
|
||||
if (room_id < 0 || room_id >= rooms_.size()) {
|
||||
return absl::InvalidArgumentError("Invalid room ID");
|
||||
}
|
||||
return room_loader_.LoadAndRenderRoomGraphics(room_id, rooms_[room_id]);
|
||||
absl::Status DungeonEditor::LoadAndRenderRoomGraphics(zelda3::Room& room) {
|
||||
return room_loader_.LoadAndRenderRoomGraphics(room);
|
||||
}
|
||||
|
||||
absl::Status DungeonEditor::ReloadAllRoomGraphics() {
|
||||
return room_loader_.ReloadAllRoomGraphics(rooms_);
|
||||
}
|
||||
|
||||
absl::Status DungeonEditor::UpdateRoomBackgroundLayers(int room_id) {
|
||||
absl::Status DungeonEditor::UpdateRoomBackgroundLayers(int /*room_id*/) {
|
||||
// This method is deprecated - rendering is handled by DungeonRenderer component
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ class DungeonEditor : public Editor {
|
||||
void DrawObjectRenderer();
|
||||
|
||||
// Legacy methods (delegated to components)
|
||||
absl::Status LoadAndRenderRoomGraphics(int room_id);
|
||||
absl::Status LoadAndRenderRoomGraphics(zelda3::Room& room);
|
||||
absl::Status ReloadAllRoomGraphics();
|
||||
absl::Status UpdateRoomBackgroundLayers(int room_id);
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/zelda3/dungeon/room.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze::editor {
|
||||
@@ -28,8 +30,8 @@ absl::Status DungeonEditorV2::Load() {
|
||||
return absl::FailedPreconditionError("ROM not loaded");
|
||||
}
|
||||
|
||||
// Load all rooms using the loader component
|
||||
RETURN_IF_ERROR(room_loader_.LoadAllRooms(rooms_));
|
||||
// Load all rooms using the loader component - DEFERRED for lazy loading
|
||||
// RETURN_IF_ERROR(room_loader_.LoadAllRooms(rooms_));
|
||||
RETURN_IF_ERROR(room_loader_.LoadRoomEntrances(entrances_));
|
||||
|
||||
// Load palette group
|
||||
@@ -106,7 +108,16 @@ void DungeonEditorV2::DrawLayout() {
|
||||
int room_id = active_rooms_[i];
|
||||
bool open = true;
|
||||
|
||||
if (BeginTabItem(absl::StrFormat("Room %03X", room_id).c_str(), &open)) {
|
||||
std::string tab_name_str;
|
||||
const char* tab_name;
|
||||
if (room_id >= 0 && static_cast<size_t>(room_id) < std::size(zelda3::kRoomNames)) {
|
||||
tab_name = zelda3::kRoomNames[room_id].data();
|
||||
} else {
|
||||
tab_name_str = absl::StrFormat("Room %03X", room_id);
|
||||
tab_name = tab_name_str.c_str();
|
||||
}
|
||||
|
||||
if (BeginTabItem(tab_name, &open)) {
|
||||
DrawRoomTab(room_id);
|
||||
EndTabItem();
|
||||
}
|
||||
@@ -116,6 +127,12 @@ void DungeonEditorV2::DrawLayout() {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Add tab button
|
||||
if (ImGui::TabItemButton(ICON_MD_ADD, ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) {
|
||||
OnRoomSelected(room_selector_.current_room_id());
|
||||
}
|
||||
|
||||
EndTabBar();
|
||||
}
|
||||
|
||||
@@ -133,11 +150,21 @@ void DungeonEditorV2::DrawRoomTab(int room_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Lazy load room data
|
||||
if (!rooms_[room_id].IsLoaded()) {
|
||||
auto status = room_loader_.LoadRoom(room_id, rooms_[room_id]);
|
||||
if (!status.ok()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Failed to load room: %s",
|
||||
status.message().data());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Quick controls
|
||||
ImGui::Text("Room %03X", room_id);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Load Graphics")) {
|
||||
(void)room_loader_.LoadAndRenderRoomGraphics(room_id, rooms_[room_id]);
|
||||
(void)room_loader_.LoadAndRenderRoomGraphics(rooms_[room_id]);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Save")) {
|
||||
|
||||
@@ -13,6 +13,20 @@
|
||||
|
||||
namespace yaze::editor {
|
||||
|
||||
absl::Status DungeonRoomLoader::LoadRoom(int room_id, zelda3::Room& room) {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
return absl::FailedPreconditionError("ROM not loaded");
|
||||
}
|
||||
if (room_id < 0 || room_id >= 0x128) {
|
||||
return absl::InvalidArgumentError("Invalid room ID");
|
||||
}
|
||||
|
||||
room = zelda3::LoadRoomFromRom(rom_, room_id);
|
||||
room.LoadObjects();
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status DungeonRoomLoader::LoadAllRooms(std::array<zelda3::Room, 0x128>& rooms) {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
return absl::FailedPreconditionError("ROM not loaded");
|
||||
@@ -26,7 +40,7 @@ absl::Status DungeonRoomLoader::LoadAllRooms(std::array<zelda3::Room, 0x128>& ro
|
||||
static_cast<int>(std::thread::hardware_concurrency()));
|
||||
const int rooms_per_thread = (kTotalRooms + max_concurrency - 1) / max_concurrency;
|
||||
|
||||
util::logf("Loading %d dungeon rooms using %d threads (%d rooms per thread)",
|
||||
LOG_INFO("Dungeon", "Loading %d dungeon rooms using %d threads (%d rooms per thread)",
|
||||
kTotalRooms, max_concurrency, rooms_per_thread);
|
||||
|
||||
// Thread-safe data structures for collecting results
|
||||
@@ -164,7 +178,7 @@ void DungeonRoomLoader::LoadDungeonRoomSize() {
|
||||
}
|
||||
}
|
||||
|
||||
absl::Status DungeonRoomLoader::LoadAndRenderRoomGraphics(int room_id, zelda3::Room& room) {
|
||||
absl::Status DungeonRoomLoader::LoadAndRenderRoomGraphics(zelda3::Room& room) {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
return absl::FailedPreconditionError("ROM not loaded");
|
||||
}
|
||||
@@ -184,8 +198,8 @@ absl::Status DungeonRoomLoader::ReloadAllRoomGraphics(std::array<zelda3::Room, 0
|
||||
}
|
||||
|
||||
// Reload graphics for all rooms
|
||||
for (size_t i = 0; i < rooms.size(); ++i) {
|
||||
auto status = LoadAndRenderRoomGraphics(static_cast<int>(i), rooms[i]);
|
||||
for (auto& room : rooms) {
|
||||
auto status = LoadAndRenderRoomGraphics(room);
|
||||
if (!status.ok()) {
|
||||
continue; // Log error but continue with other rooms
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ class DungeonRoomLoader {
|
||||
explicit DungeonRoomLoader(Rom* rom) : rom_(rom) {}
|
||||
|
||||
// Room loading
|
||||
absl::Status LoadRoom(int room_id, zelda3::Room& room);
|
||||
absl::Status LoadAllRooms(std::array<zelda3::Room, 0x128>& rooms);
|
||||
absl::Status LoadRoomEntrances(std::array<zelda3::RoomEntrance, 0x8C>& entrances);
|
||||
|
||||
@@ -31,7 +32,7 @@ class DungeonRoomLoader {
|
||||
uint64_t GetTotalRoomSize() const { return total_room_size_; }
|
||||
|
||||
// Room graphics
|
||||
absl::Status LoadAndRenderRoomGraphics(int room_id, zelda3::Room& room);
|
||||
absl::Status LoadAndRenderRoomGraphics(zelda3::Room& room);
|
||||
absl::Status ReloadAllRoomGraphics(std::array<zelda3::Room, 0x128>& rooms);
|
||||
|
||||
// Data access
|
||||
|
||||
Reference in New Issue
Block a user