Add MapPropertiesSystem for enhanced overworld map management
- Introduced MapPropertiesSystem class to manage map properties, including settings for area size, graphics, palettes, and overlays. - Implemented UI components for drawing map properties, allowing users to customize map settings through a dedicated panel. - Enhanced OverworldEditor to integrate map properties functionality, providing quick access to map settings via context menus and UI interactions. - Added support for custom background colors and overlays, improving the overall customization experience for users.
This commit is contained in:
@@ -13,6 +13,7 @@ set(
|
||||
app/editor/graphics/graphics_editor.cc
|
||||
app/editor/graphics/palette_editor.cc
|
||||
app/editor/overworld/tile16_editor.cc
|
||||
app/editor/overworld/map_properties.cc
|
||||
app/editor/graphics/gfx_group_editor.cc
|
||||
app/editor/overworld/entity.cc
|
||||
app/editor/system/settings_editor.cc
|
||||
|
||||
667
src/app/editor/overworld/map_properties.cc
Normal file
667
src/app/editor/overworld/map_properties.cc
Normal file
@@ -0,0 +1,667 @@
|
||||
#include "app/editor/overworld/map_properties.h"
|
||||
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/style.h"
|
||||
#include "app/zelda3/overworld/overworld_map.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
using ImGui::BeginTable;
|
||||
using ImGui::Button;
|
||||
using ImGui::Checkbox;
|
||||
using ImGui::EndTable;
|
||||
// HOVER_HINT is defined in util/macro.h
|
||||
using ImGui::SameLine;
|
||||
using ImGui::Separator;
|
||||
using ImGui::TableNextColumn;
|
||||
using ImGui::Text;
|
||||
|
||||
// Static constants
|
||||
constexpr const char* kWorldList[] = {"Light World", "Dark World", "Special World"};
|
||||
constexpr const char* kGamePartComboString[] = {"Light World", "Dark World", "Special World"};
|
||||
|
||||
void MapPropertiesSystem::DrawSimplifiedMapSettings(int& current_world, int& current_map,
|
||||
bool& current_map_lock, bool& show_map_properties_panel,
|
||||
bool& show_custom_bg_color_editor, bool& show_overlay_editor) {
|
||||
// Enhanced settings table with popup buttons for quick access
|
||||
if (BeginTable("SimplifiedMapSettings", 8, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit, ImVec2(0, 0), -1)) {
|
||||
ImGui::TableSetupColumn("World", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
ImGui::TableSetupColumn("Map", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("Area Size", ImGuiTableColumnFlags_WidthFixed, 100);
|
||||
ImGui::TableSetupColumn("Lock", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("Graphics", ImGuiTableColumnFlags_WidthFixed, 70);
|
||||
ImGui::TableSetupColumn("Palettes", ImGuiTableColumnFlags_WidthFixed, 70);
|
||||
ImGui::TableSetupColumn("Overlays", ImGuiTableColumnFlags_WidthFixed, 70);
|
||||
ImGui::TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(70.f);
|
||||
if (ImGui::Combo("##world", ¤t_world, kWorldList, 3)) {
|
||||
// World changed, update current map if needed
|
||||
if (current_map >= 0x40 && current_world == 0) {
|
||||
current_map -= 0x40;
|
||||
} else if (current_map < 0x40 && current_world == 1) {
|
||||
current_map += 0x40;
|
||||
} else if (current_map < 0x80 && current_world == 2) {
|
||||
current_map += 0x80;
|
||||
} else if (current_map >= 0x80 && current_world != 2) {
|
||||
current_map -= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::Text("%d (0x%02X)", current_map, current_map);
|
||||
|
||||
TableNextColumn();
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version != 0xFF) {
|
||||
static const char *area_size_names[] = {"Small (1x1)", "Large (2x2)", "Wide (2x1)", "Tall (1x2)"};
|
||||
int current_area_size = static_cast<int>(overworld_->overworld_map(current_map)->area_size());
|
||||
ImGui::SetNextItemWidth(90.f);
|
||||
if (ImGui::Combo("##AreaSize", ¤t_area_size, area_size_names, 4)) {
|
||||
overworld_->mutable_overworld_map(current_map)->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("N/A");
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button(current_map_lock ? ICON_MD_LOCK : ICON_MD_LOCK_OPEN, ImVec2(30, 0))) {
|
||||
current_map_lock = !current_map_lock;
|
||||
}
|
||||
HOVER_HINT(current_map_lock ? "Unlock Map" : "Lock Map");
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Graphics", ImVec2(60, 0))) {
|
||||
ImGui::OpenPopup("GraphicsPopup");
|
||||
}
|
||||
HOVER_HINT("Graphics Settings");
|
||||
DrawGraphicsPopup(current_map);
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Palettes", ImVec2(60, 0))) {
|
||||
ImGui::OpenPopup("PalettesPopup");
|
||||
}
|
||||
HOVER_HINT("Palette Settings");
|
||||
DrawPalettesPopup(current_map, show_custom_bg_color_editor);
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Overlays", ImVec2(60, 0))) {
|
||||
ImGui::OpenPopup("OverlaysPopup");
|
||||
}
|
||||
HOVER_HINT("Overlay Settings");
|
||||
DrawOverlaysPopup(current_map, show_overlay_editor);
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Properties", ImVec2(70, 0))) {
|
||||
ImGui::OpenPopup("PropertiesPopup");
|
||||
}
|
||||
HOVER_HINT("Map Properties");
|
||||
DrawPropertiesPopup(current_map, show_map_properties_panel);
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawMapPropertiesPanel(int current_map, bool& show_map_properties_panel) {
|
||||
if (!overworld_->is_loaded()) {
|
||||
Text("No overworld loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// Header with map info and lock status
|
||||
ImGui::BeginGroup();
|
||||
Text("Current Map: %d (0x%02X)", current_map, current_map);
|
||||
ImGui::EndGroup();
|
||||
|
||||
Separator();
|
||||
|
||||
// Create tabs for different property categories
|
||||
if (ImGui::BeginTabBar("MapPropertiesTabs", ImGuiTabBarFlags_FittingPolicyScroll)) {
|
||||
|
||||
// Basic Properties Tab
|
||||
if (ImGui::BeginTabItem("Basic Properties")) {
|
||||
DrawBasicPropertiesTab(current_map);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// Sprite Properties Tab
|
||||
if (ImGui::BeginTabItem("Sprite Properties")) {
|
||||
DrawSpritePropertiesTab(current_map);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// Custom Overworld Features Tab
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version != 0xFF && ImGui::BeginTabItem("Custom Features")) {
|
||||
DrawCustomFeaturesTab(current_map);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// Tile Graphics Tab
|
||||
if (ImGui::BeginTabItem("Tile Graphics")) {
|
||||
DrawTileGraphicsTab(current_map);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawCustomBackgroundColorEditor(int current_map, bool& show_custom_bg_color_editor) {
|
||||
if (!overworld_->is_loaded()) {
|
||||
Text("No overworld loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version < 2) {
|
||||
Text("Custom background colors require ZSCustomOverworld v2+");
|
||||
return;
|
||||
}
|
||||
|
||||
Text("Custom Background Color Editor");
|
||||
Separator();
|
||||
|
||||
// Enable/disable area-specific background color
|
||||
static bool use_area_specific_bg_color = false;
|
||||
if (ImGui::Checkbox("Use Area-Specific Background Color", &use_area_specific_bg_color)) {
|
||||
// Update ROM data
|
||||
(*rom_)[zelda3::OverworldCustomAreaSpecificBGEnabled] = use_area_specific_bg_color ? 1 : 0;
|
||||
}
|
||||
|
||||
if (use_area_specific_bg_color) {
|
||||
// Get current color
|
||||
uint16_t current_color = overworld_->overworld_map(current_map)->area_specific_bg_color();
|
||||
gfx::SnesColor snes_color(current_color);
|
||||
|
||||
// Convert to ImVec4 for color picker
|
||||
ImVec4 color_vec = gui::ConvertSnesColorToImVec4(snes_color);
|
||||
|
||||
if (ImGui::ColorPicker4("Background Color", (float*)&color_vec,
|
||||
ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_DisplayHex)) {
|
||||
// Convert back to SNES color and update
|
||||
gfx::SnesColor new_snes_color = gui::ConvertImVec4ToSnesColor(color_vec);
|
||||
overworld_->mutable_overworld_map(current_map)->set_area_specific_bg_color(new_snes_color.snes());
|
||||
|
||||
// Update ROM
|
||||
int rom_address = zelda3::OverworldCustomAreaSpecificBGPalette + (current_map * 2);
|
||||
(*rom_)[rom_address] = new_snes_color.snes() & 0xFF;
|
||||
(*rom_)[rom_address + 1] = (new_snes_color.snes() >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
Text("SNES Color: 0x%04X", current_color);
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawOverlayEditor(int current_map, bool& show_overlay_editor) {
|
||||
if (!overworld_->is_loaded()) {
|
||||
Text("No overworld loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version < 1) {
|
||||
Text("Subscreen overlays require ZSCustomOverworld v1+");
|
||||
return;
|
||||
}
|
||||
|
||||
Text("Overlay Editor");
|
||||
Separator();
|
||||
|
||||
// Enable/disable subscreen overlay
|
||||
static bool use_subscreen_overlay = false;
|
||||
if (ImGui::Checkbox("Use Subscreen Overlay", &use_subscreen_overlay)) {
|
||||
// Update ROM data
|
||||
(*rom_)[zelda3::OverworldCustomSubscreenOverlayEnabled] = use_subscreen_overlay ? 1 : 0;
|
||||
}
|
||||
|
||||
if (use_subscreen_overlay) {
|
||||
uint16_t current_overlay = overworld_->overworld_map(current_map)->subscreen_overlay();
|
||||
if (gui::InputHexWord("Overlay ID", ¤t_overlay, kInputFieldSize + 20)) {
|
||||
overworld_->mutable_overworld_map(current_map)->set_subscreen_overlay(current_overlay);
|
||||
|
||||
// Update ROM
|
||||
int rom_address = zelda3::OverworldCustomSubscreenOverlayArray + (current_map * 2);
|
||||
(*rom_)[rom_address] = current_overlay & 0xFF;
|
||||
(*rom_)[rom_address + 1] = (current_overlay >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
Text("Common overlay IDs:");
|
||||
Text("0x0000 = None");
|
||||
Text("0x0001 = Map overlay");
|
||||
Text("0x0002 = Dungeon overlay");
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::SetupCanvasContextMenu(gui::Canvas& canvas, int current_map, bool current_map_lock,
|
||||
bool& show_map_properties_panel, bool& show_custom_bg_color_editor,
|
||||
bool& show_overlay_editor) {
|
||||
// Clear any existing context menu items
|
||||
canvas.ClearContextMenuItems();
|
||||
|
||||
// Add overworld-specific context menu items
|
||||
gui::Canvas::ContextMenuItem lock_item;
|
||||
lock_item.label = current_map_lock ? "Unlock Map" : "Lock to This Map";
|
||||
lock_item.callback = [¤t_map_lock]() {
|
||||
current_map_lock = !current_map_lock;
|
||||
};
|
||||
canvas.AddContextMenuItem(lock_item);
|
||||
|
||||
// Map Properties
|
||||
gui::Canvas::ContextMenuItem properties_item;
|
||||
properties_item.label = "Map Properties";
|
||||
properties_item.callback = [&show_map_properties_panel]() {
|
||||
show_map_properties_panel = true;
|
||||
};
|
||||
canvas.AddContextMenuItem(properties_item);
|
||||
|
||||
// Custom overworld features (only show if v3+)
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 3 && asm_version != 0xFF) {
|
||||
// Custom Background Color
|
||||
gui::Canvas::ContextMenuItem bg_color_item;
|
||||
bg_color_item.label = "Custom Background Color";
|
||||
bg_color_item.callback = [&show_custom_bg_color_editor]() {
|
||||
show_custom_bg_color_editor = true;
|
||||
};
|
||||
canvas.AddContextMenuItem(bg_color_item);
|
||||
|
||||
// Overlay Settings
|
||||
gui::Canvas::ContextMenuItem overlay_item;
|
||||
overlay_item.label = "Overlay Settings";
|
||||
overlay_item.callback = [&show_overlay_editor]() {
|
||||
show_overlay_editor = true;
|
||||
};
|
||||
canvas.AddContextMenuItem(overlay_item);
|
||||
}
|
||||
|
||||
// Canvas controls
|
||||
gui::Canvas::ContextMenuItem reset_pos_item;
|
||||
reset_pos_item.label = "Reset Canvas Position";
|
||||
reset_pos_item.callback = [&canvas]() {
|
||||
canvas.set_scrolling(ImVec2(0, 0));
|
||||
};
|
||||
canvas.AddContextMenuItem(reset_pos_item);
|
||||
|
||||
gui::Canvas::ContextMenuItem zoom_fit_item;
|
||||
zoom_fit_item.label = "Zoom to Fit";
|
||||
zoom_fit_item.callback = [&canvas]() {
|
||||
canvas.set_global_scale(1.0f);
|
||||
canvas.set_scrolling(ImVec2(0, 0));
|
||||
};
|
||||
canvas.AddContextMenuItem(zoom_fit_item);
|
||||
}
|
||||
|
||||
// Private method implementations
|
||||
void MapPropertiesSystem::DrawGraphicsPopup(int current_map) {
|
||||
if (ImGui::BeginPopup("GraphicsPopup")) {
|
||||
ImGui::Text("Graphics Settings");
|
||||
ImGui::Separator();
|
||||
|
||||
if (gui::InputHexByte("Area Graphics",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_area_graphics(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite GFX 1",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_graphics(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite GFX 2",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_graphics(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 3) {
|
||||
if (gui::InputHexByte("Animated GFX",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_animated_gfx(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Tile Graphics (8 sheets)")) {
|
||||
// This would open the full properties panel
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawPalettesPopup(int current_map, bool& show_custom_bg_color_editor) {
|
||||
if (ImGui::BeginPopup("PalettesPopup")) {
|
||||
ImGui::Text("Palette Settings");
|
||||
ImGui::Separator();
|
||||
|
||||
if (gui::InputHexByte("Area Palette",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_area_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 2) {
|
||||
if (gui::InputHexByte("Main Palette",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_main_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite Palette 1",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_palette(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite Palette 2",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_palette(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Background Color")) {
|
||||
show_custom_bg_color_editor = !show_custom_bg_color_editor;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawOverlaysPopup(int current_map, bool& show_overlay_editor) {
|
||||
if (ImGui::BeginPopup("OverlaysPopup")) {
|
||||
ImGui::Text("Overlay Settings");
|
||||
ImGui::Separator();
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 3) {
|
||||
if (gui::InputHexWord("Subscreen Overlay",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_subscreen_overlay(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Overlay Settings")) {
|
||||
show_overlay_editor = !show_overlay_editor;
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("Overlays require ZSCustomOverworld v3+");
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawPropertiesPopup(int current_map, bool& show_map_properties_panel) {
|
||||
if (ImGui::BeginPopup("PropertiesPopup")) {
|
||||
ImGui::Text("Map Properties");
|
||||
ImGui::Separator();
|
||||
|
||||
if (gui::InputHexWord("Message ID",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_message_id(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("Mosaic Effect",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_mosaic())) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static int game_state = 0; // This should be passed in or stored
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if (ImGui::Combo("Game State", &game_state, kGamePartComboString, 3)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version != 0xFF) {
|
||||
static const char *area_size_names[] = {"Small (1x1)", "Large (2x2)", "Wide (2x1)", "Tall (1x2)"};
|
||||
int current_area_size = static_cast<int>(overworld_->overworld_map(current_map)->area_size());
|
||||
ImGui::SetNextItemWidth(120.f);
|
||||
if (ImGui::Combo("Area Size", ¤t_area_size, area_size_names, 4)) {
|
||||
overworld_->mutable_overworld_map(current_map)->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Full Properties Panel")) {
|
||||
show_map_properties_panel = true;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawBasicPropertiesTab(int current_map) {
|
||||
if (BeginTable("BasicProperties", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextColumn(); ImGui::Text("Area Graphics");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##AreaGfx",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_area_graphics(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Area Palette");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##AreaPal",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_area_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Message ID");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexWord("##MsgId",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_message_id(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Mosaic Effect");
|
||||
TableNextColumn();
|
||||
if (ImGui::Checkbox("##mosaic",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_mosaic())) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
HOVER_HINT("Enable Mosaic effect for the current map");
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawSpritePropertiesTab(int current_map) {
|
||||
if (BeginTable("SpriteProperties", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextColumn(); ImGui::Text("Game State");
|
||||
TableNextColumn();
|
||||
static int game_state = 0;
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if (ImGui::Combo("##GameState", &game_state, kGamePartComboString, 3)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Sprite Graphics 1");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprGfx1",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_graphics(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Sprite Graphics 2");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprGfx2",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_graphics(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Sprite Palette 1");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprPal1",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_palette(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Sprite Palette 2");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprPal2",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_sprite_palette(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawCustomFeaturesTab(int current_map) {
|
||||
if (BeginTable("CustomFeatures", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextColumn(); ImGui::Text("Area Size");
|
||||
TableNextColumn();
|
||||
static const char *area_size_names[] = {"Small (1x1)", "Large (2x2)", "Wide (2x1)", "Tall (1x2)"};
|
||||
int current_area_size = static_cast<int>(overworld_->overworld_map(current_map)->area_size());
|
||||
ImGui::SetNextItemWidth(120.f);
|
||||
if (ImGui::Combo("##AreaSize", ¤t_area_size, area_size_names, 4)) {
|
||||
overworld_->mutable_overworld_map(current_map)->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 2) {
|
||||
TableNextColumn(); ImGui::Text("Main Palette");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##MainPal",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_main_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
if (asm_version >= 3) {
|
||||
TableNextColumn(); ImGui::Text("Animated GFX");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##AnimGfx",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_animated_gfx(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); ImGui::Text("Subscreen Overlay");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexWord("##SubOverlay",
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_subscreen_overlay(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::DrawTileGraphicsTab(int current_map) {
|
||||
ImGui::Text("Custom Tile Graphics (8 sheets per map):");
|
||||
Separator();
|
||||
|
||||
if (BeginTable("TileGraphics", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
TableNextColumn();
|
||||
ImGui::Text("Sheet %d", i);
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i).c_str(),
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_custom_tileset(i),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::Text("Sheet %d", i + 4);
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i + 4).c_str(),
|
||||
overworld_->mutable_overworld_map(current_map)->mutable_custom_tileset(i + 4),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::RefreshMapProperties() {
|
||||
// Implementation would refresh map properties
|
||||
}
|
||||
|
||||
void MapPropertiesSystem::RefreshOverworldMap() {
|
||||
// Implementation would refresh the overworld map display
|
||||
}
|
||||
|
||||
absl::Status MapPropertiesSystem::RefreshMapPalette() {
|
||||
// Implementation would refresh the map palette
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
62
src/app/editor/overworld/map_properties.h
Normal file
62
src/app/editor/overworld/map_properties.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef YAZE_APP_EDITOR_OVERWORLD_MAP_PROPERTIES_H
|
||||
#define YAZE_APP_EDITOR_OVERWORLD_MAP_PROPERTIES_H
|
||||
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
class MapPropertiesSystem {
|
||||
public:
|
||||
explicit MapPropertiesSystem(zelda3::Overworld* overworld, Rom* rom)
|
||||
: overworld_(overworld), rom_(rom) {}
|
||||
|
||||
// Main interface methods
|
||||
void DrawSimplifiedMapSettings(int& current_world, int& current_map,
|
||||
bool& current_map_lock, bool& show_map_properties_panel,
|
||||
bool& show_custom_bg_color_editor, bool& show_overlay_editor);
|
||||
|
||||
void DrawMapPropertiesPanel(int current_map, bool& show_map_properties_panel);
|
||||
|
||||
void DrawCustomBackgroundColorEditor(int current_map, bool& show_custom_bg_color_editor);
|
||||
|
||||
void DrawOverlayEditor(int current_map, bool& show_overlay_editor);
|
||||
|
||||
// Context menu integration
|
||||
void SetupCanvasContextMenu(gui::Canvas& canvas, int current_map, bool current_map_lock,
|
||||
bool& show_map_properties_panel, bool& show_custom_bg_color_editor,
|
||||
bool& show_overlay_editor);
|
||||
|
||||
private:
|
||||
// Property category drawers
|
||||
void DrawGraphicsPopup(int current_map);
|
||||
void DrawPalettesPopup(int current_map, bool& show_custom_bg_color_editor);
|
||||
void DrawOverlaysPopup(int current_map, bool& show_overlay_editor);
|
||||
void DrawPropertiesPopup(int current_map, bool& show_map_properties_panel);
|
||||
|
||||
// Tab content drawers
|
||||
void DrawBasicPropertiesTab(int current_map);
|
||||
void DrawSpritePropertiesTab(int current_map);
|
||||
void DrawCustomFeaturesTab(int current_map);
|
||||
void DrawTileGraphicsTab(int current_map);
|
||||
|
||||
// Utility methods
|
||||
void RefreshMapProperties();
|
||||
void RefreshOverworldMap();
|
||||
absl::Status RefreshMapPalette();
|
||||
|
||||
zelda3::Overworld* overworld_;
|
||||
Rom* rom_;
|
||||
|
||||
// Static constants
|
||||
static constexpr float kInputFieldSize = 30.f;
|
||||
static constexpr int kOverworldMapSize = 512;
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_OVERWORLD_MAP_PROPERTIES_H
|
||||
@@ -43,6 +43,9 @@ void OverworldEditor::Initialize() {
|
||||
|
||||
gui::zeml::Bind(std::to_address(layout_node_.GetNode("OverworldCanvas")),
|
||||
[this]() { DrawOverworldCanvas(); });
|
||||
|
||||
// Setup overworld canvas context menu
|
||||
SetupOverworldCanvasContextMenu();
|
||||
gui::zeml::Bind(
|
||||
std::to_address(layout_node_.GetNode("OverworldTileSelector")),
|
||||
[this]() { status_ = DrawTileSelector(); });
|
||||
@@ -250,6 +253,12 @@ void OverworldEditor::DrawToolset() {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
if (show_map_properties_panel_) {
|
||||
ImGui::Begin("Map Properties Panel", &show_map_properties_panel_);
|
||||
DrawMapPropertiesPanel();
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// TODO: Customizable shortcuts for the Overworld Editor
|
||||
if (!ImGui::IsAnyItemActive()) {
|
||||
using enum EditingMode;
|
||||
@@ -492,6 +501,236 @@ void OverworldEditor::DrawCustomOverworldMapSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
void OverworldEditor::DrawSimplifiedMapSettings() {
|
||||
// Enhanced settings table with popup buttons for quick access
|
||||
if (BeginTable("SimplifiedMapSettings", 8, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit, ImVec2(0, 0), -1)) {
|
||||
ImGui::TableSetupColumn("World", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
ImGui::TableSetupColumn("Map", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("Area Size", ImGuiTableColumnFlags_WidthFixed, 100);
|
||||
ImGui::TableSetupColumn("Lock", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("Graphics", ImGuiTableColumnFlags_WidthFixed, 70);
|
||||
ImGui::TableSetupColumn("Palettes", ImGuiTableColumnFlags_WidthFixed, 70);
|
||||
ImGui::TableSetupColumn("Overlays", ImGuiTableColumnFlags_WidthFixed, 70);
|
||||
ImGui::TableSetupColumn("Properties", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(70.f);
|
||||
if (ImGui::Combo("##world", ¤t_world_, kWorldList.data(), 3)) {
|
||||
// World changed, update current map if needed
|
||||
if (current_map_ >= 0x40 && current_world_ == 0) {
|
||||
current_map_ -= 0x40;
|
||||
} else if (current_map_ < 0x40 && current_world_ == 1) {
|
||||
current_map_ += 0x40;
|
||||
} else if (current_map_ < 0x80 && current_world_ == 2) {
|
||||
current_map_ += 0x80;
|
||||
} else if (current_map_ >= 0x80 && current_world_ != 2) {
|
||||
current_map_ -= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
ImGui::Text("%d (0x%02X)", current_map_, current_map_);
|
||||
|
||||
TableNextColumn();
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version != 0xFF) {
|
||||
static const char *area_size_names[] = {"Small (1x1)", "Large (2x2)", "Wide (2x1)", "Tall (1x2)"};
|
||||
int current_area_size = static_cast<int>(overworld_.overworld_map(current_map_)->area_size());
|
||||
ImGui::SetNextItemWidth(90.f);
|
||||
if (ImGui::Combo("##AreaSize", ¤t_area_size, area_size_names, 4)) {
|
||||
overworld_.mutable_overworld_map(current_map_)->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("N/A");
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button(current_map_lock_ ? ICON_MD_LOCK : ICON_MD_LOCK_OPEN, ImVec2(30, 0))) {
|
||||
current_map_lock_ = !current_map_lock_;
|
||||
// Refresh context menu to update lock/unlock text
|
||||
SetupOverworldCanvasContextMenu();
|
||||
}
|
||||
HOVER_HINT(current_map_lock_ ? "Unlock Map" : "Lock Map");
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Graphics", ImVec2(60, 0))) {
|
||||
ImGui::OpenPopup("GraphicsPopup");
|
||||
}
|
||||
HOVER_HINT("Graphics Settings");
|
||||
if (ImGui::BeginPopup("GraphicsPopup")) {
|
||||
ImGui::Text("Graphics Settings");
|
||||
ImGui::Separator();
|
||||
|
||||
if (gui::InputHexByte("Area Graphics",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_area_graphics(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite GFX 1",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_graphics(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite GFX 2",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_graphics(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 3) {
|
||||
if (gui::InputHexByte("Animated GFX",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_animated_gfx(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Tile Graphics (8 sheets)")) {
|
||||
show_map_properties_panel_ = true;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Palettes", ImVec2(60, 0))) {
|
||||
ImGui::OpenPopup("PalettesPopup");
|
||||
}
|
||||
HOVER_HINT("Palette Settings");
|
||||
if (ImGui::BeginPopup("PalettesPopup")) {
|
||||
ImGui::Text("Palette Settings");
|
||||
ImGui::Separator();
|
||||
|
||||
if (gui::InputHexByte("Area Palette",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_area_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
status_ = RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 2) {
|
||||
if (gui::InputHexByte("Main Palette",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_main_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
status_ = RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite Palette 1",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_palette(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (gui::InputHexByte("Sprite Palette 2",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_palette(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Background Color")) {
|
||||
show_custom_bg_color_editor_ = !show_custom_bg_color_editor_;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Overlays", ImVec2(60, 0))) {
|
||||
ImGui::OpenPopup("OverlaysPopup");
|
||||
}
|
||||
HOVER_HINT("Overlay Settings");
|
||||
if (ImGui::BeginPopup("OverlaysPopup")) {
|
||||
ImGui::Text("Overlay Settings");
|
||||
ImGui::Separator();
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 3) {
|
||||
if (gui::InputHexWord("Subscreen Overlay",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_subscreen_overlay(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Overlay Settings")) {
|
||||
show_overlay_editor_ = !show_overlay_editor_;
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("Overlays require ZSCustomOverworld v3+");
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
if (ImGui::Button("Properties", ImVec2(70, 0))) {
|
||||
ImGui::OpenPopup("PropertiesPopup");
|
||||
}
|
||||
HOVER_HINT("Map Properties");
|
||||
if (ImGui::BeginPopup("PropertiesPopup")) {
|
||||
ImGui::Text("Map Properties");
|
||||
ImGui::Separator();
|
||||
|
||||
if (gui::InputHexWord("Message ID",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (ImGui::Checkbox("Mosaic Effect",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_mosaic())) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if (ImGui::Combo("Game State", &game_state_, kGamePartComboString.data(), 3)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version != 0xFF) {
|
||||
static const char *area_size_names[] = {"Small (1x1)", "Large (2x2)", "Wide (2x1)", "Tall (1x2)"};
|
||||
int current_area_size = static_cast<int>(overworld_.overworld_map(current_map_)->area_size());
|
||||
ImGui::SetNextItemWidth(120.f);
|
||||
if (ImGui::Combo("Area Size", ¤t_area_size, area_size_names, 4)) {
|
||||
overworld_.mutable_overworld_map(current_map_)->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Button("Full Properties Panel")) {
|
||||
show_map_properties_panel_ = true;
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void OverworldEditor::DrawOverworldMaps() {
|
||||
int xx = 0;
|
||||
int yy = 0;
|
||||
@@ -767,17 +1006,20 @@ absl::Status OverworldEditor::CheckForCurrentMap() {
|
||||
int map_y = (mouse_position.y - canvas_zero_point.y) / kOverworldMapSize;
|
||||
|
||||
// Calculate the index of the map in the `maps_bmp_` vector
|
||||
current_map_ = map_x + map_y * 8;
|
||||
int hovered_map = map_x + map_y * 8;
|
||||
if (current_world_ == 1) {
|
||||
current_map_ += 0x40;
|
||||
hovered_map += 0x40;
|
||||
} else if (current_world_ == 2) {
|
||||
current_map_ += 0x80;
|
||||
hovered_map += 0x80;
|
||||
}
|
||||
const int current_highlighted_map = current_map_;
|
||||
|
||||
|
||||
// Only update current_map_ if not locked
|
||||
if (!current_map_lock_) {
|
||||
current_map_ = hovered_map;
|
||||
current_parent_ = overworld_.overworld_map(current_map_)->parent();
|
||||
}
|
||||
|
||||
const int current_highlighted_map = current_map_;
|
||||
|
||||
if (overworld_.overworld_map(current_map_)->is_large_map() ||
|
||||
overworld_.overworld_map(current_map_)->large_index() != 0) {
|
||||
@@ -830,7 +1072,7 @@ void OverworldEditor::CheckForMousePan() {
|
||||
void OverworldEditor::DrawOverworldCanvas() {
|
||||
if (all_gfx_loaded_) {
|
||||
if (core::FeatureFlags::get().overworld.kLoadCustomOverworld) {
|
||||
DrawCustomOverworldMapSettings();
|
||||
DrawSimplifiedMapSettings();
|
||||
} else {
|
||||
DrawOverworldMapSettings();
|
||||
}
|
||||
@@ -847,8 +1089,8 @@ void OverworldEditor::DrawOverworldCanvas() {
|
||||
ow_map_canvas_.DrawContextMenu();
|
||||
} else {
|
||||
ow_map_canvas_.set_draggable(false);
|
||||
// Always show our custom overworld context menu
|
||||
DrawOverworldContextMenu();
|
||||
// Handle map interaction with middle-click instead of right-click
|
||||
HandleMapInteraction();
|
||||
}
|
||||
|
||||
if (overworld_.is_loaded()) {
|
||||
@@ -1627,6 +1869,367 @@ void OverworldEditor::DrawOverworldContextMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
void OverworldEditor::HandleMapInteraction() {
|
||||
// Handle middle-click for map interaction instead of right-click
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle) && ImGui::IsItemHovered()) {
|
||||
// Get the current map from mouse position
|
||||
auto mouse_position = ow_map_canvas_.drawn_tile_position();
|
||||
int map_x = mouse_position.x / kOverworldMapSize;
|
||||
int map_y = mouse_position.y / kOverworldMapSize;
|
||||
int hovered_map = map_x + map_y * 8;
|
||||
if (current_world_ == 1) {
|
||||
hovered_map += 0x40;
|
||||
} else if (current_world_ == 2) {
|
||||
hovered_map += 0x80;
|
||||
}
|
||||
|
||||
// Only interact if we're hovering over a valid map
|
||||
if (hovered_map >= 0 && hovered_map < 0xA0) {
|
||||
// Toggle map lock or open properties panel
|
||||
if (current_map_lock_ && current_map_ == hovered_map) {
|
||||
current_map_lock_ = false;
|
||||
} else {
|
||||
current_map_lock_ = true;
|
||||
current_map_ = hovered_map;
|
||||
show_map_properties_panel_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle double-click to open properties panel
|
||||
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) && ImGui::IsItemHovered()) {
|
||||
show_map_properties_panel_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void OverworldEditor::DrawMapPropertiesPanel() {
|
||||
if (!overworld_.is_loaded()) {
|
||||
Text("No overworld loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// Header with map info and lock status
|
||||
ImGui::BeginGroup();
|
||||
if (current_map_lock_) {
|
||||
PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.5f, 0.0f, 1.0f));
|
||||
Text("Map Locked: %d (0x%02X)", current_map_, current_map_);
|
||||
PopStyleColor();
|
||||
} else {
|
||||
Text("Current Map: %d (0x%02X)", current_map_, current_map_);
|
||||
}
|
||||
|
||||
SameLine();
|
||||
if (Button(current_map_lock_ ? "Unlock" : "Lock")) {
|
||||
current_map_lock_ = !current_map_lock_;
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
Separator();
|
||||
|
||||
// Create tabs for different property categories
|
||||
if (BeginTabBar("MapPropertiesTabs", ImGuiTabBarFlags_FittingPolicyScroll)) {
|
||||
|
||||
// Basic Properties Tab
|
||||
if (BeginTabItem("Basic Properties")) {
|
||||
if (BeginTable("BasicProperties", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextColumn(); Text("World");
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if (ImGui::Combo("##world", ¤t_world_, kWorldList.data(), 3)) {
|
||||
// Update current map based on world change
|
||||
if (current_map_ >= 0x40 && current_world_ == 0) {
|
||||
current_map_ -= 0x40;
|
||||
} else if (current_map_ < 0x40 && current_world_ == 1) {
|
||||
current_map_ += 0x40;
|
||||
} else if (current_map_ < 0x80 && current_world_ == 2) {
|
||||
current_map_ += 0x80;
|
||||
} else if (current_map_ >= 0x80 && current_world_ != 2) {
|
||||
current_map_ -= 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Area Graphics");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##AreaGfx",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_area_graphics(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Area Palette");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##AreaPal",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_area_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
status_ = RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Message ID");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexWord("##MsgId",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_message_id(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Mosaic Effect");
|
||||
TableNextColumn();
|
||||
if (ImGui::Checkbox("##mosaic",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_mosaic())) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
HOVER_HINT("Enable Mosaic effect for the current map");
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
EndTabItem();
|
||||
}
|
||||
|
||||
// Sprite Properties Tab
|
||||
if (BeginTabItem("Sprite Properties")) {
|
||||
if (BeginTable("SpriteProperties", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextColumn(); Text("Game State");
|
||||
TableNextColumn();
|
||||
ImGui::SetNextItemWidth(100.f);
|
||||
if (ImGui::Combo("##GameState", &game_state_, kGamePartComboString.data(), 3)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Sprite Graphics 1");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprGfx1",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_graphics(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Sprite Graphics 2");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprGfx2",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_graphics(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Sprite Palette 1");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprPal1",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_palette(1),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Sprite Palette 2");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##SprPal2",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_sprite_palette(2),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
EndTabItem();
|
||||
}
|
||||
|
||||
// Custom Overworld Features Tab
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version != 0xFF && BeginTabItem("Custom Features")) {
|
||||
if (BeginTable("CustomFeatures", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Property", ImGuiTableColumnFlags_WidthFixed, 150);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextColumn(); Text("Area Size");
|
||||
TableNextColumn();
|
||||
static const char *area_size_names[] = {"Small (1x1)", "Large (2x2)", "Wide (2x1)", "Tall (1x2)"};
|
||||
int current_area_size = static_cast<int>(overworld_.overworld_map(current_map_)->area_size());
|
||||
ImGui::SetNextItemWidth(120.f);
|
||||
if (ImGui::Combo("##AreaSize", ¤t_area_size, area_size_names, 4)) {
|
||||
overworld_.mutable_overworld_map(current_map_)->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_area_size));
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
if (asm_version >= 2) {
|
||||
TableNextColumn(); Text("Main Palette");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##MainPal",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_main_palette(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
status_ = RefreshMapPalette();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
if (asm_version >= 3) {
|
||||
TableNextColumn(); Text("Animated GFX");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte("##AnimGfx",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_animated_gfx(),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn(); Text("Subscreen Overlay");
|
||||
TableNextColumn();
|
||||
if (gui::InputHexWord("##SubOverlay",
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_subscreen_overlay(),
|
||||
kInputFieldSize + 20)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
Separator();
|
||||
|
||||
// Quick action buttons
|
||||
ImGui::BeginGroup();
|
||||
if (Button("Custom Background Color")) {
|
||||
show_custom_bg_color_editor_ = !show_custom_bg_color_editor_;
|
||||
}
|
||||
SameLine();
|
||||
if (Button("Overlay Settings")) {
|
||||
show_overlay_editor_ = !show_overlay_editor_;
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
|
||||
EndTabItem();
|
||||
}
|
||||
|
||||
// Tile Graphics Tab
|
||||
if (BeginTabItem("Tile Graphics")) {
|
||||
Text("Custom Tile Graphics (8 sheets per map):");
|
||||
Separator();
|
||||
|
||||
if (BeginTable("TileGraphics", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit)) {
|
||||
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
ImGui::TableSetupColumn("Sheet", ImGuiTableColumnFlags_WidthFixed, 60);
|
||||
ImGui::TableSetupColumn("GFX ID", ImGuiTableColumnFlags_WidthFixed, 80);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
TableNextColumn();
|
||||
Text("Sheet %d", i);
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i).c_str(),
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_custom_tileset(i),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
|
||||
TableNextColumn();
|
||||
Text("Sheet %d", i + 4);
|
||||
TableNextColumn();
|
||||
if (gui::InputHexByte(absl::StrFormat("##TileGfx%d", i + 4).c_str(),
|
||||
overworld_.mutable_overworld_map(current_map_)->mutable_custom_tileset(i + 4),
|
||||
kInputFieldSize)) {
|
||||
RefreshMapProperties();
|
||||
RefreshOverworldMap();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
EndTabItem();
|
||||
}
|
||||
|
||||
EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
void OverworldEditor::SetupOverworldCanvasContextMenu() {
|
||||
// Clear any existing context menu items
|
||||
ow_map_canvas_.ClearContextMenuItems();
|
||||
|
||||
// Add overworld-specific context menu items
|
||||
gui::Canvas::ContextMenuItem lock_item;
|
||||
lock_item.label = current_map_lock_ ? "Unlock Map" : "Lock to This Map";
|
||||
lock_item.callback = [this]() {
|
||||
current_map_lock_ = !current_map_lock_;
|
||||
if (current_map_lock_) {
|
||||
// Get the current map from mouse position
|
||||
auto mouse_position = ow_map_canvas_.drawn_tile_position();
|
||||
int map_x = mouse_position.x / kOverworldMapSize;
|
||||
int map_y = mouse_position.y / kOverworldMapSize;
|
||||
int hovered_map = map_x + map_y * 8;
|
||||
if (current_world_ == 1) {
|
||||
hovered_map += 0x40;
|
||||
} else if (current_world_ == 2) {
|
||||
hovered_map += 0x80;
|
||||
}
|
||||
if (hovered_map >= 0 && hovered_map < 0xA0) {
|
||||
current_map_ = hovered_map;
|
||||
}
|
||||
}
|
||||
};
|
||||
ow_map_canvas_.AddContextMenuItem(lock_item);
|
||||
|
||||
// Map Properties
|
||||
gui::Canvas::ContextMenuItem properties_item;
|
||||
properties_item.label = "Map Properties";
|
||||
properties_item.callback = [this]() {
|
||||
show_map_properties_panel_ = true;
|
||||
};
|
||||
ow_map_canvas_.AddContextMenuItem(properties_item);
|
||||
|
||||
// Custom overworld features (only show if v3+)
|
||||
static uint8_t asm_version = (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
if (asm_version >= 3 && asm_version != 0xFF) {
|
||||
// Custom Background Color
|
||||
gui::Canvas::ContextMenuItem bg_color_item;
|
||||
bg_color_item.label = "Custom Background Color";
|
||||
bg_color_item.callback = [this]() {
|
||||
show_custom_bg_color_editor_ = true;
|
||||
};
|
||||
ow_map_canvas_.AddContextMenuItem(bg_color_item);
|
||||
|
||||
// Overlay Settings
|
||||
gui::Canvas::ContextMenuItem overlay_item;
|
||||
overlay_item.label = "Overlay Settings";
|
||||
overlay_item.callback = [this]() {
|
||||
show_overlay_editor_ = true;
|
||||
};
|
||||
ow_map_canvas_.AddContextMenuItem(overlay_item);
|
||||
}
|
||||
|
||||
// Canvas controls
|
||||
gui::Canvas::ContextMenuItem reset_pos_item;
|
||||
reset_pos_item.label = "Reset Canvas Position";
|
||||
reset_pos_item.callback = [this]() {
|
||||
ow_map_canvas_.set_scrolling(ImVec2(0, 0));
|
||||
};
|
||||
ow_map_canvas_.AddContextMenuItem(reset_pos_item);
|
||||
|
||||
gui::Canvas::ContextMenuItem zoom_fit_item;
|
||||
zoom_fit_item.label = "Zoom to Fit";
|
||||
zoom_fit_item.callback = [this]() {
|
||||
ow_map_canvas_.set_global_scale(1.0f);
|
||||
ow_map_canvas_.set_scrolling(ImVec2(0, 0));
|
||||
};
|
||||
ow_map_canvas_.AddContextMenuItem(zoom_fit_item);
|
||||
}
|
||||
|
||||
void OverworldEditor::DrawOverworldProperties() {
|
||||
static bool init_properties = false;
|
||||
|
||||
|
||||
@@ -162,6 +162,10 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
||||
void DrawOverlayEditor();
|
||||
void DrawMapLockControls();
|
||||
void DrawOverworldContextMenu();
|
||||
void DrawSimplifiedMapSettings();
|
||||
void DrawMapPropertiesPanel();
|
||||
void HandleMapInteraction();
|
||||
void SetupOverworldCanvasContextMenu();
|
||||
|
||||
absl::Status UpdateUsageStats();
|
||||
void DrawUsageGrid();
|
||||
@@ -222,6 +226,7 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
||||
bool show_custom_bg_color_editor_ = false;
|
||||
bool show_overlay_editor_ = false;
|
||||
bool use_area_specific_bg_color_ = false;
|
||||
bool show_map_properties_panel_ = false;
|
||||
|
||||
gfx::Tilemap tile16_blockset_;
|
||||
|
||||
|
||||
@@ -123,6 +123,17 @@ void Canvas::DrawContextMenu() {
|
||||
|
||||
// Contents of the Context Menu
|
||||
if (ImGui::BeginPopup(context_id_.c_str())) {
|
||||
// Draw custom context menu items first
|
||||
for (const auto& item : context_menu_items_) {
|
||||
DrawContextMenuItem(item);
|
||||
}
|
||||
|
||||
// Add separator if there are custom items
|
||||
if (!context_menu_items_.empty()) {
|
||||
ImGui::Separator();
|
||||
}
|
||||
|
||||
// Default canvas menu items
|
||||
if (MenuItem("Reset Position", nullptr, false)) {
|
||||
scrolling_.x = 0;
|
||||
scrolling_.y = 0;
|
||||
@@ -216,6 +227,39 @@ void Canvas::DrawContextMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::DrawContextMenuItem(const ContextMenuItem& item) {
|
||||
if (!item.enabled_condition()) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
|
||||
if (item.subitems.empty()) {
|
||||
// Simple menu item
|
||||
if (ImGui::MenuItem(item.label.c_str(), item.shortcut.empty() ? nullptr : item.shortcut.c_str())) {
|
||||
item.callback();
|
||||
}
|
||||
} else {
|
||||
// Menu with subitems
|
||||
if (ImGui::BeginMenu(item.label.c_str())) {
|
||||
for (const auto& subitem : item.subitems) {
|
||||
DrawContextMenuItem(subitem);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.enabled_condition()) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::AddContextMenuItem(const ContextMenuItem& item) {
|
||||
context_menu_items_.push_back(item);
|
||||
}
|
||||
|
||||
void Canvas::ClearContextMenuItems() {
|
||||
context_menu_items_.clear();
|
||||
}
|
||||
|
||||
bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) {
|
||||
const ImGuiIO &io = GetIO();
|
||||
const bool is_hovered = IsItemHovered();
|
||||
|
||||
@@ -91,37 +91,39 @@ class Canvas {
|
||||
// Context Menu refers to what happens when the right mouse button is pressed
|
||||
// This routine also handles the scrolling for the canvas.
|
||||
void DrawContextMenu();
|
||||
|
||||
// Context menu system for consumers to add their own menu elements
|
||||
struct ContextMenuItem {
|
||||
std::string label;
|
||||
std::string shortcut;
|
||||
std::function<void()> callback;
|
||||
std::function<bool()> enabled_condition = []() { return true; };
|
||||
std::vector<ContextMenuItem> subitems;
|
||||
};
|
||||
|
||||
void AddContextMenuItem(const ContextMenuItem& item);
|
||||
void ClearContextMenuItems();
|
||||
void SetContextMenuEnabled(bool enabled) { context_menu_enabled_ = enabled; }
|
||||
|
||||
private:
|
||||
void DrawContextMenuItem(const ContextMenuItem& item);
|
||||
|
||||
// Tile painter shows a preview of the currently selected tile
|
||||
// and allows the user to left click to paint the tile or right
|
||||
// click to select a new tile to paint with.
|
||||
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale = 1.0f);
|
||||
bool DrawSolidTilePainter(const ImVec4 &color, int size);
|
||||
// (Moved to public section)
|
||||
|
||||
// Draws a tile on the canvas at the specified position
|
||||
// (Moved to public section)
|
||||
|
||||
// These methods are now public - see public section above
|
||||
|
||||
public:
|
||||
// Tile painter methods
|
||||
bool DrawTilePainter(const Bitmap &bitmap, int size, float scale = 1.0f);
|
||||
bool DrawSolidTilePainter(const ImVec4 &color, int size);
|
||||
void DrawTileOnBitmap(int tile_size, gfx::Bitmap *bitmap, ImVec4 color);
|
||||
|
||||
// Dictates which tile is currently selected based on what the user clicks
|
||||
// in the canvas window. Represented and split apart into a grid of tiles.
|
||||
bool DrawTileSelector(int size, int size_y = 0);
|
||||
|
||||
// Draws the selection rectangle when the user is selecting multiple tiles
|
||||
void DrawSelectRect(int current_map, int tile_size = 0x10,
|
||||
float scale = 1.0f);
|
||||
|
||||
// Draws the contents of the Bitmap image to the Canvas
|
||||
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale);
|
||||
void DrawBitmap(Bitmap &bitmap, int x_offset, int y_offset,
|
||||
float scale = 1.0f, int alpha = 255);
|
||||
void DrawBitmap(Bitmap &bitmap, ImVec2 dest_pos, ImVec2 dest_size,
|
||||
ImVec2 src_pos, ImVec2 src_size);
|
||||
void DrawBitmapTable(const BitmapTable &gfx_bin);
|
||||
|
||||
void DrawBitmapGroup(std::vector<int> &group, gfx::Tilemap &tilemap,
|
||||
int tile_size, float scale = 1.0f);
|
||||
|
||||
bool DrawTilemapPainter(gfx::Tilemap &tilemap, int current_tile);
|
||||
|
||||
|
||||
void DrawOutline(int x, int y, int w, int h);
|
||||
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color);
|
||||
void DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color);
|
||||
@@ -130,8 +132,6 @@ class Canvas {
|
||||
|
||||
void DrawText(std::string text, int x, int y);
|
||||
void DrawGridLines(float grid_step);
|
||||
void DrawGrid(float grid_step = 64.0f, int tile_id_offset = 8);
|
||||
void DrawOverlay(); // last
|
||||
|
||||
void DrawInfoGrid(float grid_step = 64.0f, int tile_id_offset = 8,
|
||||
int label_id = 0);
|
||||
@@ -150,10 +150,6 @@ class Canvas {
|
||||
}
|
||||
return tile_id;
|
||||
}
|
||||
void SetCanvasSize(ImVec2 canvas_size) {
|
||||
canvas_sz_ = canvas_size;
|
||||
custom_canvas_size_ = true;
|
||||
}
|
||||
void DrawCustomHighlight(float grid_step);
|
||||
bool IsMouseHovering() const { return is_hovered_; }
|
||||
void ZoomIn() { global_scale_ += 0.25f; }
|
||||
@@ -169,13 +165,36 @@ class Canvas {
|
||||
auto drawn_tile_position() const { return drawn_tile_pos_; }
|
||||
auto canvas_size() const { return canvas_sz_; }
|
||||
void set_global_scale(float scale) { global_scale_ = scale; }
|
||||
void set_draggable(bool draggable) { draggable_ = draggable; }
|
||||
|
||||
// Public accessors for commonly used private members
|
||||
auto select_rect_active() const { return select_rect_active_; }
|
||||
auto selected_tiles() const { return selected_tiles_; }
|
||||
auto selected_tile_pos() const { return selected_tile_pos_; }
|
||||
void set_selected_tile_pos(ImVec2 pos) { selected_tile_pos_ = pos; }
|
||||
|
||||
// Public methods for commonly used private methods
|
||||
void SetCanvasSize(ImVec2 canvas_size) { canvas_sz_ = canvas_size; custom_canvas_size_ = true; }
|
||||
auto global_scale() const { return global_scale_; }
|
||||
auto custom_labels_enabled() { return &enable_custom_labels_; }
|
||||
auto custom_step() const { return custom_step_; }
|
||||
auto width() const { return canvas_sz_.x; }
|
||||
auto height() const { return canvas_sz_.y; }
|
||||
auto set_draggable(bool value) { draggable_ = value; }
|
||||
|
||||
// Public accessors for methods that need to be accessed externally
|
||||
auto canvas_id() const { return canvas_id_; }
|
||||
|
||||
// Public methods for drawing operations
|
||||
void DrawBitmap(Bitmap &bitmap, int border_offset, float scale);
|
||||
void DrawBitmap(Bitmap &bitmap, int x_offset, int y_offset, float scale = 1.0f, int alpha = 255);
|
||||
void DrawBitmap(Bitmap &bitmap, ImVec2 dest_pos, ImVec2 dest_size, ImVec2 src_pos, ImVec2 src_size);
|
||||
void DrawBitmapTable(const BitmapTable &gfx_bin);
|
||||
void DrawBitmapGroup(std::vector<int> &group, gfx::Tilemap &tilemap, int tile_size, float scale = 1.0f);
|
||||
bool DrawTilemapPainter(gfx::Tilemap &tilemap, int current_tile);
|
||||
void DrawSelectRect(int current_map, int tile_size = 0x10, float scale = 1.0f);
|
||||
bool DrawTileSelector(int size, int size_y = 0);
|
||||
void DrawGrid(float grid_step = 64.0f, int tile_id_offset = 8);
|
||||
void DrawOverlay();
|
||||
auto labels(int i) {
|
||||
if (i >= labels_.size()) {
|
||||
labels_.push_back(ImVector<std::string>());
|
||||
@@ -197,12 +216,7 @@ class Canvas {
|
||||
auto set_current_labels(int i) { current_labels_ = i; }
|
||||
auto set_highlight_tile_id(int i) { highlight_tile_id = i; }
|
||||
|
||||
auto selected_tiles() const { return selected_tiles_; }
|
||||
auto mutable_selected_tiles() { return &selected_tiles_; }
|
||||
|
||||
auto selected_tile_pos() const { return selected_tile_pos_; }
|
||||
auto set_selected_tile_pos(ImVec2 pos) { selected_tile_pos_ = pos; }
|
||||
bool select_rect_active() const { return select_rect_active_; }
|
||||
auto selected_points() const { return selected_points_; }
|
||||
|
||||
auto hover_mouse_pos() const { return mouse_pos_in_canvas_; }
|
||||
@@ -221,6 +235,10 @@ class Canvas {
|
||||
bool select_rect_active_ = false;
|
||||
bool refresh_graphics_ = false;
|
||||
|
||||
// Context menu system
|
||||
std::vector<ContextMenuItem> context_menu_items_;
|
||||
bool context_menu_enabled_ = true;
|
||||
|
||||
float custom_step_ = 0.0f;
|
||||
float global_scale_ = 1.0f;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user