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"),
|
||||
context_.shortcut_manager.GetKeys("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",
|
||||
{},
|
||||
@@ -583,47 +605,8 @@ absl::Status EditorManager::Update() {
|
||||
// Clean window titles without session clutter
|
||||
std::string window_title = GetEditorName(editor->type());
|
||||
|
||||
// Set window flags for better UX
|
||||
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)) {
|
||||
if (ImGui::Begin(window_title.c_str(), editor->active())) {
|
||||
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();
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
@@ -45,7 +45,8 @@ void OverworldEditor::Initialize() {
|
||||
layout_node_ = gui::zeml::Parse(gui::zeml::LoadFile("overworld.zeml"));
|
||||
|
||||
// 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")),
|
||||
[this]() { DrawOverworldCanvas(); });
|
||||
@@ -122,7 +123,7 @@ void OverworldEditor::Initialize() {
|
||||
current_mode = EditingMode::MUSIC;
|
||||
HOVER_HINT("Music (8)");
|
||||
});
|
||||
|
||||
|
||||
// View controls
|
||||
gui::AddTableColumn(toolset_table_, "##ZoomOut", [&]() {
|
||||
if (Button(ICON_MD_ZOOM_OUT)) ow_map_canvas_.ZoomOut();
|
||||
@@ -137,7 +138,7 @@ void OverworldEditor::Initialize() {
|
||||
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
||||
HOVER_HINT("Fullscreen Canvas (F11)");
|
||||
});
|
||||
|
||||
|
||||
// Quick access tools
|
||||
gui::AddTableColumn(toolset_table_, "##Tile16Editor", [&]() {
|
||||
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
|
||||
if (!ImGui::IsAnyItemActive()) {
|
||||
using enum EditingMode;
|
||||
|
||||
|
||||
// Tool shortcuts
|
||||
if (ImGui::IsKeyDown(ImGuiKey_1)) {
|
||||
current_mode = PAN;
|
||||
@@ -258,17 +259,17 @@ void OverworldEditor::DrawToolset() {
|
||||
} else if (ImGui::IsKeyDown(ImGuiKey_8)) {
|
||||
current_mode = MUSIC;
|
||||
}
|
||||
|
||||
|
||||
// View shortcuts
|
||||
if (ImGui::IsKeyDown(ImGuiKey_F11)) {
|
||||
overworld_canvas_fullscreen_ = !overworld_canvas_fullscreen_;
|
||||
}
|
||||
|
||||
|
||||
// Toggle map lock with L key
|
||||
if (ImGui::IsKeyDown(ImGuiKey_L) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) {
|
||||
current_map_lock_ = !current_map_lock_;
|
||||
}
|
||||
|
||||
|
||||
// Toggle Tile16 editor with T key
|
||||
if (ImGui::IsKeyDown(ImGuiKey_T) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl)) {
|
||||
show_tile16_editor_ = !show_tile16_editor_;
|
||||
@@ -281,21 +282,24 @@ constexpr std::array<const char *, 6> kVanillaMapSettingsColumnNames = {
|
||||
"##WorldId", "##GfxId", "##PalId", "##SprGfxId", "##SprPalId", "##MsgId"};
|
||||
|
||||
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 = {
|
||||
"##WorldId", "##GfxId", "##PalId", "##MainPalId", "##SprGfxId", "##SprPalId",
|
||||
"##MsgId", "##AnimGfx", "##AreaSize"};
|
||||
"##WorldId", "##GfxId", "##PalId", "##MainPalId", "##SprGfxId",
|
||||
"##SprPalId", "##MsgId", "##AnimGfx", "##AreaSize"};
|
||||
|
||||
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
|
||||
int column_count = 6; // Vanilla
|
||||
int column_count = 6; // Vanilla
|
||||
if (asm_version >= 2 && asm_version != 0xFF) column_count = 7; // v2
|
||||
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
|
||||
if (asm_version == 0xFF) {
|
||||
// Vanilla ROM
|
||||
@@ -320,14 +324,16 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
}
|
||||
HOVER_HINT("Upgrade ROM to support ZSCustomOverworld features");
|
||||
} 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")) {
|
||||
ImGui::OpenPopup("UpgradeROMVersion");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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::Separator();
|
||||
ImGui::Text("This will enable advanced features like:");
|
||||
@@ -337,31 +343,36 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
ImGui::BulletText("Custom background colors");
|
||||
ImGui::BulletText("Advanced overlay system");
|
||||
ImGui::Separator();
|
||||
|
||||
|
||||
// Show ASM application option if feature flag is enabled
|
||||
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::Text("ZSCustomOverworld ASM will be automatically applied to ROM");
|
||||
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f),
|
||||
ICON_MD_CODE " ASM Patch Application Enabled");
|
||||
ImGui::Text(
|
||||
"ZSCustomOverworld ASM will be automatically applied to ROM");
|
||||
ImGui::Separator();
|
||||
} 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("for full ASM functionality.");
|
||||
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))) {
|
||||
// Apply ASM if feature flag is enabled
|
||||
if (core::FeatureFlags::get().overworld.kApplyZSCustomOverworldASM) {
|
||||
auto asm_status = ApplyZSCustomOverworldASM(3);
|
||||
if (!asm_status.ok()) {
|
||||
// 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
|
||||
(*rom_)[zelda3::OverworldCustomASMHasBeenApplied] = 3;
|
||||
asm_version = 3;
|
||||
@@ -374,9 +385,6 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::TableHeadersRow();
|
||||
ImGui::TableNextRow();
|
||||
|
||||
// World selector (always present)
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(120.f);
|
||||
@@ -388,8 +396,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
// Area Graphics (always present)
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_IMAGE " Graphics");
|
||||
if (gui::InputHexByte("##Gfx",
|
||||
if (gui::InputHexByte(ICON_MD_IMAGE " Graphics",
|
||||
overworld_.mutable_overworld_map(current_map_)
|
||||
->mutable_area_graphics(),
|
||||
kInputFieldSize)) {
|
||||
@@ -401,8 +408,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
// Area Palette (always present)
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_PALETTE " Palette");
|
||||
if (gui::InputHexByte("##Palette",
|
||||
if (gui::InputHexByte(ICON_MD_PALETTE " Palette",
|
||||
overworld_.mutable_overworld_map(current_map_)
|
||||
->mutable_area_palette(),
|
||||
kInputFieldSize)) {
|
||||
@@ -416,8 +422,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
if (asm_version >= 2 && asm_version != 0xFF) {
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_COLOR_LENS " Main Pal");
|
||||
if (gui::InputHexByte("##MainPal",
|
||||
if (gui::InputHexByte(ICON_MD_COLOR_LENS " Main Pal",
|
||||
overworld_.mutable_overworld_map(current_map_)
|
||||
->mutable_main_palette(),
|
||||
kInputFieldSize)) {
|
||||
@@ -431,8 +436,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
// Sprite Graphics (always present)
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_PETS " Spr Gfx");
|
||||
if (gui::InputHexByte("##SprGfx",
|
||||
if (gui::InputHexByte(ICON_MD_PETS " Spr Gfx",
|
||||
overworld_.mutable_overworld_map(current_map_)
|
||||
->mutable_sprite_graphics(game_state_),
|
||||
kInputFieldSize)) {
|
||||
@@ -444,8 +448,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
// Sprite Palette (always present)
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_COLORIZE " Spr Pal");
|
||||
if (gui::InputHexByte("##SprPalette",
|
||||
if (gui::InputHexByte(ICON_MD_COLORIZE " Spr Pal",
|
||||
overworld_.mutable_overworld_map(current_map_)
|
||||
->mutable_sprite_palette(game_state_),
|
||||
kInputFieldSize)) {
|
||||
@@ -457,9 +460,9 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
// Message ID (always present)
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_MESSAGE " Msg ID");
|
||||
if (gui::InputHexWord("##MsgId",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
|
||||
if (gui::InputHexWord(ICON_MD_MESSAGE " Msg ID",
|
||||
overworld_.mutable_overworld_map(current_map_)
|
||||
->mutable_message_id(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
@@ -470,8 +473,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
if (asm_version >= 3 && asm_version != 0xFF) {
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_ANIMATION " Anim GFX");
|
||||
if (gui::InputHexByte("##AnimGfx",
|
||||
if (gui::InputHexByte(ICON_MD_ANIMATION " Anim GFX",
|
||||
overworld_.mutable_overworld_map(current_map_)
|
||||
->mutable_animated_gfx(),
|
||||
kInputFieldSize)) {
|
||||
@@ -479,16 +481,16 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
|
||||
// Area Size (v3+ only)
|
||||
TableNextColumn();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text(ICON_MD_ASPECT_RATIO " Size");
|
||||
static const char *area_size_names[] = {"Small", "Large", "Wide", "Tall"};
|
||||
int current_area_size = static_cast<int>(
|
||||
overworld_.overworld_map(current_map_)->area_size());
|
||||
int current_area_size =
|
||||
static_cast<int>(overworld_.overworld_map(current_map_)->area_size());
|
||||
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_)
|
||||
->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||
RefreshOverworldMap();
|
||||
@@ -500,15 +502,17 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
||||
ImGui::TableNextRow();
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if (ImGui::Combo("##GameState", &game_state_, kGamePartComboString.data(), 3)) {
|
||||
if (ImGui::Combo("##GameState", &game_state_, kGamePartComboString.data(),
|
||||
3)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
HOVER_HINT("Game progression state for sprite graphics/palettes");
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Checkbox(ICON_MD_BLUR_ON " Mosaic",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_mosaic())) {
|
||||
if (ImGui::Checkbox(
|
||||
ICON_MD_BLUR_ON " Mosaic",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_mosaic())) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
@@ -1005,9 +1009,10 @@ void OverworldEditor::DrawOverworldCanvas() {
|
||||
if (all_gfx_loaded_) {
|
||||
if (core::FeatureFlags::get().overworld.kLoadCustomOverworld) {
|
||||
map_properties_system_->DrawSimplifiedMapSettings(
|
||||
current_world_, current_map_, current_map_lock_, show_map_properties_panel_,
|
||||
show_custom_bg_color_editor_, show_overlay_editor_, show_overlay_preview_, game_state_,
|
||||
reinterpret_cast<int&>(current_mode));
|
||||
current_world_, current_map_, current_map_lock_,
|
||||
show_map_properties_panel_, show_custom_bg_color_editor_,
|
||||
show_overlay_editor_, show_overlay_preview_, game_state_,
|
||||
reinterpret_cast<int &>(current_mode));
|
||||
} else {
|
||||
DrawOverworldMapSettings();
|
||||
}
|
||||
@@ -1035,12 +1040,13 @@ void OverworldEditor::DrawOverworldCanvas() {
|
||||
ow_map_canvas_.scrolling());
|
||||
DrawOverworldItems();
|
||||
DrawOverworldSprites();
|
||||
|
||||
|
||||
// Draw overlay preview if enabled
|
||||
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) {
|
||||
CheckForOverworldEdits();
|
||||
}
|
||||
@@ -1119,14 +1125,17 @@ void OverworldEditor::DrawTile8Selector() {
|
||||
}
|
||||
|
||||
absl::Status OverworldEditor::DrawAreaGraphics() {
|
||||
if (overworld_.is_loaded() && current_graphics_set_.contains(current_map_)) {
|
||||
overworld_.set_current_map(current_map_);
|
||||
palette_ = overworld_.current_area_palette();
|
||||
gfx::Bitmap bmp;
|
||||
Renderer::Get().CreateAndRenderBitmap(0x80, kOverworldMapSize, 0x08,
|
||||
overworld_.current_graphics(), bmp,
|
||||
palette_);
|
||||
current_graphics_set_[current_map_] = bmp;
|
||||
if (overworld_.is_loaded()) {
|
||||
// Always ensure current map graphics are loaded
|
||||
if (!current_graphics_set_.contains(current_map_)) {
|
||||
overworld_.set_current_map(current_map_);
|
||||
palette_ = overworld_.current_area_palette();
|
||||
gfx::Bitmap bmp;
|
||||
Renderer::Get().CreateAndRenderBitmap(0x80, kOverworldMapSize, 0x08,
|
||||
overworld_.current_graphics(), bmp,
|
||||
palette_);
|
||||
current_graphics_set_[current_map_] = bmp;
|
||||
}
|
||||
}
|
||||
|
||||
gui::BeginPadding(3);
|
||||
@@ -1137,7 +1146,7 @@ absl::Status OverworldEditor::DrawAreaGraphics() {
|
||||
{
|
||||
current_gfx_canvas_.DrawContextMenu();
|
||||
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_.DrawGrid();
|
||||
current_gfx_canvas_.DrawOverlay();
|
||||
@@ -1181,8 +1190,7 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
||||
if (each.is_hole_) {
|
||||
color = ImVec4(255, 255, 255, 200);
|
||||
}
|
||||
float scale = ow_map_canvas_.global_scale();
|
||||
ow_map_canvas_.DrawRect(each.x_ * scale, each.y_ * scale, 16 * scale, 16 * scale, color);
|
||||
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color);
|
||||
std::string str = util::HexByte(each.entrance_id_);
|
||||
|
||||
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++;
|
||||
}
|
||||
@@ -1243,8 +1251,7 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
|
||||
for (auto &each : *overworld_.mutable_exits()) {
|
||||
if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
|
||||
each.map_id_ >= (current_world_ * 0x40) && !each.deleted_) {
|
||||
float scale = ow_map_canvas_.global_scale();
|
||||
ow_map_canvas_.DrawRect(each.x_ * scale, each.y_ * scale, 16 * scale, 16 * scale,
|
||||
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16,
|
||||
ImVec4(255, 255, 255, 150));
|
||||
if (current_mode == EditingMode::EXITS) {
|
||||
each.entity_id_ = i;
|
||||
@@ -1268,7 +1275,7 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
@@ -1296,8 +1303,7 @@ void OverworldEditor::DrawOverworldItems() {
|
||||
// Get the item's bitmap and real X and Y positions
|
||||
if (item.room_map_id_ < 0x40 + (current_world_ * 0x40) &&
|
||||
item.room_map_id_ >= (current_world_ * 0x40) && !item.deleted) {
|
||||
float scale = ow_map_canvas_.global_scale();
|
||||
ow_map_canvas_.DrawRect(item.x_ * scale, item.y_ * scale, 16 * scale, 16 * scale, ImVec4(255, 0, 0, 150));
|
||||
ow_map_canvas_.DrawRect(item.x_, item.y_, 16, 16, ImVec4(255, 0, 0, 150));
|
||||
|
||||
if (current_mode == EditingMode::ITEMS) {
|
||||
// Check if this item is being clicked and dragged
|
||||
@@ -1319,7 +1325,7 @@ void OverworldEditor::DrawOverworldItems() {
|
||||
} else {
|
||||
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++;
|
||||
}
|
||||
@@ -1356,8 +1362,7 @@ void OverworldEditor::DrawOverworldSprites() {
|
||||
int original_x = sprite.x_;
|
||||
int original_y = sprite.y_;
|
||||
|
||||
float scale = ow_map_canvas_.global_scale();
|
||||
ow_map_canvas_.DrawRect(sprite_x * scale, sprite_y * scale, kTile16Size * scale, kTile16Size * scale,
|
||||
ow_map_canvas_.DrawRect(sprite_x, sprite_y, kTile16Size, kTile16Size,
|
||||
/*magenta=*/ImVec4(255, 0, 255, 150));
|
||||
if (current_mode == EditingMode::SPRITES) {
|
||||
HandleEntityDragging(&sprite, ow_map_canvas_.zero_point(),
|
||||
@@ -1372,13 +1377,13 @@ void OverworldEditor::DrawOverworldSprites() {
|
||||
}
|
||||
if (core::FeatureFlags::get().overworld.kDrawOverworldSprites) {
|
||||
if (sprite_previews_[sprite.id()].is_active()) {
|
||||
ow_map_canvas_.DrawBitmap(sprite_previews_[sprite.id()], sprite_x * scale,
|
||||
sprite_y * scale, 2.0f * scale);
|
||||
ow_map_canvas_.DrawBitmap(sprite_previews_[sprite.id()], sprite_x,
|
||||
sprite_y, 2.0f);
|
||||
}
|
||||
}
|
||||
|
||||
ow_map_canvas_.DrawText(absl::StrFormat("%s", sprite.name()), sprite_x * scale,
|
||||
sprite_y * scale);
|
||||
ow_map_canvas_.DrawText(absl::StrFormat("%s", sprite.name()), sprite_x,
|
||||
sprite_y);
|
||||
|
||||
// Restore original coordinates
|
||||
sprite.x_ = original_x;
|
||||
@@ -1698,7 +1703,7 @@ void OverworldEditor::DrawOverlayEditor() {
|
||||
Text("Vanilla ROM - Subscreen Overlays:");
|
||||
Text("Subscreen overlays in vanilla ROMs reference special area maps");
|
||||
Text("(0x80-0x9F) for visual effects like fog, rain, backgrounds.");
|
||||
|
||||
|
||||
Separator();
|
||||
if (Checkbox("Show Subscreen Overlay Preview", &show_overlay_preview_)) {
|
||||
// Toggle subscreen overlay preview
|
||||
@@ -1710,7 +1715,8 @@ void OverworldEditor::DrawOverlayEditor() {
|
||||
|
||||
Separator();
|
||||
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.");
|
||||
return;
|
||||
}
|
||||
@@ -1793,16 +1799,17 @@ void OverworldEditor::DrawOverlayEditor() {
|
||||
|
||||
void OverworldEditor::DrawOverlayPreview() {
|
||||
if (!show_overlay_preview_) return;
|
||||
|
||||
|
||||
Text("Subscreen Overlay Preview:");
|
||||
Separator();
|
||||
|
||||
|
||||
// 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
|
||||
Text("Subscreen Overlay ID: 0x%04X", overlay_id);
|
||||
|
||||
|
||||
// Show subscreen overlay description based on common overlay IDs
|
||||
std::string overlay_desc = "";
|
||||
if (overlay_id == 0x0093) {
|
||||
@@ -1829,32 +1836,34 @@ void OverworldEditor::DrawOverlayPreview() {
|
||||
overlay_desc = "Custom subscreen overlay effect";
|
||||
}
|
||||
Text("Description: %s", overlay_desc.c_str());
|
||||
|
||||
|
||||
Separator();
|
||||
|
||||
|
||||
// Map subscreen overlay ID to special area map for preview
|
||||
int overlay_map_index = -1;
|
||||
if (overlay_id >= 0x80 && overlay_id < 0xA0) {
|
||||
overlay_map_index = overlay_id;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
const auto &overlay_bitmap = maps_bmp_[overlay_map_index];
|
||||
|
||||
|
||||
if (overlay_bitmap.is_active()) {
|
||||
// Display the subscreen overlay map bitmap
|
||||
ImVec2 image_size(256, 256); // Scale down for preview
|
||||
ImGui::Image((ImTextureID)(intptr_t)overlay_bitmap.texture(), image_size);
|
||||
|
||||
|
||||
Separator();
|
||||
Text("This subscreen overlay would be displayed semi-transparently");
|
||||
Text("on top of the current map when active.");
|
||||
|
||||
|
||||
// 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("(behind the main map tiles).");
|
||||
} else {
|
||||
@@ -1870,7 +1879,6 @@ void OverworldEditor::DrawOverlayPreview() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OverworldEditor::DrawMapLockControls() {
|
||||
if (current_map_lock_) {
|
||||
PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.0f, 1.0f));
|
||||
@@ -1944,7 +1952,8 @@ void OverworldEditor::DrawOverworldContextMenu() {
|
||||
}
|
||||
} else if (asm_version == 0xFF) {
|
||||
// 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 (MenuItem("View Subscreen Overlay")) {
|
||||
show_overlay_editor_ = true;
|
||||
@@ -2268,9 +2277,11 @@ void OverworldEditor::DrawMapPropertiesPanel() {
|
||||
"TileGraphics", 4,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
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("GFX ID", ImGuiTableColumnFlags_WidthFixed, 120);
|
||||
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed,
|
||||
120);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
TableNextColumn();
|
||||
@@ -2645,8 +2656,8 @@ absl::Status OverworldEditor::ApplyZSCustomOverworldASM(int target_version) {
|
||||
auto patch_result = asar.ApplyPatch(asm_file_path, rom_data);
|
||||
if (!patch_result.ok()) {
|
||||
return absl::InternalError(
|
||||
absl::StrFormat("Failed to apply ZSCustomOverworld ASM: %s",
|
||||
patch_result.status().ToString()));
|
||||
absl::StrFormat("Failed to apply ZSCustomOverworld ASM: %s",
|
||||
patch_result.status().ToString()));
|
||||
}
|
||||
|
||||
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)
|
||||
if (patch_result->rom_size > 0 &&
|
||||
if (patch_result->rom_size > 0 &&
|
||||
static_cast<size_t>(patch_result->rom_size) != rom_->vector().size()) {
|
||||
// ROM size changed, need to expand/shrink
|
||||
rom_->Expand(patch_result->rom_size);
|
||||
}
|
||||
|
||||
|
||||
// Copy patched data to ROM (rom_data was modified in-place by asar)
|
||||
std::copy(rom_data.begin(), rom_data.end(), rom_->mutable_data());
|
||||
|
||||
// Log success and any symbols
|
||||
util::logf("Successfully applied ZSCustomOverworld ASM v%d", target_version);
|
||||
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
|
||||
if (!patch_result->warnings.empty()) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ absl::Status Tile16Editor::UpdateBlockset() {
|
||||
gui::EndPadding();
|
||||
blockset_canvas_.DrawContextMenu();
|
||||
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_.DrawOverlay();
|
||||
EndChild();
|
||||
@@ -391,7 +391,8 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
// Display the current Tile16 at a larger size
|
||||
auto texture = current_tile16_bmp_.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
|
||||
|
||||
@@ -85,7 +85,7 @@ class Tile16Editor : public gfx::GfxContext {
|
||||
|
||||
// Tile16 blockset for selecting the tile to edit
|
||||
gui::Canvas blockset_canvas_{"blocksetCanvas", ImVec2(0x100, 0x4000),
|
||||
gui::CanvasGridSize::k32x32};
|
||||
gui::CanvasGridSize::k32x32,};
|
||||
gfx::Bitmap tile16_blockset_bmp_;
|
||||
|
||||
// Canvas for editing the selected tile
|
||||
|
||||
@@ -134,12 +134,21 @@ void Canvas::DrawContextMenu() {
|
||||
}
|
||||
|
||||
// Default canvas menu items
|
||||
if (MenuItem("Reset Position", nullptr, false)) {
|
||||
scrolling_.x = 0;
|
||||
scrolling_.y = 0;
|
||||
if (MenuItem("Reset View", nullptr, false)) {
|
||||
ResetView();
|
||||
}
|
||||
if (MenuItem("Zoom to Fit", nullptr, false) && bitmap_) {
|
||||
SetZoomToFit(*bitmap_);
|
||||
}
|
||||
ImGui::Separator();
|
||||
MenuItem("Show Grid", nullptr, &enable_grid_);
|
||||
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")) {
|
||||
Text("Canvas Size: %.0f x %.0f", canvas_sz_.x, canvas_sz_.y);
|
||||
Text("Global Scale: %.1f", global_scale_);
|
||||
@@ -225,6 +234,12 @@ void Canvas::DrawContextMenu() {
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Draw enhanced property dialogs
|
||||
if (bitmap_) {
|
||||
ShowBitmapProperties(*bitmap_);
|
||||
ShowPaletteEditor(*bitmap_->mutable_palette());
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::DrawContextMenuItem(const ContextMenuItem& item) {
|
||||
@@ -260,6 +275,87 @@ void Canvas::ClearContextMenuItems() {
|
||||
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) {
|
||||
const ImGuiIO &io = GetIO();
|
||||
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) {
|
||||
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
|
||||
canvas_p0_.y + scrolling_.y + y);
|
||||
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
|
||||
canvas_p0_.y + scrolling_.y + y + h);
|
||||
// Apply global scale to position and size
|
||||
float scaled_x = x * global_scale_;
|
||||
float scaled_y = y * global_scale_;
|
||||
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,
|
||||
IM_COL32(color.x, color.y, color.z, color.w));
|
||||
// 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) {
|
||||
draw_list_->AddText(ImVec2(canvas_p0_.x + scrolling_.x + x + 1,
|
||||
canvas_p0_.y + scrolling_.y + y + 1),
|
||||
// Apply global scale to text position
|
||||
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());
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,12 @@ class Canvas {
|
||||
void ClearContextMenuItems();
|
||||
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:
|
||||
void DrawContextMenuItem(const ContextMenuItem& item);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user