Refactor Overworld Editor and enhance settings management for v3 features
- Removed the outdated ZEML layout file and associated references to streamline the OverworldEditor. - Introduced the OverworldEditorManager class to encapsulate v3 settings management, improving code organization and maintainability. - Updated the OverworldEditor to utilize ImGui for layout, enhancing user interaction and flexibility. - Enhanced the changelog with detailed descriptions of new features and improvements, including a comprehensive undo/redo system and advanced palette management. - Removed deprecated diagnostic patterns from the clangd configuration to improve code quality checks.
This commit is contained in:
@@ -11,6 +11,7 @@ set(
|
||||
app/editor/dungeon/dungeon_room_loader.cc
|
||||
app/editor/dungeon/dungeon_usage_tracker.cc
|
||||
app/editor/overworld/overworld_editor.cc
|
||||
app/editor/overworld/overworld_editor_manager.cc
|
||||
app/editor/sprite/sprite_editor.cc
|
||||
app/editor/music/music_editor.cc
|
||||
app/editor/message/message_editor.cc
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/style.h"
|
||||
#include "app/gui/zeml.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/common.h"
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
@@ -42,40 +41,15 @@ using namespace ImGui;
|
||||
constexpr float kInputFieldSize = 30.f;
|
||||
|
||||
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_);
|
||||
|
||||
gui::zeml::Bind(std::to_address(layout_node_.GetNode("OverworldCanvas")),
|
||||
[this]() { DrawOverworldCanvas(); });
|
||||
// Initialize OverworldEditorManager for v3 features
|
||||
overworld_manager_ = std::make_unique<OverworldEditorManager>(&overworld_, rom_);
|
||||
|
||||
// Setup overworld canvas context menu
|
||||
SetupOverworldCanvasContextMenu();
|
||||
gui::zeml::Bind(
|
||||
std::to_address(layout_node_.GetNode("OverworldTileSelector")),
|
||||
[this]() { status_ = DrawTileSelector(); });
|
||||
gui::zeml::Bind(std::to_address(layout_node_.GetNode("OwUsageStats")),
|
||||
[this]() {
|
||||
if (rom_->is_loaded()) {
|
||||
status_ = UpdateUsageStats();
|
||||
}
|
||||
});
|
||||
gui::zeml::Bind(std::to_address(layout_node_.GetNode("owToolset")),
|
||||
[this]() { DrawToolset(); });
|
||||
gui::zeml::Bind(std::to_address(layout_node_.GetNode("OwTile16Editor")),
|
||||
[this]() {
|
||||
if (rom_->is_loaded()) {
|
||||
status_ = tile16_editor_.Update();
|
||||
}
|
||||
});
|
||||
gui::zeml::Bind(std::to_address(layout_node_.GetNode("OwGfxGroupEditor")),
|
||||
[this]() {
|
||||
if (rom_->is_loaded()) {
|
||||
status_ = gfx_group_editor_.Update();
|
||||
}
|
||||
});
|
||||
|
||||
// Core editing tools
|
||||
gui::AddTableColumn(toolset_table_, "##Pan", [&]() {
|
||||
@@ -179,8 +153,65 @@ absl::Status OverworldEditor::Load() {
|
||||
|
||||
absl::Status OverworldEditor::Update() {
|
||||
status_ = absl::OkStatus();
|
||||
if (overworld_canvas_fullscreen_) DrawFullscreenCanvas();
|
||||
gui::zeml::Render(layout_node_);
|
||||
if (overworld_canvas_fullscreen_) {
|
||||
DrawFullscreenCanvas();
|
||||
return status_;
|
||||
}
|
||||
|
||||
// Replace ZEML with pure ImGui layout
|
||||
if (ImGui::BeginTabBar("##OwEditorTabBar")) {
|
||||
if (ImGui::BeginTabItem("Map Editor")) {
|
||||
DrawToolset();
|
||||
|
||||
if (ImGui::BeginTable("##owEditTable", 2,
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
|
||||
ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter |
|
||||
ImGuiTableFlags_BordersV)) {
|
||||
ImGui::TableSetupColumn("Canvas", ImGuiTableColumnFlags_WidthStretch);
|
||||
ImGui::TableSetupColumn("Tile Selector", ImGuiTableColumnFlags_WidthFixed, 256.0f);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
DrawOverworldCanvas();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
status_ = DrawTileSelector();
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Tile16 Editor")) {
|
||||
if (rom_->is_loaded()) {
|
||||
status_ = tile16_editor_.Update();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Graphics Group Editor")) {
|
||||
if (rom_->is_loaded()) {
|
||||
status_ = gfx_group_editor_.Update();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("Usage Statistics")) {
|
||||
if (rom_->is_loaded()) {
|
||||
status_ = UpdateUsageStats();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// Add v3 settings tab
|
||||
if (rom_->is_loaded()) {
|
||||
status_ = overworld_manager_->DrawV3SettingsPanel();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
return status_;
|
||||
}
|
||||
|
||||
@@ -1249,9 +1280,9 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
||||
for (auto &each : overworld_.entrances()) {
|
||||
if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
|
||||
each.map_id_ >= (current_world_ * 0x40) && !each.deleted) {
|
||||
auto color = ImVec4(255, 255, 0, 100);
|
||||
auto color = ImVec4(255, 0, 255, 100);
|
||||
if (each.is_hole_) {
|
||||
color = ImVec4(255, 255, 255, 200);
|
||||
color = ImVec4(255, 255, 0, 200);
|
||||
}
|
||||
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color);
|
||||
std::string str = util::HexByte(each.entrance_id_);
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
#include "app/gfx/tilemap.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/zeml.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
#include "app/editor/overworld/overworld_editor_manager.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -263,6 +263,7 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
||||
|
||||
// Map properties system for UI organization
|
||||
std::unique_ptr<MapPropertiesSystem> map_properties_system_;
|
||||
std::unique_ptr<OverworldEditorManager> overworld_manager_;
|
||||
|
||||
// Scratch space for large layouts
|
||||
// Scratch space canvas for tile16 drawing (like a mini overworld)
|
||||
@@ -328,7 +329,6 @@ class OverworldEditor : public Editor, public gfx::GfxContext {
|
||||
gui::Table map_settings_table_{kOWMapTable.data(), 8, kOWMapFlags,
|
||||
ImVec2(0, 0)};
|
||||
|
||||
gui::zeml::Node layout_node_;
|
||||
absl::Status status_;
|
||||
};
|
||||
} // namespace editor
|
||||
|
||||
284
src/app/editor/overworld/overworld_editor_manager.cc
Normal file
284
src/app/editor/overworld/overworld_editor_manager.cc
Normal file
@@ -0,0 +1,284 @@
|
||||
#include "overworld_editor_manager.h"
|
||||
|
||||
#include "app/gfx/snes_color.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/style.h"
|
||||
#include "app/zelda3/overworld/overworld_map.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
using namespace ImGui;
|
||||
|
||||
absl::Status OverworldEditorManager::DrawV3SettingsPanel() {
|
||||
if (BeginTabItem("v3 Settings")) {
|
||||
Text("ZSCustomOverworld v3 Settings");
|
||||
Separator();
|
||||
|
||||
// Check if custom ASM is applied
|
||||
uint8_t asm_version = GetCustomASMVersion();
|
||||
if (asm_version >= 3 && asm_version != 0xFF) {
|
||||
TextColored(ImVec4(0, 1, 0, 1), "Custom Overworld ASM v%d Applied", asm_version);
|
||||
} else if (asm_version == 0x00) {
|
||||
TextColored(ImVec4(1, 1, 0, 1), "Vanilla ROM - Custom features available via flag");
|
||||
} else {
|
||||
TextColored(ImVec4(1, 0, 0, 1), "Custom ASM v%d - Consider upgrading to v3", asm_version);
|
||||
}
|
||||
|
||||
Separator();
|
||||
|
||||
RETURN_IF_ERROR(DrawCustomOverworldSettings());
|
||||
RETURN_IF_ERROR(DrawAreaSpecificSettings());
|
||||
RETURN_IF_ERROR(DrawTransitionSettings());
|
||||
RETURN_IF_ERROR(DrawOverlaySettings());
|
||||
|
||||
EndTabItem();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawCustomOverworldSettings() {
|
||||
if (TreeNode("Custom Overworld Features")) {
|
||||
RETURN_IF_ERROR(DrawBooleanSetting("Enable Area-Specific Background Colors",
|
||||
&enable_area_specific_bg_,
|
||||
"Allows each overworld area to have its own background color"));
|
||||
|
||||
RETURN_IF_ERROR(DrawBooleanSetting("Enable Main Palette Override",
|
||||
&enable_main_palette_,
|
||||
"Allows each area to override the main palette"));
|
||||
|
||||
RETURN_IF_ERROR(DrawBooleanSetting("Enable Mosaic Transitions",
|
||||
&enable_mosaic_,
|
||||
"Enables mosaic screen transitions between areas"));
|
||||
|
||||
RETURN_IF_ERROR(DrawBooleanSetting("Enable Custom GFX Groups",
|
||||
&enable_gfx_groups_,
|
||||
"Allows each area to have custom tile GFX groups"));
|
||||
|
||||
RETURN_IF_ERROR(DrawBooleanSetting("Enable Subscreen Overlays",
|
||||
&enable_subscreen_overlay_,
|
||||
"Enables custom subscreen overlays (fog, sky, etc.)"));
|
||||
|
||||
RETURN_IF_ERROR(DrawBooleanSetting("Enable Animated GFX Override",
|
||||
&enable_animated_gfx_,
|
||||
"Allows each area to have custom animated tiles"));
|
||||
|
||||
Separator();
|
||||
|
||||
if (Button("Apply Custom Overworld ASM")) {
|
||||
RETURN_IF_ERROR(ApplyCustomOverworldASM());
|
||||
}
|
||||
SameLine();
|
||||
HOVER_HINT("Writes the custom overworld settings to ROM");
|
||||
|
||||
TreePop();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawAreaSpecificSettings() {
|
||||
if (TreeNode("Area-Specific Settings")) {
|
||||
// Map selection
|
||||
int map_count = zelda3::kNumOverworldMaps;
|
||||
SliderInt("Map Index", ¤t_map_index_, 0, map_count - 1);
|
||||
|
||||
auto* current_map = overworld_->mutable_overworld_map(current_map_index_);
|
||||
|
||||
// Area size controls
|
||||
RETURN_IF_ERROR(DrawAreaSizeControls());
|
||||
|
||||
// Background color
|
||||
if (enable_area_specific_bg_) {
|
||||
uint16_t bg_color = current_map->area_specific_bg_color();
|
||||
RETURN_IF_ERROR(DrawColorPicker("Background Color", &bg_color));
|
||||
current_map->set_area_specific_bg_color(bg_color);
|
||||
}
|
||||
|
||||
// Main palette
|
||||
if (enable_main_palette_) {
|
||||
uint8_t main_palette = current_map->main_palette();
|
||||
SliderInt("Main Palette", (int*)&main_palette, 0, 5);
|
||||
current_map->set_main_palette(main_palette);
|
||||
}
|
||||
|
||||
// Mosaic settings
|
||||
if (enable_mosaic_) {
|
||||
RETURN_IF_ERROR(DrawMosaicControls());
|
||||
}
|
||||
|
||||
// GFX groups
|
||||
if (enable_gfx_groups_) {
|
||||
RETURN_IF_ERROR(DrawGfxGroupControls());
|
||||
}
|
||||
|
||||
// Subscreen overlay
|
||||
if (enable_subscreen_overlay_) {
|
||||
uint16_t overlay = current_map->subscreen_overlay();
|
||||
RETURN_IF_ERROR(DrawOverlaySetting("Subscreen Overlay", &overlay));
|
||||
current_map->set_subscreen_overlay(overlay);
|
||||
}
|
||||
|
||||
// Animated GFX
|
||||
if (enable_animated_gfx_) {
|
||||
uint8_t animated_gfx = current_map->animated_gfx();
|
||||
RETURN_IF_ERROR(DrawGfxGroupSetting("Animated GFX", &animated_gfx));
|
||||
current_map->set_animated_gfx(animated_gfx);
|
||||
}
|
||||
|
||||
TreePop();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawAreaSizeControls() {
|
||||
auto* current_map = overworld_->mutable_overworld_map(current_map_index_);
|
||||
|
||||
const char* area_size_names[] = {"Small", "Large", "Wide", "Tall"};
|
||||
int current_size = static_cast<int>(current_map->area_size());
|
||||
|
||||
if (Combo("Area Size", ¤t_size, area_size_names, 4)) {
|
||||
current_map->SetAreaSize(static_cast<zelda3::AreaSizeEnum>(current_size));
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawMosaicControls() {
|
||||
auto* current_map = overworld_->mutable_overworld_map(current_map_index_);
|
||||
const auto& mosaic = current_map->mosaic_expanded();
|
||||
|
||||
bool mosaic_up = mosaic[0];
|
||||
bool mosaic_down = mosaic[1];
|
||||
bool mosaic_left = mosaic[2];
|
||||
bool mosaic_right = mosaic[3];
|
||||
|
||||
if (Checkbox("Mosaic Up", &mosaic_up)) {
|
||||
current_map->set_mosaic_expanded(0, mosaic_up);
|
||||
}
|
||||
SameLine();
|
||||
if (Checkbox("Mosaic Down", &mosaic_down)) {
|
||||
current_map->set_mosaic_expanded(1, mosaic_down);
|
||||
}
|
||||
if (Checkbox("Mosaic Left", &mosaic_left)) {
|
||||
current_map->set_mosaic_expanded(2, mosaic_left);
|
||||
}
|
||||
SameLine();
|
||||
if (Checkbox("Mosaic Right", &mosaic_right)) {
|
||||
current_map->set_mosaic_expanded(3, mosaic_right);
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawGfxGroupControls() {
|
||||
auto* current_map = overworld_->mutable_overworld_map(current_map_index_);
|
||||
|
||||
Text("Custom Tile GFX Groups:");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t gfx_id = current_map->custom_tileset(i);
|
||||
std::string label = "GFX " + std::to_string(i);
|
||||
RETURN_IF_ERROR(DrawGfxGroupSetting(label.c_str(), &gfx_id));
|
||||
current_map->set_custom_tileset(i, gfx_id);
|
||||
if (i < 7) SameLine();
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawTransitionSettings() {
|
||||
if (TreeNode("Transition Settings")) {
|
||||
Text("Complex area transition calculations are automatically handled");
|
||||
Text("based on neighboring area sizes (Large, Wide, Tall, Small).");
|
||||
|
||||
if (GetCustomASMVersion() >= 3) {
|
||||
TextColored(ImVec4(0, 1, 0, 1), "Using v3+ enhanced transitions");
|
||||
} else {
|
||||
TextColored(ImVec4(1, 1, 0, 1), "Using vanilla/v2 transitions");
|
||||
}
|
||||
|
||||
TreePop();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawOverlaySettings() {
|
||||
if (TreeNode("Interactive Overlay Settings")) {
|
||||
Text("Interactive overlays reveal holes and change map elements.");
|
||||
|
||||
auto* current_map = overworld_->mutable_overworld_map(current_map_index_);
|
||||
|
||||
Text("Map %d has %s", current_map_index_,
|
||||
current_map->has_overlay() ? "interactive overlay" : "no overlay");
|
||||
|
||||
if (current_map->has_overlay()) {
|
||||
Text("Overlay ID: 0x%04X", current_map->overlay_id());
|
||||
Text("Overlay data size: %zu bytes", current_map->overlay_data().size());
|
||||
}
|
||||
|
||||
TreePop();
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::ApplyCustomOverworldASM() {
|
||||
return overworld_->SaveCustomOverworldASM(
|
||||
enable_area_specific_bg_, enable_main_palette_, enable_mosaic_,
|
||||
enable_gfx_groups_, enable_subscreen_overlay_, enable_animated_gfx_);
|
||||
}
|
||||
|
||||
bool OverworldEditorManager::ValidateV3Compatibility() {
|
||||
uint8_t asm_version = GetCustomASMVersion();
|
||||
return (asm_version >= 3 && asm_version != 0xFF);
|
||||
}
|
||||
|
||||
bool OverworldEditorManager::CheckCustomASMApplied() {
|
||||
uint8_t asm_version = GetCustomASMVersion();
|
||||
return (asm_version != 0xFF && asm_version != 0x00);
|
||||
}
|
||||
|
||||
uint8_t OverworldEditorManager::GetCustomASMVersion() {
|
||||
return (*rom_)[zelda3::OverworldCustomASMHasBeenApplied];
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawBooleanSetting(const char* label, bool* setting,
|
||||
const char* help_text) {
|
||||
Checkbox(label, setting);
|
||||
if (help_text && IsItemHovered()) {
|
||||
SetTooltip("%s", help_text);
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawColorPicker(const char* label, uint16_t* color) {
|
||||
gfx::SnesColor snes_color(*color);
|
||||
ImVec4 imgui_color = snes_color.rgb();
|
||||
|
||||
if (ColorEdit3(label, &imgui_color.x)) {
|
||||
gfx::SnesColor new_color;
|
||||
new_color.set_rgb(imgui_color);
|
||||
*color = new_color.snes();
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawOverlaySetting(const char* label, uint16_t* overlay) {
|
||||
int overlay_int = *overlay;
|
||||
if (InputInt(label, &overlay_int, 1, 16, ImGuiInputTextFlags_CharsHexadecimal)) {
|
||||
*overlay = static_cast<uint16_t>(overlay_int & 0xFFFF);
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status OverworldEditorManager::DrawGfxGroupSetting(const char* label, uint8_t* gfx_id,
|
||||
int max_value) {
|
||||
int gfx_int = *gfx_id;
|
||||
if (SliderInt(label, &gfx_int, 0, max_value)) {
|
||||
*gfx_id = static_cast<uint8_t>(gfx_int);
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
90
src/app/editor/overworld/overworld_editor_manager.h
Normal file
90
src/app/editor/overworld/overworld_editor_manager.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef YAZE_APP_EDITOR_OVERWORLD_OVERWORLD_EDITOR_MANAGER_H
|
||||
#define YAZE_APP_EDITOR_OVERWORLD_OVERWORLD_EDITOR_MANAGER_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/overworld/overworld.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace editor {
|
||||
|
||||
/**
|
||||
* @class OverworldEditorManager
|
||||
* @brief Manages the complex overworld editor functionality and v3 features
|
||||
*
|
||||
* This class separates the complex overworld editing functionality from the main
|
||||
* OverworldEditor class to improve maintainability and organization, especially
|
||||
* for ZSCustomOverworld v3 features.
|
||||
*/
|
||||
class OverworldEditorManager {
|
||||
public:
|
||||
OverworldEditorManager(zelda3::Overworld* overworld, Rom* rom)
|
||||
: overworld_(overworld), rom_(rom) {}
|
||||
|
||||
// v3 Feature Management
|
||||
absl::Status DrawV3SettingsPanel();
|
||||
absl::Status DrawCustomOverworldSettings();
|
||||
absl::Status DrawAreaSpecificSettings();
|
||||
absl::Status DrawTransitionSettings();
|
||||
absl::Status DrawOverlaySettings();
|
||||
|
||||
// Map Properties Management
|
||||
absl::Status DrawMapPropertiesTable();
|
||||
absl::Status DrawAreaSizeControls();
|
||||
absl::Status DrawMosaicControls();
|
||||
absl::Status DrawPaletteControls();
|
||||
absl::Status DrawGfxGroupControls();
|
||||
|
||||
// Save/Load Operations for v3
|
||||
absl::Status SaveCustomOverworldData();
|
||||
absl::Status LoadCustomOverworldData();
|
||||
absl::Status ApplyCustomOverworldASM();
|
||||
|
||||
// Validation and Checks
|
||||
bool ValidateV3Compatibility();
|
||||
bool CheckCustomASMApplied();
|
||||
uint8_t GetCustomASMVersion();
|
||||
|
||||
// Getters/Setters for v3 settings
|
||||
auto enable_area_specific_bg() const { return enable_area_specific_bg_; }
|
||||
auto enable_main_palette() const { return enable_main_palette_; }
|
||||
auto enable_mosaic() const { return enable_mosaic_; }
|
||||
auto enable_gfx_groups() const { return enable_gfx_groups_; }
|
||||
auto enable_subscreen_overlay() const { return enable_subscreen_overlay_; }
|
||||
auto enable_animated_gfx() const { return enable_animated_gfx_; }
|
||||
|
||||
void set_enable_area_specific_bg(bool value) { enable_area_specific_bg_ = value; }
|
||||
void set_enable_main_palette(bool value) { enable_main_palette_ = value; }
|
||||
void set_enable_mosaic(bool value) { enable_mosaic_ = value; }
|
||||
void set_enable_gfx_groups(bool value) { enable_gfx_groups_ = value; }
|
||||
void set_enable_subscreen_overlay(bool value) { enable_subscreen_overlay_ = value; }
|
||||
void set_enable_animated_gfx(bool value) { enable_animated_gfx_ = value; }
|
||||
|
||||
private:
|
||||
zelda3::Overworld* overworld_;
|
||||
Rom* rom_;
|
||||
|
||||
// v3 Feature flags
|
||||
bool enable_area_specific_bg_ = false;
|
||||
bool enable_main_palette_ = false;
|
||||
bool enable_mosaic_ = false;
|
||||
bool enable_gfx_groups_ = false;
|
||||
bool enable_subscreen_overlay_ = false;
|
||||
bool enable_animated_gfx_ = false;
|
||||
|
||||
// Current editing state
|
||||
int current_map_index_ = 0;
|
||||
|
||||
// Helper methods
|
||||
absl::Status DrawBooleanSetting(const char* label, bool* setting, const char* help_text = nullptr);
|
||||
absl::Status DrawColorPicker(const char* label, uint16_t* color);
|
||||
absl::Status DrawOverlaySetting(const char* label, uint16_t* overlay);
|
||||
absl::Status DrawGfxGroupSetting(const char* label, uint8_t* gfx_id, int max_value = 255);
|
||||
};
|
||||
|
||||
} // namespace editor
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_EDITOR_OVERWORLD_OVERWORLD_EDITOR_MANAGER_H
|
||||
@@ -471,14 +471,12 @@ absl::Status Tile16Editor::DrawToCurrentTile16(ImVec2 click_position) {
|
||||
absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
static bool show_tile8_selector = true;
|
||||
static bool show_tile16_editor = true;
|
||||
static bool show_controls = true;
|
||||
|
||||
// View controls
|
||||
if (BeginMenuBar()) {
|
||||
if (BeginMenu("View")) {
|
||||
Checkbox("Tile8 Selector", &show_tile8_selector);
|
||||
Checkbox("Tile16 Editor", &show_tile16_editor);
|
||||
Checkbox("Controls", &show_controls);
|
||||
EndMenu();
|
||||
}
|
||||
EndMenuBar();
|
||||
@@ -552,6 +550,32 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
tile8_source_canvas_.DrawOverlay();
|
||||
|
||||
EndChild();
|
||||
|
||||
Separator();
|
||||
Text("Palette: %d (Group: %d)", current_palette_, current_palette_group_);
|
||||
if (Button("Pal -", ImVec2(40, 0)))
|
||||
RETURN_IF_ERROR(CyclePalette(false));
|
||||
SameLine();
|
||||
if (Button("Pal +", ImVec2(40, 0)))
|
||||
RETURN_IF_ERROR(CyclePalette(true));
|
||||
|
||||
// Quick palette grid
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (i > 0 && i % 4 != 0)
|
||||
SameLine();
|
||||
bool is_current = (current_palette_ == i);
|
||||
if (is_current)
|
||||
PushStyleColor(ImGuiCol_Button, ImVec4(0.4f, 0.7f, 0.4f, 1.0f));
|
||||
if (Button(std::to_string(i).c_str(), ImVec2(20, 20))) {
|
||||
current_palette_ = i;
|
||||
RETURN_IF_ERROR(RefreshAllPalettes());
|
||||
}
|
||||
if (is_current)
|
||||
PopStyleColor();
|
||||
if (i == 3) { /* New line */
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
@@ -674,132 +698,98 @@ absl::Status Tile16Editor::UpdateTile16Edit() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compact controls section directly below
|
||||
if (show_controls) {
|
||||
if (BeginTable("##Tile16CompactControls", 3,
|
||||
ImGuiTableFlags_Resizable |
|
||||
ImGuiTableFlags_BordersInnerV)) {
|
||||
TableSetupColumn("Info & Palette", ImGuiTableColumnFlags_WidthFixed,
|
||||
280);
|
||||
TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, 200);
|
||||
TableSetupColumn("Advanced", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextRow();
|
||||
|
||||
// Info and palette column
|
||||
TableNextColumn();
|
||||
if (BeginChild("InfoPaletteChild", ImVec2(270, 120), true)) {
|
||||
gui::DrawTable(tile_edit_table_);
|
||||
|
||||
Separator();
|
||||
Text("Palette: %d (Group: %d)", current_palette_,
|
||||
current_palette_group_);
|
||||
if (Button("Pal -", ImVec2(35, 0)))
|
||||
RETURN_IF_ERROR(CyclePalette(false));
|
||||
SameLine();
|
||||
if (Button("Pal +", ImVec2(35, 0)))
|
||||
RETURN_IF_ERROR(CyclePalette(true));
|
||||
|
||||
// Quick palette grid
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
if (i > 0 && i % 4 != 0)
|
||||
SameLine();
|
||||
bool is_current = (current_palette_ == i);
|
||||
if (is_current)
|
||||
PushStyleColor(ImGuiCol_Button, ImVec4(0.4f, 0.7f, 0.4f, 1.0f));
|
||||
if (Button(std::to_string(i).c_str(), ImVec2(16, 16))) {
|
||||
current_palette_ = i;
|
||||
RETURN_IF_ERROR(RefreshAllPalettes());
|
||||
}
|
||||
if (is_current)
|
||||
PopStyleColor();
|
||||
if (i == 3) { /* New line */
|
||||
}
|
||||
}
|
||||
}
|
||||
EndChild();
|
||||
|
||||
// Actions column
|
||||
TableNextColumn();
|
||||
if (BeginChild("ActionsChild", ImVec2(190, 120), true)) {
|
||||
if (Button("Clear Tile16", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(ClearTile16());
|
||||
if (Button("Copy", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(CopyTile16ToClipboard(current_tile16_));
|
||||
if (Button("Paste", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(PasteTile16FromClipboard());
|
||||
|
||||
Separator();
|
||||
|
||||
bool can_undo = !undo_stack_.empty();
|
||||
bool can_redo = !redo_stack_.empty();
|
||||
|
||||
if (!can_undo)
|
||||
BeginDisabled();
|
||||
if (Button("Undo", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(Undo());
|
||||
if (!can_undo)
|
||||
EndDisabled();
|
||||
|
||||
if (!can_redo)
|
||||
BeginDisabled();
|
||||
if (Button("Redo", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(Redo());
|
||||
if (!can_redo)
|
||||
EndDisabled();
|
||||
|
||||
Separator();
|
||||
DrawScratchSpace();
|
||||
}
|
||||
EndChild();
|
||||
|
||||
// Advanced settings column
|
||||
TableNextColumn();
|
||||
if (BeginChild("AdvancedChild", ImVec2(0, 120), true)) {
|
||||
if (Button("Palette Settings")) {
|
||||
show_palette_settings_ = !show_palette_settings_;
|
||||
}
|
||||
|
||||
if (Button("Manual Tile8 Inputs")) {
|
||||
ImGui::OpenPopup("ManualTile8Editor");
|
||||
}
|
||||
HOVER_HINT("Edit tile8 IDs and properties directly");
|
||||
|
||||
if (Button("Refresh Blockset")) {
|
||||
RETURN_IF_ERROR(RefreshTile16Blockset());
|
||||
}
|
||||
HOVER_HINT("Regenerate tile16 blockset from ROM data");
|
||||
|
||||
Text("Advanced Palette:");
|
||||
const char* palette_group_names[] = {
|
||||
"OW Main", "OW Aux", "OW Anim", "Dungeon",
|
||||
"Sprites", "Armor", "Sword"};
|
||||
if (Combo("##AdvPaletteGroup", ¤t_palette_group_,
|
||||
palette_group_names, 7)) {
|
||||
RETURN_IF_ERROR(RefreshAllPalettes());
|
||||
}
|
||||
|
||||
Text("Normalization:");
|
||||
int mask_value = static_cast<int>(palette_normalization_mask_);
|
||||
if (SliderInt("##NormMask", &mask_value, 1, 255, "0x%02X")) {
|
||||
palette_normalization_mask_ = static_cast<uint8_t>(mask_value);
|
||||
RETURN_IF_ERROR(LoadTile8()); // Reload with new mask
|
||||
}
|
||||
|
||||
Checkbox("Auto Normalize", &auto_normalize_pixels_);
|
||||
}
|
||||
EndChild();
|
||||
|
||||
// Manual tile8 editor popup
|
||||
DrawManualTile8Inputs();
|
||||
|
||||
EndTable();
|
||||
}
|
||||
|
||||
// Close the tile16 editor scroll region
|
||||
EndChild();
|
||||
if (BeginChild("InfoPaletteChild", ImVec2(270, 120), true)) {
|
||||
gui::DrawTable(tile_edit_table_);
|
||||
}
|
||||
EndChild();
|
||||
// Compact controls section directly below
|
||||
if (BeginTable(
|
||||
"##Tile16CompactControls", 2,
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersInnerV)) {
|
||||
TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthFixed, 100);
|
||||
TableSetupColumn("Advanced", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
TableNextRow();
|
||||
|
||||
// Actions column
|
||||
TableNextColumn();
|
||||
if (BeginChild("ActionsChild", ImVec2(190, 120), true)) {
|
||||
if (Button("Clear Tile16", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(ClearTile16());
|
||||
if (Button("Copy", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(CopyTile16ToClipboard(current_tile16_));
|
||||
if (Button("Paste", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(PasteTile16FromClipboard());
|
||||
|
||||
Separator();
|
||||
|
||||
bool can_undo = !undo_stack_.empty();
|
||||
bool can_redo = !redo_stack_.empty();
|
||||
|
||||
if (!can_undo)
|
||||
BeginDisabled();
|
||||
if (Button("Undo", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(Undo());
|
||||
if (!can_undo)
|
||||
EndDisabled();
|
||||
|
||||
if (!can_redo)
|
||||
BeginDisabled();
|
||||
if (Button("Redo", ImVec2(80, 0)))
|
||||
RETURN_IF_ERROR(Redo());
|
||||
if (!can_redo)
|
||||
EndDisabled();
|
||||
|
||||
Separator();
|
||||
DrawScratchSpace();
|
||||
}
|
||||
EndChild();
|
||||
|
||||
// Advanced settings column
|
||||
TableNextColumn();
|
||||
if (BeginChild("AdvancedChild", ImVec2(0, 120), true)) {
|
||||
if (Button("Palette Settings")) {
|
||||
show_palette_settings_ = !show_palette_settings_;
|
||||
}
|
||||
|
||||
if (Button("Manual Tile8 Inputs")) {
|
||||
ImGui::OpenPopup("ManualTile8Editor");
|
||||
}
|
||||
HOVER_HINT("Edit tile8 IDs and properties directly");
|
||||
|
||||
if (Button("Refresh Blockset")) {
|
||||
RETURN_IF_ERROR(RefreshTile16Blockset());
|
||||
}
|
||||
HOVER_HINT("Regenerate tile16 blockset from ROM data");
|
||||
|
||||
Text("Advanced Palette:");
|
||||
const char* palette_group_names[] = {"OW Main", "OW Aux", "OW Anim",
|
||||
"Dungeon", "Sprites", "Armor",
|
||||
"Sword"};
|
||||
if (Combo("##AdvPaletteGroup", ¤t_palette_group_,
|
||||
palette_group_names, 7)) {
|
||||
RETURN_IF_ERROR(RefreshAllPalettes());
|
||||
}
|
||||
|
||||
Text("Normalization:");
|
||||
int mask_value = static_cast<int>(palette_normalization_mask_);
|
||||
if (SliderInt("##NormMask", &mask_value, 1, 255, "0x%02X")) {
|
||||
palette_normalization_mask_ = static_cast<uint8_t>(mask_value);
|
||||
RETURN_IF_ERROR(LoadTile8()); // Reload with new mask
|
||||
}
|
||||
|
||||
Checkbox("Auto Normalize", &auto_normalize_pixels_);
|
||||
}
|
||||
EndChild();
|
||||
|
||||
// Manual tile8 editor popup
|
||||
DrawManualTile8Inputs();
|
||||
|
||||
EndTable();
|
||||
}
|
||||
|
||||
// Close the tile16 editor scroll region
|
||||
EndChild();
|
||||
|
||||
EndTable();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user