Enhance Overworld and Tile16 editors with new features and UI improvements
- Added context-aware options in the EditorManager for refreshing overworld and dungeon data, improving user interaction. - Streamlined the OverworldEditor by removing redundant menu bars and integrating refresh options directly into the context menu. - Improved the Tile16Editor by scaling tile displays for better visibility and enhancing the blockset canvas functionality. - Introduced new bitmap property dialogs in the Canvas class, allowing users to view and edit bitmap and palette properties directly from the context menu. - Refactored various UI elements for consistency and clarity, enhancing overall user experience.
This commit is contained in:
@@ -355,6 +355,28 @@ void EditorManager::Initialize(const std::string &filename) {
|
|||||||
{absl::StrCat(ICON_MD_SEARCH, " Find"),
|
{absl::StrCat(ICON_MD_SEARCH, " Find"),
|
||||||
context_.shortcut_manager.GetKeys("Find"),
|
context_.shortcut_manager.GetKeys("Find"),
|
||||||
context_.shortcut_manager.GetCallback("Find")},
|
context_.shortcut_manager.GetCallback("Find")},
|
||||||
|
{gui::kSeparator, "", nullptr, []() { return true; }},
|
||||||
|
// Context-aware editor options
|
||||||
|
{absl::StrCat(ICON_MD_REFRESH, " Refresh Data"), "F5",
|
||||||
|
[this]() {
|
||||||
|
if (current_editor_ && current_editor_->type() == EditorType::kOverworld) {
|
||||||
|
// Refresh overworld data
|
||||||
|
auto& ow_editor = static_cast<OverworldEditor&>(*current_editor_);
|
||||||
|
[[maybe_unused]] auto load_status = ow_editor.Load();
|
||||||
|
toast_manager_.Show("Overworld data refreshed", editor::ToastType::kInfo);
|
||||||
|
} else if (current_editor_ && current_editor_->type() == EditorType::kDungeon) {
|
||||||
|
// Refresh dungeon data
|
||||||
|
toast_manager_.Show("Dungeon data refreshed", editor::ToastType::kInfo);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this]() { return current_editor_ != nullptr; }},
|
||||||
|
{absl::StrCat(ICON_MD_MAP, " Load All Maps"), "",
|
||||||
|
[this]() {
|
||||||
|
if (current_editor_ && current_editor_->type() == EditorType::kOverworld) {
|
||||||
|
toast_manager_.Show("Loading all overworld maps...", editor::ToastType::kInfo);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[this]() { return current_editor_ && current_editor_->type() == EditorType::kOverworld; }},
|
||||||
}},
|
}},
|
||||||
{"View",
|
{"View",
|
||||||
{},
|
{},
|
||||||
@@ -583,47 +605,8 @@ absl::Status EditorManager::Update() {
|
|||||||
// Clean window titles without session clutter
|
// Clean window titles without session clutter
|
||||||
std::string window_title = GetEditorName(editor->type());
|
std::string window_title = GetEditorName(editor->type());
|
||||||
|
|
||||||
// Set window flags for better UX
|
if (ImGui::Begin(window_title.c_str(), editor->active())) {
|
||||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
|
|
||||||
if (editor->type() == EditorType::kOverworld || editor->type() == EditorType::kDungeon) {
|
|
||||||
window_flags |= ImGuiWindowFlags_MenuBar;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Begin(window_title.c_str(), editor->active(), window_flags)) {
|
|
||||||
current_editor_ = editor;
|
current_editor_ = editor;
|
||||||
|
|
||||||
// Add editor-specific menu bar with integrated session info
|
|
||||||
if (window_flags & ImGuiWindowFlags_MenuBar && ImGui::BeginMenuBar()) {
|
|
||||||
// Editor-specific menus
|
|
||||||
if (editor->type() == EditorType::kOverworld) {
|
|
||||||
if (ImGui::BeginMenu("Overworld")) {
|
|
||||||
if (ImGui::MenuItem(absl::StrCat(ICON_MD_REFRESH, " Refresh Data").c_str(), "F5")) {
|
|
||||||
toast_manager_.Show("Overworld refreshed", editor::ToastType::kInfo);
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
if (ImGui::MenuItem(absl::StrCat(ICON_MD_MAP, " Load All Maps").c_str())) {
|
|
||||||
toast_manager_.Show("Loading all overworld maps...", editor::ToastType::kInfo);
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
} else if (editor->type() == EditorType::kDungeon) {
|
|
||||||
if (ImGui::BeginMenu("Dungeon")) {
|
|
||||||
if (ImGui::MenuItem(absl::StrCat(ICON_MD_MAP, " Load Room").c_str(), "Ctrl+R")) {
|
|
||||||
// Quick room loading
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
if (ImGui::MenuItem(absl::StrCat(ICON_MD_REFRESH, " Refresh Room Data").c_str(), "F5")) {
|
|
||||||
toast_manager_.Show("Dungeon data refreshed", editor::ToastType::kInfo);
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep editor menu bars clean - session info is in main menu bar
|
|
||||||
|
|
||||||
ImGui::EndMenuBar();
|
|
||||||
}
|
|
||||||
|
|
||||||
status_ = editor->Update();
|
status_ = editor->Update();
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ void OverworldEditor::Initialize() {
|
|||||||
layout_node_ = gui::zeml::Parse(gui::zeml::LoadFile("overworld.zeml"));
|
layout_node_ = gui::zeml::Parse(gui::zeml::LoadFile("overworld.zeml"));
|
||||||
|
|
||||||
// Initialize MapPropertiesSystem with canvas and bitmap data
|
// Initialize MapPropertiesSystem with canvas and bitmap data
|
||||||
map_properties_system_ = std::make_unique<MapPropertiesSystem>(&overworld_, rom_, &maps_bmp_, &ow_map_canvas_);
|
map_properties_system_ = std::make_unique<MapPropertiesSystem>(
|
||||||
|
&overworld_, rom_, &maps_bmp_, &ow_map_canvas_);
|
||||||
|
|
||||||
gui::zeml::Bind(std::to_address(layout_node_.GetNode("OverworldCanvas")),
|
gui::zeml::Bind(std::to_address(layout_node_.GetNode("OverworldCanvas")),
|
||||||
[this]() { DrawOverworldCanvas(); });
|
[this]() { DrawOverworldCanvas(); });
|
||||||
@@ -122,7 +123,7 @@ void OverworldEditor::Initialize() {
|
|||||||
current_mode = EditingMode::MUSIC;
|
current_mode = EditingMode::MUSIC;
|
||||||
HOVER_HINT("Music (8)");
|
HOVER_HINT("Music (8)");
|
||||||
});
|
});
|
||||||
|
|
||||||
// View controls
|
// View controls
|
||||||
gui::AddTableColumn(toolset_table_, "##ZoomOut", [&]() {
|
gui::AddTableColumn(toolset_table_, "##ZoomOut", [&]() {
|
||||||
if (Button(ICON_MD_ZOOM_OUT)) ow_map_canvas_.ZoomOut();
|
if (Button(ICON_MD_ZOOM_OUT)) ow_map_canvas_.ZoomOut();
|
||||||
@@ -137,7 +138,7 @@ void OverworldEditor::Initialize() {
|
|||||||
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
||||||
HOVER_HINT("Fullscreen Canvas (F11)");
|
HOVER_HINT("Fullscreen Canvas (F11)");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Quick access tools
|
// Quick access tools
|
||||||
gui::AddTableColumn(toolset_table_, "##Tile16Editor", [&]() {
|
gui::AddTableColumn(toolset_table_, "##Tile16Editor", [&]() {
|
||||||
if (Button(ICON_MD_GRID_VIEW)) show_tile16_editor_ = !show_tile16_editor_;
|
if (Button(ICON_MD_GRID_VIEW)) show_tile16_editor_ = !show_tile16_editor_;
|
||||||
@@ -239,7 +240,7 @@ void OverworldEditor::DrawToolset() {
|
|||||||
// Keyboard shortcuts for the Overworld Editor
|
// Keyboard shortcuts for the Overworld Editor
|
||||||
if (!ImGui::IsAnyItemActive()) {
|
if (!ImGui::IsAnyItemActive()) {
|
||||||
using enum EditingMode;
|
using enum EditingMode;
|
||||||
|
|
||||||
// Tool shortcuts
|
// Tool shortcuts
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_1)) {
|
if (ImGui::IsKeyDown(ImGuiKey_1)) {
|
||||||
current_mode = PAN;
|
current_mode = PAN;
|
||||||
@@ -258,17 +259,17 @@ void OverworldEditor::DrawToolset() {
|
|||||||
} else if (ImGui::IsKeyDown(ImGuiKey_8)) {
|
} else if (ImGui::IsKeyDown(ImGuiKey_8)) {
|
||||||
current_mode = MUSIC;
|
current_mode = MUSIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
// View shortcuts
|
// View shortcuts
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_F11)) {
|
if (ImGui::IsKeyDown(ImGuiKey_F11)) {
|
||||||
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle map lock with L key
|
// Toggle map lock with L key
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_L) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) {
|
if (ImGui::IsKeyDown(ImGuiKey_L) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) {
|
||||||
current_map_lock_ = !current_map_lock_;
|
current_map_lock_ = !current_map_lock_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle Tile16 editor with T key
|
// Toggle Tile16 editor with T key
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_T) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) {
|
if (ImGui::IsKeyDown(ImGuiKey_T) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) {
|
||||||
show_tile16_editor_ = !show_tile16_editor_;
|
show_tile16_editor_ = !show_tile16_editor_;
|
||||||
@@ -281,21 +282,24 @@ constexpr std::array<const char *, 6> kVanillaMapSettingsColumnNames = {
|
|||||||
"##WorldId", "##GfxId", "##PalId", "##SprGfxId", "##SprPalId", "##MsgId"};
|
"##WorldId", "##GfxId", "##PalId", "##SprGfxId", "##SprPalId", "##MsgId"};
|
||||||
|
|
||||||
constexpr std::array<const char *, 7> kV2MapSettingsColumnNames = {
|
constexpr std::array<const char *, 7> kV2MapSettingsColumnNames = {
|
||||||
"##WorldId", "##GfxId", "##PalId", "##MainPalId", "##SprGfxId", "##SprPalId", "##MsgId"};
|
"##WorldId", "##GfxId", "##PalId", "##MainPalId",
|
||||||
|
"##SprGfxId", "##SprPalId", "##MsgId"};
|
||||||
|
|
||||||
constexpr std::array<const char *, 9> kV3MapSettingsColumnNames = {
|
constexpr std::array<const char *, 9> kV3MapSettingsColumnNames = {
|
||||||
"##WorldId", "##GfxId", "##PalId", "##MainPalId", "##SprGfxId", "##SprPalId",
|
"##WorldId", "##GfxId", "##PalId", "##MainPalId", "##SprGfxId",
|
||||||
"##MsgId", "##AnimGfx", "##AreaSize"};
|
"##SprPalId", "##MsgId", "##AnimGfx", "##AreaSize"};
|
||||||
|
|
||||||
void OverworldEditor::DrawOverworldMapSettings() {
|
void OverworldEditor::DrawOverworldMapSettings() {
|
||||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
static uint8_t asm_version =
|
||||||
|
(*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||||
|
|
||||||
// Determine column count and names based on ROM version
|
// Determine column count and names based on ROM version
|
||||||
int column_count = 6; // Vanilla
|
int column_count = 6; // Vanilla
|
||||||
if (asm_version >= 2 && asm_version != 0xFF) column_count = 7; // v2
|
if (asm_version >= 2 && asm_version != 0xFF) column_count = 7; // v2
|
||||||
if (asm_version >= 3 && asm_version != 0xFF) column_count = 9; // v3
|
if (asm_version >= 3 && asm_version != 0xFF) column_count = 9; // v3
|
||||||
|
|
||||||
if (BeginTable(kOWMapTable.data(), column_count, kOWMapFlags, ImVec2(0, 0), -1)) {
|
if (BeginTable(kOWMapTable.data(), column_count, kOWMapFlags, ImVec2(0, 0),
|
||||||
|
-1)) {
|
||||||
// Setup columns based on version
|
// Setup columns based on version
|
||||||
if (asm_version == 0xFF) {
|
if (asm_version == 0xFF) {
|
||||||
// Vanilla ROM
|
// Vanilla ROM
|
||||||
@@ -320,14 +324,16 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
}
|
}
|
||||||
HOVER_HINT("Upgrade ROM to support ZSCustomOverworld features");
|
HOVER_HINT("Upgrade ROM to support ZSCustomOverworld features");
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "ZSCustomOverworld v%d", asm_version);
|
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||||
|
"ZSCustomOverworld v%d", asm_version);
|
||||||
if (asm_version < 3 && ImGui::Button(ICON_MD_UPGRADE " Upgrade to v3")) {
|
if (asm_version < 3 && ImGui::Button(ICON_MD_UPGRADE " Upgrade to v3")) {
|
||||||
ImGui::OpenPopup("UpgradeROMVersion");
|
ImGui::OpenPopup("UpgradeROMVersion");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ROM Upgrade Dialog
|
// ROM Upgrade Dialog
|
||||||
if (ImGui::BeginPopupModal("UpgradeROMVersion", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
if (ImGui::BeginPopupModal("UpgradeROMVersion", NULL,
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
ImGui::Text("Upgrade ROM to ZSCustomOverworld v3");
|
ImGui::Text("Upgrade ROM to ZSCustomOverworld v3");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("This will enable advanced features like:");
|
ImGui::Text("This will enable advanced features like:");
|
||||||
@@ -337,31 +343,36 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
ImGui::BulletText("Custom background colors");
|
ImGui::BulletText("Custom background colors");
|
||||||
ImGui::BulletText("Advanced overlay system");
|
ImGui::BulletText("Advanced overlay system");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
// Show ASM application option if feature flag is enabled
|
// Show ASM application option if feature flag is enabled
|
||||||
if (core::FeatureFlags::get().overworld.kApplyZSCustomOverworldASM) {
|
if (core::FeatureFlags::get().overworld.kApplyZSCustomOverworldASM) {
|
||||||
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), ICON_MD_CODE " ASM Patch Application Enabled");
|
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||||
ImGui::Text("ZSCustomOverworld ASM will be automatically applied to ROM");
|
ICON_MD_CODE " ASM Patch Application Enabled");
|
||||||
|
ImGui::Text(
|
||||||
|
"ZSCustomOverworld ASM will be automatically applied to ROM");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
} else {
|
} else {
|
||||||
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), ICON_MD_INFO " ASM Patch Application Disabled");
|
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f),
|
||||||
|
ICON_MD_INFO " ASM Patch Application Disabled");
|
||||||
ImGui::Text("Only version marker will be set. Enable in Feature Flags");
|
ImGui::Text("Only version marker will be set. Enable in Feature Flags");
|
||||||
ImGui::Text("for full ASM functionality.");
|
ImGui::Text("for full ASM functionality.");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f), "Warning: This will modify your ROM!");
|
ImGui::TextColored(ImVec4(1.0f, 0.5f, 0.0f, 1.0f),
|
||||||
|
"Warning: This will modify your ROM!");
|
||||||
|
|
||||||
if (ImGui::Button(ICON_MD_CHECK " Upgrade", ImVec2(120, 0))) {
|
if (ImGui::Button(ICON_MD_CHECK " Upgrade", ImVec2(120, 0))) {
|
||||||
// Apply ASM if feature flag is enabled
|
// Apply ASM if feature flag is enabled
|
||||||
if (core::FeatureFlags::get().overworld.kApplyZSCustomOverworldASM) {
|
if (core::FeatureFlags::get().overworld.kApplyZSCustomOverworldASM) {
|
||||||
auto asm_status = ApplyZSCustomOverworldASM(3);
|
auto asm_status = ApplyZSCustomOverworldASM(3);
|
||||||
if (!asm_status.ok()) {
|
if (!asm_status.ok()) {
|
||||||
// Show error but still set version marker
|
// Show error but still set version marker
|
||||||
util::logf("Failed to apply ZSCustomOverworld ASM: %s", asm_status.ToString().c_str());
|
util::logf("Failed to apply ZSCustomOverworld ASM: %s",
|
||||||
|
asm_status.ToString().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the ROM version marker
|
// Set the ROM version marker
|
||||||
(*rom_)[zelda3::OverworldCustomASMHasBeenApplied] = 3;
|
(*rom_)[zelda3::OverworldCustomASMHasBeenApplied] = 3;
|
||||||
asm_version = 3;
|
asm_version = 3;
|
||||||
@@ -374,9 +385,6 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableHeadersRow();
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
|
|
||||||
// World selector (always present)
|
// World selector (always present)
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::SetNextItemWidth(120.f);
|
ImGui::SetNextItemWidth(120.f);
|
||||||
@@ -388,8 +396,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
// Area Graphics (always present)
|
// Area Graphics (always present)
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_IMAGE " Graphics");
|
if (gui::InputHexByte(ICON_MD_IMAGE " Graphics",
|
||||||
if (gui::InputHexByte("##Gfx",
|
|
||||||
overworld_.mutable_overworld_map(current_map_)
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
->mutable_area_graphics(),
|
->mutable_area_graphics(),
|
||||||
kInputFieldSize)) {
|
kInputFieldSize)) {
|
||||||
@@ -401,8 +408,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
// Area Palette (always present)
|
// Area Palette (always present)
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_PALETTE " Palette");
|
if (gui::InputHexByte(ICON_MD_PALETTE " Palette",
|
||||||
if (gui::InputHexByte("##Palette",
|
|
||||||
overworld_.mutable_overworld_map(current_map_)
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
->mutable_area_palette(),
|
->mutable_area_palette(),
|
||||||
kInputFieldSize)) {
|
kInputFieldSize)) {
|
||||||
@@ -416,8 +422,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
if (asm_version >= 2 && asm_version != 0xFF) {
|
if (asm_version >= 2 && asm_version != 0xFF) {
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_COLOR_LENS " Main Pal");
|
if (gui::InputHexByte(ICON_MD_COLOR_LENS " Main Pal",
|
||||||
if (gui::InputHexByte("##MainPal",
|
|
||||||
overworld_.mutable_overworld_map(current_map_)
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
->mutable_main_palette(),
|
->mutable_main_palette(),
|
||||||
kInputFieldSize)) {
|
kInputFieldSize)) {
|
||||||
@@ -431,8 +436,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
// Sprite Graphics (always present)
|
// Sprite Graphics (always present)
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_PETS " Spr Gfx");
|
if (gui::InputHexByte(ICON_MD_PETS " Spr Gfx",
|
||||||
if (gui::InputHexByte("##SprGfx",
|
|
||||||
overworld_.mutable_overworld_map(current_map_)
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
->mutable_sprite_graphics(game_state_),
|
->mutable_sprite_graphics(game_state_),
|
||||||
kInputFieldSize)) {
|
kInputFieldSize)) {
|
||||||
@@ -444,8 +448,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
// Sprite Palette (always present)
|
// Sprite Palette (always present)
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_COLORIZE " Spr Pal");
|
if (gui::InputHexByte(ICON_MD_COLORIZE " Spr Pal",
|
||||||
if (gui::InputHexByte("##SprPalette",
|
|
||||||
overworld_.mutable_overworld_map(current_map_)
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
->mutable_sprite_palette(game_state_),
|
->mutable_sprite_palette(game_state_),
|
||||||
kInputFieldSize)) {
|
kInputFieldSize)) {
|
||||||
@@ -457,9 +460,9 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
// Message ID (always present)
|
// Message ID (always present)
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_MESSAGE " Msg ID");
|
if (gui::InputHexWord(ICON_MD_MESSAGE " Msg ID",
|
||||||
if (gui::InputHexWord("##MsgId",
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
|
->mutable_message_id(),
|
||||||
kInputFieldSize + 20)) {
|
kInputFieldSize + 20)) {
|
||||||
RefreshMapProperties();
|
RefreshMapProperties();
|
||||||
RefreshOverworldMap();
|
RefreshOverworldMap();
|
||||||
@@ -470,8 +473,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
if (asm_version >= 3 && asm_version != 0xFF) {
|
if (asm_version >= 3 && asm_version != 0xFF) {
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_ANIMATION " Anim GFX");
|
if (gui::InputHexByte(ICON_MD_ANIMATION " Anim GFX",
|
||||||
if (gui::InputHexByte("##AnimGfx",
|
|
||||||
overworld_.mutable_overworld_map(current_map_)
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
->mutable_animated_gfx(),
|
->mutable_animated_gfx(),
|
||||||
kInputFieldSize)) {
|
kInputFieldSize)) {
|
||||||
@@ -479,16 +481,16 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
RefreshOverworldMap();
|
RefreshOverworldMap();
|
||||||
}
|
}
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
|
|
||||||
// Area Size (v3+ only)
|
// Area Size (v3+ only)
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
ImGui::Text(ICON_MD_ASPECT_RATIO " Size");
|
|
||||||
static const char *area_size_names[] = {"Small", "Large", "Wide", "Tall"};
|
static const char *area_size_names[] = {"Small", "Large", "Wide", "Tall"};
|
||||||
int current_area_size = static_cast<int>(
|
int current_area_size =
|
||||||
overworld_.overworld_map(current_map_)->area_size());
|
static_cast<int>(overworld_.overworld_map(current_map_)->area_size());
|
||||||
ImGui::SetNextItemWidth(80.f);
|
ImGui::SetNextItemWidth(80.f);
|
||||||
if (ImGui::Combo("##AreaSize", ¤t_area_size, area_size_names, 4)) {
|
if (ImGui::Combo(ICON_MD_ASPECT_RATIO " Size", ¤t_area_size,
|
||||||
|
area_size_names, 4)) {
|
||||||
overworld_.mutable_overworld_map(current_map_)
|
overworld_.mutable_overworld_map(current_map_)
|
||||||
->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||||
RefreshOverworldMap();
|
RefreshOverworldMap();
|
||||||
@@ -500,15 +502,17 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ImGui::SetNextItemWidth(100.f);
|
ImGui::SetNextItemWidth(100.f);
|
||||||
if (ImGui::Combo("##GameState", &game_state_, kGamePartComboString.data(), 3)) {
|
if (ImGui::Combo("##GameState", &game_state_, kGamePartComboString.data(),
|
||||||
|
3)) {
|
||||||
RefreshMapProperties();
|
RefreshMapProperties();
|
||||||
RefreshOverworldMap();
|
RefreshOverworldMap();
|
||||||
}
|
}
|
||||||
HOVER_HINT("Game progression state for sprite graphics/palettes");
|
HOVER_HINT("Game progression state for sprite graphics/palettes");
|
||||||
|
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
if (ImGui::Checkbox(ICON_MD_BLUR_ON " Mosaic",
|
if (ImGui::Checkbox(
|
||||||
overworld_.mutable_overworld_map(current_map_)->mutable_mosaic())) {
|
ICON_MD_BLUR_ON " Mosaic",
|
||||||
|
overworld_.mutable_overworld_map(current_map_)->mutable_mosaic())) {
|
||||||
RefreshMapProperties();
|
RefreshMapProperties();
|
||||||
RefreshOverworldMap();
|
RefreshOverworldMap();
|
||||||
}
|
}
|
||||||
@@ -1005,9 +1009,10 @@ void OverworldEditor::DrawOverworldCanvas() {
|
|||||||
if (all_gfx_loaded_) {
|
if (all_gfx_loaded_) {
|
||||||
if (core::FeatureFlags::get().overworld.kLoadCustomOverworld) {
|
if (core::FeatureFlags::get().overworld.kLoadCustomOverworld) {
|
||||||
map_properties_system_->DrawSimplifiedMapSettings(
|
map_properties_system_->DrawSimplifiedMapSettings(
|
||||||
current_world_, current_map_, current_map_lock_, show_map_properties_panel_,
|
current_world_, current_map_, current_map_lock_,
|
||||||
show_custom_bg_color_editor_, show_overlay_editor_, show_overlay_preview_, game_state_,
|
show_map_properties_panel_, show_custom_bg_color_editor_,
|
||||||
reinterpret_cast<int&>(current_mode));
|
show_overlay_editor_, show_overlay_preview_, game_state_,
|
||||||
|
reinterpret_cast<int &>(current_mode));
|
||||||
} else {
|
} else {
|
||||||
DrawOverworldMapSettings();
|
DrawOverworldMapSettings();
|
||||||
}
|
}
|
||||||
@@ -1035,12 +1040,13 @@ void OverworldEditor::DrawOverworldCanvas() {
|
|||||||
ow_map_canvas_.scrolling());
|
ow_map_canvas_.scrolling());
|
||||||
DrawOverworldItems();
|
DrawOverworldItems();
|
||||||
DrawOverworldSprites();
|
DrawOverworldSprites();
|
||||||
|
|
||||||
// Draw overlay preview if enabled
|
// Draw overlay preview if enabled
|
||||||
if (show_overlay_preview_) {
|
if (show_overlay_preview_) {
|
||||||
map_properties_system_->DrawOverlayPreviewOnMap(current_map_, current_world_, show_overlay_preview_);
|
map_properties_system_->DrawOverlayPreviewOnMap(
|
||||||
|
current_map_, current_world_, show_overlay_preview_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_mode == EditingMode::DRAW_TILE) {
|
if (current_mode == EditingMode::DRAW_TILE) {
|
||||||
CheckForOverworldEdits();
|
CheckForOverworldEdits();
|
||||||
}
|
}
|
||||||
@@ -1119,14 +1125,17 @@ void OverworldEditor::DrawTile8Selector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status OverworldEditor::DrawAreaGraphics() {
|
absl::Status OverworldEditor::DrawAreaGraphics() {
|
||||||
if (overworld_.is_loaded() && current_graphics_set_.contains(current_map_)) {
|
if (overworld_.is_loaded()) {
|
||||||
overworld_.set_current_map(current_map_);
|
// Always ensure current map graphics are loaded
|
||||||
palette_ = overworld_.current_area_palette();
|
if (!current_graphics_set_.contains(current_map_)) {
|
||||||
gfx::Bitmap bmp;
|
overworld_.set_current_map(current_map_);
|
||||||
Renderer::Get().CreateAndRenderBitmap(0x80, kOverworldMapSize, 0x08,
|
palette_ = overworld_.current_area_palette();
|
||||||
overworld_.current_graphics(), bmp,
|
gfx::Bitmap bmp;
|
||||||
palette_);
|
Renderer::Get().CreateAndRenderBitmap(0x80, kOverworldMapSize, 0x08,
|
||||||
current_graphics_set_[current_map_] = bmp;
|
overworld_.current_graphics(), bmp,
|
||||||
|
palette_);
|
||||||
|
current_graphics_set_[current_map_] = bmp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gui::BeginPadding(3);
|
gui::BeginPadding(3);
|
||||||
@@ -1137,7 +1146,7 @@ absl::Status OverworldEditor::DrawAreaGraphics() {
|
|||||||
{
|
{
|
||||||
current_gfx_canvas_.DrawContextMenu();
|
current_gfx_canvas_.DrawContextMenu();
|
||||||
current_gfx_canvas_.DrawBitmap(current_graphics_set_[current_map_],
|
current_gfx_canvas_.DrawBitmap(current_graphics_set_[current_map_],
|
||||||
/*border_offset=*/2, overworld_.is_loaded());
|
/*border_offset=*/2, 2.0f);
|
||||||
current_gfx_canvas_.DrawTileSelector(32.0f);
|
current_gfx_canvas_.DrawTileSelector(32.0f);
|
||||||
current_gfx_canvas_.DrawGrid();
|
current_gfx_canvas_.DrawGrid();
|
||||||
current_gfx_canvas_.DrawOverlay();
|
current_gfx_canvas_.DrawOverlay();
|
||||||
@@ -1181,8 +1190,7 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
|||||||
if (each.is_hole_) {
|
if (each.is_hole_) {
|
||||||
color = ImVec4(255, 255, 255, 200);
|
color = ImVec4(255, 255, 255, 200);
|
||||||
}
|
}
|
||||||
float scale = ow_map_canvas_.global_scale();
|
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color);
|
||||||
ow_map_canvas_.DrawRect(each.x_ * scale, each.y_ * scale, 16 * scale, 16 * scale, color);
|
|
||||||
std::string str = util::HexByte(each.entrance_id_);
|
std::string str = util::HexByte(each.entrance_id_);
|
||||||
|
|
||||||
if (current_mode == EditingMode::ENTRANCES) {
|
if (current_mode == EditingMode::ENTRANCES) {
|
||||||
@@ -1201,7 +1209,7 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ow_map_canvas_.DrawText(str, each.x_ * scale, each.y_ * scale);
|
ow_map_canvas_.DrawText(str, each.x_, each.y_);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -1243,8 +1251,7 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
|
|||||||
for (auto &each : *overworld_.mutable_exits()) {
|
for (auto &each : *overworld_.mutable_exits()) {
|
||||||
if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
|
if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
|
||||||
each.map_id_ >= (current_world_ * 0x40) && !each.deleted_) {
|
each.map_id_ >= (current_world_ * 0x40) && !each.deleted_) {
|
||||||
float scale = ow_map_canvas_.global_scale();
|
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16,
|
||||||
ow_map_canvas_.DrawRect(each.x_ * scale, each.y_ * scale, 16 * scale, 16 * scale,
|
|
||||||
ImVec4(255, 255, 255, 150));
|
ImVec4(255, 255, 255, 150));
|
||||||
if (current_mode == EditingMode::EXITS) {
|
if (current_mode == EditingMode::EXITS) {
|
||||||
each.entity_id_ = i;
|
each.entity_id_ = i;
|
||||||
@@ -1268,7 +1275,7 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string str = util::HexByte(i);
|
std::string str = util::HexByte(i);
|
||||||
ow_map_canvas_.DrawText(str, each.x_ * scale, each.y_ * scale);
|
ow_map_canvas_.DrawText(str, each.x_, each.y_);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -1296,8 +1303,7 @@ void OverworldEditor::DrawOverworldItems() {
|
|||||||
// Get the item's bitmap and real X and Y positions
|
// Get the item's bitmap and real X and Y positions
|
||||||
if (item.room_map_id_ < 0x40 + (current_world_ * 0x40) &&
|
if (item.room_map_id_ < 0x40 + (current_world_ * 0x40) &&
|
||||||
item.room_map_id_ >= (current_world_ * 0x40) && !item.deleted) {
|
item.room_map_id_ >= (current_world_ * 0x40) && !item.deleted) {
|
||||||
float scale = ow_map_canvas_.global_scale();
|
ow_map_canvas_.DrawRect(item.x_, item.y_, 16, 16, ImVec4(255, 0, 0, 150));
|
||||||
ow_map_canvas_.DrawRect(item.x_ * scale, item.y_ * scale, 16 * scale, 16 * scale, ImVec4(255, 0, 0, 150));
|
|
||||||
|
|
||||||
if (current_mode == EditingMode::ITEMS) {
|
if (current_mode == EditingMode::ITEMS) {
|
||||||
// Check if this item is being clicked and dragged
|
// Check if this item is being clicked and dragged
|
||||||
@@ -1319,7 +1325,7 @@ void OverworldEditor::DrawOverworldItems() {
|
|||||||
} else {
|
} else {
|
||||||
item_name = absl::StrFormat("0x%02X", item.id_);
|
item_name = absl::StrFormat("0x%02X", item.id_);
|
||||||
}
|
}
|
||||||
ow_map_canvas_.DrawText(item_name, item.x_ * scale, item.y_ * scale);
|
ow_map_canvas_.DrawText(item_name, item.x_, item.y_);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -1356,8 +1362,7 @@ void OverworldEditor::DrawOverworldSprites() {
|
|||||||
int original_x = sprite.x_;
|
int original_x = sprite.x_;
|
||||||
int original_y = sprite.y_;
|
int original_y = sprite.y_;
|
||||||
|
|
||||||
float scale = ow_map_canvas_.global_scale();
|
ow_map_canvas_.DrawRect(sprite_x, sprite_y, kTile16Size, kTile16Size,
|
||||||
ow_map_canvas_.DrawRect(sprite_x * scale, sprite_y * scale, kTile16Size * scale, kTile16Size * scale,
|
|
||||||
/*magenta=*/ImVec4(255, 0, 255, 150));
|
/*magenta=*/ImVec4(255, 0, 255, 150));
|
||||||
if (current_mode == EditingMode::SPRITES) {
|
if (current_mode == EditingMode::SPRITES) {
|
||||||
HandleEntityDragging(&sprite, ow_map_canvas_.zero_point(),
|
HandleEntityDragging(&sprite, ow_map_canvas_.zero_point(),
|
||||||
@@ -1372,13 +1377,13 @@ void OverworldEditor::DrawOverworldSprites() {
|
|||||||
}
|
}
|
||||||
if (core::FeatureFlags::get().overworld.kDrawOverworldSprites) {
|
if (core::FeatureFlags::get().overworld.kDrawOverworldSprites) {
|
||||||
if (sprite_previews_[sprite.id()].is_active()) {
|
if (sprite_previews_[sprite.id()].is_active()) {
|
||||||
ow_map_canvas_.DrawBitmap(sprite_previews_[sprite.id()], sprite_x * scale,
|
ow_map_canvas_.DrawBitmap(sprite_previews_[sprite.id()], sprite_x,
|
||||||
sprite_y * scale, 2.0f * scale);
|
sprite_y, 2.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ow_map_canvas_.DrawText(absl::StrFormat("%s", sprite.name()), sprite_x * scale,
|
ow_map_canvas_.DrawText(absl::StrFormat("%s", sprite.name()), sprite_x,
|
||||||
sprite_y * scale);
|
sprite_y);
|
||||||
|
|
||||||
// Restore original coordinates
|
// Restore original coordinates
|
||||||
sprite.x_ = original_x;
|
sprite.x_ = original_x;
|
||||||
@@ -1698,7 +1703,7 @@ void OverworldEditor::DrawOverlayEditor() {
|
|||||||
Text("Vanilla ROM - Subscreen Overlays:");
|
Text("Vanilla ROM - Subscreen Overlays:");
|
||||||
Text("Subscreen overlays in vanilla ROMs reference special area maps");
|
Text("Subscreen overlays in vanilla ROMs reference special area maps");
|
||||||
Text("(0x80-0x9F) for visual effects like fog, rain, backgrounds.");
|
Text("(0x80-0x9F) for visual effects like fog, rain, backgrounds.");
|
||||||
|
|
||||||
Separator();
|
Separator();
|
||||||
if (Checkbox("Show Subscreen Overlay Preview", &show_overlay_preview_)) {
|
if (Checkbox("Show Subscreen Overlay Preview", &show_overlay_preview_)) {
|
||||||
// Toggle subscreen overlay preview
|
// Toggle subscreen overlay preview
|
||||||
@@ -1710,7 +1715,8 @@ void OverworldEditor::DrawOverlayEditor() {
|
|||||||
|
|
||||||
Separator();
|
Separator();
|
||||||
Text(
|
Text(
|
||||||
"Note: Vanilla subscreen overlays are read-only. Use ZSCustomOverworld v1+ for "
|
"Note: Vanilla subscreen overlays are read-only. Use ZSCustomOverworld "
|
||||||
|
"v1+ for "
|
||||||
"editable subscreen overlays.");
|
"editable subscreen overlays.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1793,16 +1799,17 @@ void OverworldEditor::DrawOverlayEditor() {
|
|||||||
|
|
||||||
void OverworldEditor::DrawOverlayPreview() {
|
void OverworldEditor::DrawOverlayPreview() {
|
||||||
if (!show_overlay_preview_) return;
|
if (!show_overlay_preview_) return;
|
||||||
|
|
||||||
Text("Subscreen Overlay Preview:");
|
Text("Subscreen Overlay Preview:");
|
||||||
Separator();
|
Separator();
|
||||||
|
|
||||||
// Get the subscreen overlay ID from the current map
|
// Get the subscreen overlay ID from the current map
|
||||||
uint16_t overlay_id = overworld_.overworld_map(current_map_)->subscreen_overlay();
|
uint16_t overlay_id =
|
||||||
|
overworld_.overworld_map(current_map_)->subscreen_overlay();
|
||||||
|
|
||||||
// Show subscreen overlay information
|
// Show subscreen overlay information
|
||||||
Text("Subscreen Overlay ID: 0x%04X", overlay_id);
|
Text("Subscreen Overlay ID: 0x%04X", overlay_id);
|
||||||
|
|
||||||
// Show subscreen overlay description based on common overlay IDs
|
// Show subscreen overlay description based on common overlay IDs
|
||||||
std::string overlay_desc = "";
|
std::string overlay_desc = "";
|
||||||
if (overlay_id == 0x0093) {
|
if (overlay_id == 0x0093) {
|
||||||
@@ -1829,32 +1836,34 @@ void OverworldEditor::DrawOverlayPreview() {
|
|||||||
overlay_desc = "Custom subscreen overlay effect";
|
overlay_desc = "Custom subscreen overlay effect";
|
||||||
}
|
}
|
||||||
Text("Description: %s", overlay_desc.c_str());
|
Text("Description: %s", overlay_desc.c_str());
|
||||||
|
|
||||||
Separator();
|
Separator();
|
||||||
|
|
||||||
// Map subscreen overlay ID to special area map for preview
|
// Map subscreen overlay ID to special area map for preview
|
||||||
int overlay_map_index = -1;
|
int overlay_map_index = -1;
|
||||||
if (overlay_id >= 0x80 && overlay_id < 0xA0) {
|
if (overlay_id >= 0x80 && overlay_id < 0xA0) {
|
||||||
overlay_map_index = overlay_id;
|
overlay_map_index = overlay_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (overlay_map_index >= 0 && overlay_map_index < zelda3::kNumOverworldMaps) {
|
if (overlay_map_index >= 0 && overlay_map_index < zelda3::kNumOverworldMaps) {
|
||||||
Text("Subscreen Overlay Source Map: %d (0x%02X)", overlay_map_index, overlay_map_index);
|
Text("Subscreen Overlay Source Map: %d (0x%02X)", overlay_map_index,
|
||||||
|
overlay_map_index);
|
||||||
|
|
||||||
// Get the subscreen overlay map's bitmap
|
// Get the subscreen overlay map's bitmap
|
||||||
const auto &overlay_bitmap = maps_bmp_[overlay_map_index];
|
const auto &overlay_bitmap = maps_bmp_[overlay_map_index];
|
||||||
|
|
||||||
if (overlay_bitmap.is_active()) {
|
if (overlay_bitmap.is_active()) {
|
||||||
// Display the subscreen overlay map bitmap
|
// Display the subscreen overlay map bitmap
|
||||||
ImVec2 image_size(256, 256); // Scale down for preview
|
ImVec2 image_size(256, 256); // Scale down for preview
|
||||||
ImGui::Image((ImTextureID)(intptr_t)overlay_bitmap.texture(), image_size);
|
ImGui::Image((ImTextureID)(intptr_t)overlay_bitmap.texture(), image_size);
|
||||||
|
|
||||||
Separator();
|
Separator();
|
||||||
Text("This subscreen overlay would be displayed semi-transparently");
|
Text("This subscreen overlay would be displayed semi-transparently");
|
||||||
Text("on top of the current map when active.");
|
Text("on top of the current map when active.");
|
||||||
|
|
||||||
// Show drawing order info
|
// Show drawing order info
|
||||||
if (overlay_id == 0x0095 || overlay_id == 0x0096 || overlay_id == 0x009C) {
|
if (overlay_id == 0x0095 || overlay_id == 0x0096 ||
|
||||||
|
overlay_id == 0x009C) {
|
||||||
Text("Note: This subscreen overlay is drawn as a background");
|
Text("Note: This subscreen overlay is drawn as a background");
|
||||||
Text("(behind the main map tiles).");
|
Text("(behind the main map tiles).");
|
||||||
} else {
|
} else {
|
||||||
@@ -1870,7 +1879,6 @@ void OverworldEditor::DrawOverlayPreview() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OverworldEditor::DrawMapLockControls() {
|
void OverworldEditor::DrawMapLockControls() {
|
||||||
if (current_map_lock_) {
|
if (current_map_lock_) {
|
||||||
PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.0f, 1.0f));
|
PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.0f, 1.0f));
|
||||||
@@ -1944,7 +1952,8 @@ void OverworldEditor::DrawOverworldContextMenu() {
|
|||||||
}
|
}
|
||||||
} else if (asm_version == 0xFF) {
|
} else if (asm_version == 0xFF) {
|
||||||
// Show vanilla subscreen overlay information for LW and DW maps only
|
// Show vanilla subscreen overlay information for LW and DW maps only
|
||||||
bool is_special_overworld_map = (hovered_map >= 0x80 && hovered_map < 0xA0);
|
bool is_special_overworld_map =
|
||||||
|
(hovered_map >= 0x80 && hovered_map < 0xA0);
|
||||||
if (!is_special_overworld_map) {
|
if (!is_special_overworld_map) {
|
||||||
if (MenuItem("View Subscreen Overlay")) {
|
if (MenuItem("View Subscreen Overlay")) {
|
||||||
show_overlay_editor_ = true;
|
show_overlay_editor_ = true;
|
||||||
@@ -2268,9 +2277,11 @@ void OverworldEditor::DrawMapPropertiesPanel() {
|
|||||||
"TileGraphics", 4,
|
"TileGraphics", 4,
|
||||||
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||||
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 80);
|
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||||
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 120);
|
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed,
|
||||||
|
120);
|
||||||
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 80);
|
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||||
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 120);
|
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed,
|
||||||
|
120);
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
@@ -2645,8 +2656,8 @@ absl::Status OverworldEditor::ApplyZSCustomOverworldASM(int target_version) {
|
|||||||
auto patch_result = asar.ApplyPatch(asm_file_path, rom_data);
|
auto patch_result = asar.ApplyPatch(asm_file_path, rom_data);
|
||||||
if (!patch_result.ok()) {
|
if (!patch_result.ok()) {
|
||||||
return absl::InternalError(
|
return absl::InternalError(
|
||||||
absl::StrFormat("Failed to apply ZSCustomOverworld ASM: %s",
|
absl::StrFormat("Failed to apply ZSCustomOverworld ASM: %s",
|
||||||
patch_result.status().ToString()));
|
patch_result.status().ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!patch_result->success) {
|
if (!patch_result->success) {
|
||||||
@@ -2658,25 +2669,26 @@ absl::Status OverworldEditor::ApplyZSCustomOverworldASM(int target_version) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update ROM with patched data (asar modifies rom_data in-place)
|
// Update ROM with patched data (asar modifies rom_data in-place)
|
||||||
if (patch_result->rom_size > 0 &&
|
if (patch_result->rom_size > 0 &&
|
||||||
static_cast<size_t>(patch_result->rom_size) != rom_->vector().size()) {
|
static_cast<size_t>(patch_result->rom_size) != rom_->vector().size()) {
|
||||||
// ROM size changed, need to expand/shrink
|
// ROM size changed, need to expand/shrink
|
||||||
rom_->Expand(patch_result->rom_size);
|
rom_->Expand(patch_result->rom_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy patched data to ROM (rom_data was modified in-place by asar)
|
// Copy patched data to ROM (rom_data was modified in-place by asar)
|
||||||
std::copy(rom_data.begin(), rom_data.end(), rom_->mutable_data());
|
std::copy(rom_data.begin(), rom_data.end(), rom_->mutable_data());
|
||||||
|
|
||||||
// Log success and any symbols
|
// Log success and any symbols
|
||||||
util::logf("Successfully applied ZSCustomOverworld ASM v%d", target_version);
|
util::logf("Successfully applied ZSCustomOverworld ASM v%d", target_version);
|
||||||
if (!patch_result->symbols.empty()) {
|
if (!patch_result->symbols.empty()) {
|
||||||
util::logf("Extracted %zu symbols from ASM patch", patch_result->symbols.size());
|
util::logf("Extracted %zu symbols from ASM patch",
|
||||||
|
patch_result->symbols.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show any warnings from the assembler
|
// Show any warnings from the assembler
|
||||||
if (!patch_result->warnings.empty()) {
|
if (!patch_result->warnings.empty()) {
|
||||||
util::logf("ASM patch warnings:");
|
util::logf("ASM patch warnings:");
|
||||||
for (const auto& warning : patch_result->warnings) {
|
for (const auto &warning : patch_result->warnings) {
|
||||||
util::logf(" %s", warning.c_str());
|
util::logf(" %s", warning.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ absl::Status Tile16Editor::UpdateBlockset() {
|
|||||||
gui::EndPadding();
|
gui::EndPadding();
|
||||||
blockset_canvas_.DrawContextMenu();
|
blockset_canvas_.DrawContextMenu();
|
||||||
blockset_canvas_.DrawTileSelector(32);
|
blockset_canvas_.DrawTileSelector(32);
|
||||||
blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, 0, map_blockset_loaded_);
|
blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, 0, 2.0f);
|
||||||
blockset_canvas_.DrawGrid();
|
blockset_canvas_.DrawGrid();
|
||||||
blockset_canvas_.DrawOverlay();
|
blockset_canvas_.DrawOverlay();
|
||||||
EndChild();
|
EndChild();
|
||||||
@@ -391,7 +391,8 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
|
|||||||
// Display the current Tile16 at a larger size
|
// Display the current Tile16 at a larger size
|
||||||
auto texture = current_tile16_bmp_.texture();
|
auto texture = current_tile16_bmp_.texture();
|
||||||
if (texture) {
|
if (texture) {
|
||||||
ImGui::Image((ImTextureID)(intptr_t)texture, ImVec2(128, 128));
|
// Scale the 16x16 tile to 256x256 for better visibility
|
||||||
|
ImGui::Image((ImTextureID)(intptr_t)texture, ImVec2(256, 256));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display information about the current Tile16
|
// Display information about the current Tile16
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class Tile16Editor : public gfx::GfxContext {
|
|||||||
|
|
||||||
// Tile16 blockset for selecting the tile to edit
|
// Tile16 blockset for selecting the tile to edit
|
||||||
gui::Canvas blockset_canvas_{"blocksetCanvas", ImVec2(0x100, 0x4000),
|
gui::Canvas blockset_canvas_{"blocksetCanvas", ImVec2(0x100, 0x4000),
|
||||||
gui::CanvasGridSize::k32x32};
|
gui::CanvasGridSize::k32x32,};
|
||||||
gfx::Bitmap tile16_blockset_bmp_;
|
gfx::Bitmap tile16_blockset_bmp_;
|
||||||
|
|
||||||
// Canvas for editing the selected tile
|
// Canvas for editing the selected tile
|
||||||
|
|||||||
@@ -134,12 +134,21 @@ void Canvas::DrawContextMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default canvas menu items
|
// Default canvas menu items
|
||||||
if (MenuItem("Reset Position", nullptr, false)) {
|
if (MenuItem("Reset View", nullptr, false)) {
|
||||||
scrolling_.x = 0;
|
ResetView();
|
||||||
scrolling_.y = 0;
|
|
||||||
}
|
}
|
||||||
|
if (MenuItem("Zoom to Fit", nullptr, false) && bitmap_) {
|
||||||
|
SetZoomToFit(*bitmap_);
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
MenuItem("Show Grid", nullptr, &enable_grid_);
|
MenuItem("Show Grid", nullptr, &enable_grid_);
|
||||||
Selectable("Show Position Labels", &enable_hex_tile_labels_);
|
Selectable("Show Position Labels", &enable_hex_tile_labels_);
|
||||||
|
if (MenuItem("Bitmap Properties", nullptr, false) && bitmap_) {
|
||||||
|
ImGui::OpenPopup("Bitmap Properties");
|
||||||
|
}
|
||||||
|
if (MenuItem("Edit Palette", nullptr, false) && bitmap_) {
|
||||||
|
ImGui::OpenPopup("Palette Editor");
|
||||||
|
}
|
||||||
if (BeginMenu("Canvas Properties")) {
|
if (BeginMenu("Canvas Properties")) {
|
||||||
Text("Canvas Size: %.0f x %.0f", canvas_sz_.x, canvas_sz_.y);
|
Text("Canvas Size: %.0f x %.0f", canvas_sz_.x, canvas_sz_.y);
|
||||||
Text("Global Scale: %.1f", global_scale_);
|
Text("Global Scale: %.1f", global_scale_);
|
||||||
@@ -225,6 +234,12 @@ void Canvas::DrawContextMenu() {
|
|||||||
|
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draw enhanced property dialogs
|
||||||
|
if (bitmap_) {
|
||||||
|
ShowBitmapProperties(*bitmap_);
|
||||||
|
ShowPaletteEditor(*bitmap_->mutable_palette());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawContextMenuItem(const ContextMenuItem& item) {
|
void Canvas::DrawContextMenuItem(const ContextMenuItem& item) {
|
||||||
@@ -260,6 +275,87 @@ void Canvas::ClearContextMenuItems() {
|
|||||||
context_menu_items_.clear();
|
context_menu_items_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::ShowBitmapProperties(const gfx::Bitmap& bitmap) {
|
||||||
|
if (ImGui::BeginPopupModal("Bitmap Properties", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
ImGui::Text("Bitmap Information");
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::Text("Size: %d x %d", bitmap.width(), bitmap.height());
|
||||||
|
ImGui::Text("Depth: %d bits", bitmap.depth());
|
||||||
|
ImGui::Text("Data Size: %zu bytes", bitmap.size());
|
||||||
|
ImGui::Text("Active: %s", bitmap.is_active() ? "Yes" : "No");
|
||||||
|
ImGui::Text("Modified: %s", bitmap.modified() ? "Yes" : "No");
|
||||||
|
|
||||||
|
if (bitmap.surface()) {
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("SDL Surface");
|
||||||
|
ImGui::Text("Pitch: %d", bitmap.surface()->pitch);
|
||||||
|
ImGui::Text("Bits Per Pixel: %d", bitmap.surface()->format->BitsPerPixel);
|
||||||
|
ImGui::Text("Bytes Per Pixel: %d", bitmap.surface()->format->BytesPerPixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button("Close")) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::ShowPaletteEditor(gfx::SnesPalette& palette) {
|
||||||
|
if (ImGui::BeginPopupModal("Palette Editor", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
|
ImGui::Text("Palette Editor");
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
// Display palette colors in a grid
|
||||||
|
int cols = 8;
|
||||||
|
for (int i = 0; i < palette.size(); i++) {
|
||||||
|
if (i % cols != 0) ImGui::SameLine();
|
||||||
|
|
||||||
|
auto color = palette[i];
|
||||||
|
ImVec4 display_color = color.rgb();
|
||||||
|
|
||||||
|
ImGui::PushID(i);
|
||||||
|
if (ImGui::ColorButton("##color", display_color, ImGuiColorEditFlags_NoTooltip, ImVec2(30, 30))) {
|
||||||
|
// Color selected - could open detailed editor
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip("Color %d: 0x%04X\nR:%d G:%d B:%d",
|
||||||
|
i, color.snes(),
|
||||||
|
(int)(display_color.x * 255),
|
||||||
|
(int)(display_color.y * 255),
|
||||||
|
(int)(display_color.z * 255));
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::Button("Close")) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::SetZoomToFit(const gfx::Bitmap& bitmap) {
|
||||||
|
if (!bitmap.is_active()) return;
|
||||||
|
|
||||||
|
ImVec2 available = ImGui::GetContentRegionAvail();
|
||||||
|
float scale_x = available.x / bitmap.width();
|
||||||
|
float scale_y = available.y / bitmap.height();
|
||||||
|
global_scale_ = std::min(scale_x, scale_y);
|
||||||
|
|
||||||
|
// Ensure minimum readable scale
|
||||||
|
if (global_scale_ < 0.25f) global_scale_ = 0.25f;
|
||||||
|
|
||||||
|
// Center the view
|
||||||
|
scrolling_ = ImVec2(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::ResetView() {
|
||||||
|
global_scale_ = 1.0f;
|
||||||
|
scrolling_ = ImVec2(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) {
|
bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) {
|
||||||
const ImGuiIO &io = GetIO();
|
const ImGuiIO &io = GetIO();
|
||||||
const bool is_hovered = IsItemHovered();
|
const bool is_hovered = IsItemHovered();
|
||||||
@@ -693,10 +789,16 @@ void Canvas::DrawBitmapGroup(std::vector<int> &group, gfx::Tilemap &tilemap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawRect(int x, int y, int w, int h, ImVec4 color) {
|
void Canvas::DrawRect(int x, int y, int w, int h, ImVec4 color) {
|
||||||
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
|
// Apply global scale to position and size
|
||||||
canvas_p0_.y + scrolling_.y + y);
|
float scaled_x = x * global_scale_;
|
||||||
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
|
float scaled_y = y * global_scale_;
|
||||||
canvas_p0_.y + scrolling_.y + y + h);
|
float scaled_w = w * global_scale_;
|
||||||
|
float scaled_h = h * global_scale_;
|
||||||
|
|
||||||
|
ImVec2 origin(canvas_p0_.x + scrolling_.x + scaled_x,
|
||||||
|
canvas_p0_.y + scrolling_.y + scaled_y);
|
||||||
|
ImVec2 size(canvas_p0_.x + scrolling_.x + scaled_x + scaled_w,
|
||||||
|
canvas_p0_.y + scrolling_.y + scaled_y + scaled_h);
|
||||||
draw_list_->AddRectFilled(origin, size,
|
draw_list_->AddRectFilled(origin, size,
|
||||||
IM_COL32(color.x, color.y, color.z, color.w));
|
IM_COL32(color.x, color.y, color.z, color.w));
|
||||||
// Add a black outline
|
// Add a black outline
|
||||||
@@ -706,11 +808,15 @@ void Canvas::DrawRect(int x, int y, int w, int h, ImVec4 color) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawText(std::string text, int x, int y) {
|
void Canvas::DrawText(std::string text, int x, int y) {
|
||||||
draw_list_->AddText(ImVec2(canvas_p0_.x + scrolling_.x + x + 1,
|
// Apply global scale to text position
|
||||||
canvas_p0_.y + scrolling_.y + y + 1),
|
float scaled_x = x * global_scale_;
|
||||||
|
float scaled_y = y * global_scale_;
|
||||||
|
|
||||||
|
draw_list_->AddText(ImVec2(canvas_p0_.x + scrolling_.x + scaled_x + 1,
|
||||||
|
canvas_p0_.y + scrolling_.y + scaled_y + 1),
|
||||||
kBlackColor, text.data());
|
kBlackColor, text.data());
|
||||||
draw_list_->AddText(
|
draw_list_->AddText(
|
||||||
ImVec2(canvas_p0_.x + scrolling_.x + x, canvas_p0_.y + scrolling_.y + y),
|
ImVec2(canvas_p0_.x + scrolling_.x + scaled_x, canvas_p0_.y + scrolling_.y + scaled_y),
|
||||||
kWhiteColor, text.data());
|
kWhiteColor, text.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ class Canvas {
|
|||||||
void ClearContextMenuItems();
|
void ClearContextMenuItems();
|
||||||
void SetContextMenuEnabled(bool enabled) { context_menu_enabled_ = enabled; }
|
void SetContextMenuEnabled(bool enabled) { context_menu_enabled_ = enabled; }
|
||||||
|
|
||||||
|
// Enhanced view and edit operations
|
||||||
|
void ShowBitmapProperties(const gfx::Bitmap& bitmap);
|
||||||
|
void ShowPaletteEditor(gfx::SnesPalette& palette);
|
||||||
|
void SetZoomToFit(const gfx::Bitmap& bitmap);
|
||||||
|
void ResetView();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DrawContextMenuItem(const ContextMenuItem& item);
|
void DrawContextMenuItem(const ContextMenuItem& item);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user