refactor(gui): reorganize GUI includes and introduce new components
- Updated include paths for various GUI-related headers to improve organization and clarity. - Introduced new components for better modularity, including PaletteEditorWidget and EditorCardManager. - Refactored existing code to utilize the new components, ensuring consistency across the GUI subsystem. Benefits: - Enhances maintainability and readability of the GUI code. - Facilitates future enhancements and optimizations within the GUI subsystem.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#include "app/gui/widgets/agent_chat_widget.h"
|
||||
#include "app/gui/app/agent_chat_widget.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -1,10 +1,10 @@
|
||||
#include "app/gui/background_renderer.h"
|
||||
#include "app/gui/app/background_renderer.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "app/core/timing.h"
|
||||
#include "app/gui/theme_manager.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
#ifndef M_PI
|
||||
@@ -2,7 +2,11 @@
|
||||
#define YAZE_APP_EDITOR_UI_BACKGROUND_RENDERER_H
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#include "app/gui/color.h"
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "app/gui/core/color.h"
|
||||
#include "app/rom.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "app/gui/widgets/collaboration_panel.h"
|
||||
#include "app/gui/app/collaboration_panel.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctime>
|
||||
@@ -4,8 +4,8 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/theme_manager.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -1,13 +1,13 @@
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
#include "app/gui/editor_layout.h"
|
||||
#include "app/gui/app/editor_layout.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/input.h"
|
||||
#include "app/gui/ui_helpers.h"
|
||||
#include "app/gui/widgets/widget_measurement.h"
|
||||
#include "app/gui/widgets/widget_id_registry.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "app/gui/core/input.h"
|
||||
#include "app/gui/core/ui_helpers.h"
|
||||
#include "app/gui/automation/widget_measurement.h"
|
||||
#include "app/gui/automation/widget_id_registry.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/imgui_internal.h"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "app/gui/widgets/widget_auto_register.h"
|
||||
#include "app/gui/automation/widget_auto_register.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef YAZE_APP_GUI_WIDGETS_WIDGET_AUTO_REGISTER_H_
|
||||
#define YAZE_APP_GUI_WIDGETS_WIDGET_AUTO_REGISTER_H_
|
||||
#ifndef YAZE_APP_GUI_AUTOMATION_WIDGET_AUTO_REGISTER_H_
|
||||
#define YAZE_APP_GUI_AUTOMATION_WIDGET_AUTO_REGISTER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "imgui/imgui.h"
|
||||
#include "app/gui/widgets/widget_id_registry.h"
|
||||
#include "app/gui/automation/widget_id_registry.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
|
||||
/**
|
||||
@@ -260,5 +260,5 @@ inline void RegisterTable(const char* table_name, const std::string& description
|
||||
} // namespace gui
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_GUI_WIDGETS_WIDGET_AUTO_REGISTER_H_
|
||||
#endif // YAZE_APP_GUI_AUTOMATION_WIDGET_AUTO_REGISTER_H_
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "app/gui/widgets/widget_id_registry.h"
|
||||
#include "app/gui/automation/widget_id_registry.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef YAZE_APP_GUI_WIDGETS_WIDGET_ID_REGISTRY_H_
|
||||
#define YAZE_APP_GUI_WIDGETS_WIDGET_ID_REGISTRY_H_
|
||||
#ifndef YAZE_APP_GUI_AUTOMATION_WIDGET_ID_REGISTRY_H_
|
||||
#define YAZE_APP_GUI_AUTOMATION_WIDGET_ID_REGISTRY_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
@@ -173,4 +173,4 @@ class WidgetIdRegistry {
|
||||
} // namespace gui
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_GUI_WIDGETS_WIDGET_ID_REGISTRY_H_
|
||||
#endif // YAZE_APP_GUI_AUTOMATION_WIDGET_ID_REGISTRY_H_
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "app/gui/widgets/widget_measurement.h"
|
||||
#include "app/gui/automation/widget_measurement.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "imgui/imgui.h"
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "app/gui/widgets/widget_state_capture.h"
|
||||
#include "app/gui/automation/widget_state_capture.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#if defined(YAZE_ENABLE_IMGUI_TEST_ENGINE) && YAZE_ENABLE_IMGUI_TEST_ENGINE
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "app/gfx/util/bpp_format_manager.h"
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/gui/ui_helpers.h"
|
||||
#include "app/gui/core/ui_helpers.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include "app/gfx/util/bpp_format_manager.h"
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/gfx/debug/performance/performance_profiler.h"
|
||||
#include "app/gui/style.h"
|
||||
#include "canvas/canvas_utils.h"
|
||||
#include "canvas/canvas_automation_api.h"
|
||||
#include "app/gui/core/style.h"
|
||||
#include "app/gui/canvas/canvas_utils.h"
|
||||
#include "app/gui/canvas/canvas_automation_api.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze::gui {
|
||||
@@ -124,7 +124,7 @@ void Canvas::InitializeDefaults() {
|
||||
selection_.Clear();
|
||||
|
||||
// Initialize palette editor
|
||||
palette_editor_ = std::make_unique<PaletteWidget>();
|
||||
palette_editor_ = std::make_unique<PaletteEditorWidget>();
|
||||
|
||||
// Initialize interaction handler
|
||||
interaction_handler_.Initialize(canvas_id_);
|
||||
@@ -11,10 +11,10 @@
|
||||
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/rom.h"
|
||||
#include "canvas/canvas_utils.h"
|
||||
#include "app/gui/widgets/palette_widget.h"
|
||||
#include "app/gui/canvas/canvas_utils.h"
|
||||
#include "app/gui/widgets/palette_editor_widget.h"
|
||||
#include "app/gfx/util/bpp_format_manager.h"
|
||||
#include "canvas/bpp_format_ui.h"
|
||||
#include "app/gui/canvas/bpp_format_ui.h"
|
||||
#include "app/gui/canvas/canvas_modals.h"
|
||||
#include "app/gui/canvas/canvas_context_menu.h"
|
||||
#include "app/gui/canvas/canvas_usage_tracker.h"
|
||||
@@ -411,7 +411,7 @@ class Canvas {
|
||||
gfx::IRenderer* renderer_ = nullptr;
|
||||
CanvasConfig config_;
|
||||
CanvasSelection selection_;
|
||||
std::unique_ptr<PaletteWidget> palette_editor_;
|
||||
std::unique_ptr<PaletteEditorWidget> palette_editor_;
|
||||
|
||||
// Automation API (lazy-initialized on first access)
|
||||
std::unique_ptr<CanvasAutomationAPI> automation_api_;
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/canvas/canvas.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
#include "app/gfx/resource/arena.h"
|
||||
#include "app/gfx/debug/performance/performance_profiler.h"
|
||||
#include "app/gfx/debug/performance/performance_dashboard.h"
|
||||
#include "app/gui/widgets/palette_widget.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/widgets/palette_editor_widget.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "app/gui/canvas/canvas_modals.h"
|
||||
#include "app/gui/widgets/palette_editor_widget.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -27,7 +28,7 @@ void CanvasContextMenu::Initialize(const std::string& canvas_id) {
|
||||
canvas_id_ = canvas_id;
|
||||
enabled_ = true;
|
||||
current_usage_ = CanvasUsage::kTilePainting;
|
||||
palette_editor_ = std::make_unique<PaletteWidget>();
|
||||
palette_editor_ = std::make_unique<PaletteEditorWidget>();
|
||||
|
||||
// Initialize canvas state
|
||||
canvas_size_ = ImVec2(0, 0);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/gfx/types/snes_palette.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "app/gui/canvas/canvas_modals.h"
|
||||
#include "canvas_usage_tracker.h"
|
||||
#include "imgui/imgui.h"
|
||||
@@ -17,7 +17,7 @@ namespace yaze {
|
||||
namespace gui {
|
||||
|
||||
// Forward declarations
|
||||
class PaletteWidget;
|
||||
class PaletteEditorWidget;
|
||||
|
||||
namespace canvas {
|
||||
|
||||
@@ -108,7 +108,7 @@ class CanvasContextMenu {
|
||||
bool auto_resize_ = false;
|
||||
ImVec2 scrolling_;
|
||||
|
||||
std::unique_ptr<PaletteWidget> palette_editor_;
|
||||
std::unique_ptr<PaletteEditorWidget> palette_editor_;
|
||||
uint64_t edit_palette_group_name_index_ = 0;
|
||||
uint64_t edit_palette_index_ = 0;
|
||||
uint64_t edit_palette_sub_index_ = 0;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
|
||||
#include "app/gfx/debug/performance/performance_profiler.h"
|
||||
#include "app/gfx/debug/performance/performance_dashboard.h"
|
||||
#include "app/gui/widgets/palette_widget.h"
|
||||
#include "app/gui/widgets/palette_editor_widget.h"
|
||||
#include "app/gui/canvas/bpp_format_ui.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -422,8 +422,8 @@ void CanvasModals::RenderPaletteEditorModal(const std::string& canvas_id,
|
||||
ImGui::Separator();
|
||||
|
||||
// Use the existing PaletteWidget
|
||||
static std::unique_ptr<gui::PaletteWidget> palette_editor =
|
||||
std::make_unique<gui::PaletteWidget>();
|
||||
static std::unique_ptr<gui::PaletteEditorWidget> palette_editor =
|
||||
std::make_unique<gui::PaletteEditorWidget>();
|
||||
|
||||
if (options.palette) {
|
||||
palette_editor->ShowPaletteEditor(*options.palette, modal_title);
|
||||
@@ -455,8 +455,8 @@ void CanvasModals::RenderColorAnalysisModal(const std::string& canvas_id,
|
||||
ImGui::Separator();
|
||||
|
||||
// Use the existing PaletteWidget for color analysis
|
||||
static std::unique_ptr<gui::PaletteWidget> palette_editor =
|
||||
std::make_unique<gui::PaletteWidget>();
|
||||
static std::unique_ptr<gui::PaletteEditorWidget> palette_editor =
|
||||
std::make_unique<gui::PaletteEditorWidget>();
|
||||
|
||||
if (options.bitmap) {
|
||||
palette_editor->ShowColorAnalysis(*options.bitmap, modal_title);
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
#include "app/gui/layout_helpers.h"
|
||||
#include "app/gui/core/layout_helpers.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/imgui_internal.h"
|
||||
#include "app/gui/theme_manager.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "app/gui/core/color.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
@@ -1,8 +1,11 @@
|
||||
#ifndef YAZE_APP_GUI_LAYOUT_HELPERS_H
|
||||
#define YAZE_APP_GUI_LAYOUT_HELPERS_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "app/gui/theme_manager.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
@@ -1,13 +1,13 @@
|
||||
#include "style.h"
|
||||
#include "app/gui/core/style.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "util/file_util.h"
|
||||
#include "app/gui/theme_manager.h"
|
||||
#include "app/gui/background_renderer.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "app/gui/app/background_renderer.h"
|
||||
#include "app/platform/font_loader.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/imgui_internal.h"
|
||||
#include "util/log.h"
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/modules/text_editor.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "app/gui/widgets/text_editor.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -11,10 +11,11 @@
|
||||
#include "absl/strings/str_split.h"
|
||||
#include "util/file_util.h"
|
||||
#include "util/platform_paths.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/style.h" // For ColorsYaze function
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "app/gui/core/style.h" // For ColorsYaze function
|
||||
#include "imgui/imgui.h"
|
||||
#include "util/log.h"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "app/gui/ui_helpers.h"
|
||||
#include "app/gui/core/ui_helpers.h"
|
||||
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/icons.h"
|
||||
#include "app/gui/theme_manager.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/gui/core/icons.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "imgui/imgui_internal.h"
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
set(
|
||||
YAZE_GUI_SRC
|
||||
app/gui/canvas.cc
|
||||
# ==============================================================================
|
||||
# GUI Library Refactoring (see docs/gui-refactor.md)
|
||||
# ==============================================================================
|
||||
# The monolithic yaze_gui has been decomposed into smaller, layered libraries
|
||||
# to improve build times and code organization. The yaze_gui target is now
|
||||
# an INTERFACE library that aggregates these components for backward
|
||||
# compatibility.
|
||||
# ==============================================================================
|
||||
|
||||
# 1. Define Source Groups for each sub-library
|
||||
set(GUI_CORE_SRC
|
||||
app/gui/core/color.cc
|
||||
app/gui/core/input.cc
|
||||
app/gui/core/layout_helpers.cc
|
||||
app/gui/core/style.cc
|
||||
app/gui/core/theme_manager.cc
|
||||
app/gui/core/ui_helpers.cc
|
||||
)
|
||||
|
||||
set(CANVAS_SRC
|
||||
app/gui/canvas/bpp_format_ui.cc
|
||||
app/gui/canvas/canvas.cc
|
||||
app/gui/canvas/canvas_automation_api.cc
|
||||
app/gui/canvas/canvas_context_menu.cc
|
||||
app/gui/canvas/canvas_interaction_handler.cc
|
||||
@@ -9,61 +27,89 @@ set(
|
||||
app/gui/canvas/canvas_performance_integration.cc
|
||||
app/gui/canvas/canvas_usage_tracker.cc
|
||||
app/gui/canvas/canvas_utils.cc
|
||||
app/gui/color.cc
|
||||
app/gui/editor_card_manager.cc
|
||||
app/gui/editor_layout.cc
|
||||
app/gui/input.cc
|
||||
app/gui/layout_helpers.cc
|
||||
app/gui/themed_widgets.cc
|
||||
app/gui/modules/asset_browser.cc
|
||||
app/gui/modules/text_editor.cc
|
||||
app/gui/style.cc
|
||||
app/gui/theme_manager.cc
|
||||
app/gui/ui_helpers.cc
|
||||
app/gui/background_renderer.cc # Moved from yaze_editor (used by style.cc)
|
||||
app/gui/widgets/agent_chat_widget.cc
|
||||
app/gui/widgets/collaboration_panel.cc
|
||||
)
|
||||
|
||||
set(GUI_WIDGETS_SRC
|
||||
app/gui/widgets/asset_browser.cc
|
||||
app/gui/widgets/dungeon_object_emulator_preview.cc
|
||||
app/gui/widgets/palette_editor_widget.cc
|
||||
app/gui/widgets/palette_widget.cc
|
||||
app/gui/widgets/text_editor.cc
|
||||
app/gui/widgets/themed_widgets.cc
|
||||
app/gui/widgets/tile_selector_widget.cc
|
||||
app/gui/widgets/widget_auto_register.cc
|
||||
app/gui/widgets/widget_id_registry.cc
|
||||
app/gui/widgets/widget_measurement.cc
|
||||
app/gui/widgets/widget_state_capture.cc
|
||||
# Canvas system components
|
||||
)
|
||||
|
||||
# ==============================================================================
|
||||
# Yaze GUI Library
|
||||
# ==============================================================================
|
||||
# This library contains all GUI-related functionality:
|
||||
# - Canvas system
|
||||
# - ImGui widgets and utilities
|
||||
# - Input handling
|
||||
# - Theme management
|
||||
# - Color utilities
|
||||
# - Background rendering
|
||||
#
|
||||
# Dependencies: yaze_gfx, yaze_util, ImGui, SDL2
|
||||
# ==============================================================================
|
||||
|
||||
add_library(yaze_gui STATIC ${YAZE_GUI_SRC})
|
||||
|
||||
target_precompile_headers(yaze_gui PRIVATE
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/src/yaze_pch.h>"
|
||||
set(GUI_AUTOMATION_SRC
|
||||
app/gui/automation/widget_auto_register.cc
|
||||
app/gui/automation/widget_id_registry.cc
|
||||
app/gui/automation/widget_measurement.cc
|
||||
app/gui/automation/widget_state_capture.cc
|
||||
)
|
||||
|
||||
target_include_directories(yaze_gui PUBLIC
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src/lib
|
||||
${CMAKE_SOURCE_DIR}/src/lib/imgui
|
||||
${CMAKE_SOURCE_DIR}/incl
|
||||
${SDL2_INCLUDE_DIR}
|
||||
${PROJECT_BINARY_DIR}
|
||||
set(GUI_APP_SRC
|
||||
app/gui/app/agent_chat_widget.cc
|
||||
app/gui/app/background_renderer.cc
|
||||
app/gui/app/collaboration_panel.cc
|
||||
app/gui/app/editor_card_manager.cc
|
||||
app/gui/app/editor_layout.cc
|
||||
)
|
||||
|
||||
target_link_libraries(yaze_gui PUBLIC
|
||||
# 2. Create Static Libraries and Establish Link Dependencies
|
||||
add_library(yaze_gui_core STATIC ${GUI_CORE_SRC})
|
||||
add_library(yaze_canvas STATIC ${CANVAS_SRC})
|
||||
add_library(yaze_gui_widgets STATIC ${GUI_WIDGETS_SRC})
|
||||
add_library(yaze_gui_automation STATIC ${GUI_AUTOMATION_SRC})
|
||||
add_library(yaze_gui_app STATIC ${GUI_APP_SRC})
|
||||
|
||||
# Link dependencies between the new libraries
|
||||
target_link_libraries(yaze_gui_core PUBLIC yaze_util ImGui nlohmann_json::nlohmann_json)
|
||||
target_link_libraries(yaze_canvas PUBLIC yaze_gui_core yaze_gfx)
|
||||
target_link_libraries(yaze_gui_widgets PUBLIC yaze_gui_core yaze_gfx)
|
||||
target_link_libraries(yaze_gui_automation PUBLIC yaze_gui_core)
|
||||
target_link_libraries(yaze_gui_app PUBLIC yaze_gui_core yaze_gui_widgets yaze_gui_automation)
|
||||
|
||||
set(GUI_SUB_LIBS
|
||||
yaze_gui_core
|
||||
yaze_canvas
|
||||
yaze_gui_widgets
|
||||
yaze_gui_automation
|
||||
yaze_gui_app
|
||||
)
|
||||
|
||||
# Apply common properties to all new sub-libraries
|
||||
foreach(LIB ${GUI_SUB_LIBS})
|
||||
target_precompile_headers(${LIB} PRIVATE
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:${CMAKE_SOURCE_DIR}/src/yaze_pch.h>"
|
||||
)
|
||||
target_include_directories(${LIB} PUBLIC
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/incl
|
||||
${CMAKE_SOURCE_DIR}/src/app/gui
|
||||
${SDL2_INCLUDE_DIR}
|
||||
${PROJECT_BINARY_DIR}
|
||||
)
|
||||
set_target_properties(${LIB} PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
|
||||
)
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_compile_definitions(${LIB} PRIVATE linux stricmp=strcasecmp)
|
||||
elseif(APPLE)
|
||||
target_compile_definitions(${LIB} PRIVATE MACOS)
|
||||
elseif(WIN32)
|
||||
target_compile_definitions(${LIB} PRIVATE WINDOWS)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# 3. Create Aggregate INTERFACE library
|
||||
add_library(yaze_gui INTERFACE)
|
||||
target_link_libraries(yaze_gui INTERFACE
|
||||
yaze_gui_core
|
||||
yaze_canvas
|
||||
yaze_gui_widgets
|
||||
yaze_gui_automation
|
||||
yaze_gui_app
|
||||
# Link original public dependencies so downstream targets receive them
|
||||
yaze_gfx
|
||||
yaze_util
|
||||
yaze_common
|
||||
@@ -72,19 +118,4 @@ target_link_libraries(yaze_gui PUBLIC
|
||||
${SDL_TARGETS}
|
||||
)
|
||||
|
||||
set_target_properties(yaze_gui PROPERTIES
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
|
||||
)
|
||||
|
||||
# Platform-specific compile definitions
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_compile_definitions(yaze_gui PRIVATE linux stricmp=strcasecmp)
|
||||
elseif(APPLE)
|
||||
target_compile_definitions(yaze_gui PRIVATE MACOS)
|
||||
elseif(WIN32)
|
||||
target_compile_definitions(yaze_gui PRIVATE WINDOWS)
|
||||
endif()
|
||||
|
||||
message(STATUS "✓ yaze_gui library configured")
|
||||
message(STATUS "✓ yaze_gui library refactored and configured")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "zelda3/dungeon/room.h"
|
||||
#include "zelda3/dungeon/room_object.h"
|
||||
#include "app/gui/widgets/widget_auto_register.h"
|
||||
#include "app/gui/automation/widget_auto_register.h"
|
||||
#include "app/core/window.h"
|
||||
#include <cstdio>
|
||||
|
||||
|
||||
@@ -1,59 +1,75 @@
|
||||
#include "palette_editor_widget.h"
|
||||
#include "app/gui/widgets/palette_editor_widget.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "app/gfx/resource/arena.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "util/log.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
|
||||
void PaletteEditorWidget::Initialize(Rom* rom) {
|
||||
// Merged implementation from PaletteWidget and PaletteEditorWidget
|
||||
|
||||
void PaletteEditorWidget::Initialize(Rom *rom) {
|
||||
rom_ = rom;
|
||||
rom_palettes_loaded_ = false;
|
||||
if (rom_) {
|
||||
LoadROMPalettes();
|
||||
}
|
||||
current_palette_id_ = 0;
|
||||
selected_color_index_ = -1;
|
||||
}
|
||||
|
||||
// --- Embedded Draw Method (from simple editor) ---
|
||||
void PaletteEditorWidget::Draw() {
|
||||
if (!rom_ || !rom_->is_loaded()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "ROM not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ImGui::BeginGroup();
|
||||
|
||||
// Palette selector dropdown
|
||||
|
||||
DrawPaletteSelector();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Color grid display
|
||||
DrawColorGrid();
|
||||
|
||||
|
||||
auto &dungeon_pal_group = rom_->mutable_palette_group()->dungeon_main;
|
||||
if (current_palette_id_ >= 0 &&
|
||||
current_palette_id_ < (int)dungeon_pal_group.size()) {
|
||||
auto palette = dungeon_pal_group[current_palette_id_];
|
||||
DrawPaletteGrid(palette, 15);
|
||||
dungeon_pal_group[current_palette_id_] = palette;
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Color picker for selected color
|
||||
|
||||
if (selected_color_index_ >= 0) {
|
||||
DrawColorPicker();
|
||||
} else {
|
||||
ImGui::TextDisabled("Select a color to edit");
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::DrawPaletteSelector() {
|
||||
auto& dungeon_pal_group = rom_->mutable_palette_group()->dungeon_main;
|
||||
auto &dungeon_pal_group = rom_->mutable_palette_group()->dungeon_main;
|
||||
int num_palettes = dungeon_pal_group.size();
|
||||
|
||||
|
||||
ImGui::Text("Dungeon Palette:");
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::BeginCombo("##PaletteSelect",
|
||||
absl::StrFormat("Palette %d", current_palette_id_).c_str())) {
|
||||
|
||||
if (ImGui::BeginCombo(
|
||||
"##PaletteSelect",
|
||||
absl::StrFormat("Palette %d", current_palette_id_).c_str())) {
|
||||
for (int i = 0; i < num_palettes; i++) {
|
||||
bool is_selected = (current_palette_id_ == i);
|
||||
if (ImGui::Selectable(absl::StrFormat("Palette %d", i).c_str(), is_selected)) {
|
||||
if (ImGui::Selectable(absl::StrFormat("Palette %d", i).c_str(),
|
||||
is_selected)) {
|
||||
current_palette_id_ = i;
|
||||
selected_color_index_ = -1; // Reset color selection
|
||||
selected_color_index_ = -1;
|
||||
}
|
||||
if (is_selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
@@ -63,111 +79,453 @@ void PaletteEditorWidget::DrawPaletteSelector() {
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::DrawColorGrid() {
|
||||
auto& dungeon_pal_group = rom_->mutable_palette_group()->dungeon_main;
|
||||
|
||||
if (current_palette_id_ < 0 || current_palette_id_ >= (int)dungeon_pal_group.size()) {
|
||||
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Invalid palette ID");
|
||||
return;
|
||||
}
|
||||
|
||||
auto palette = dungeon_pal_group[current_palette_id_];
|
||||
int num_colors = palette.size();
|
||||
|
||||
ImGui::Text("Colors (%d):", num_colors);
|
||||
|
||||
// Draw color grid (15 colors per row for good layout)
|
||||
const int colors_per_row = 15;
|
||||
const float color_button_size = 24.0f;
|
||||
|
||||
for (int i = 0; i < num_colors; i++) {
|
||||
ImGui::PushID(i);
|
||||
|
||||
// Get color as RGB (0-255)
|
||||
auto color = palette[i];
|
||||
ImVec4 col(color.rgb().x / 255.0f,
|
||||
color.rgb().y / 255.0f,
|
||||
color.rgb().z / 255.0f,
|
||||
1.0f);
|
||||
|
||||
// Color button
|
||||
bool is_selected = (i == selected_color_index_);
|
||||
if (is_selected) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1, 1, 0, 1)); // Yellow border
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 2.0f);
|
||||
}
|
||||
|
||||
if (ImGui::ColorButton(absl::StrFormat("##color%d", i).c_str(), col,
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker,
|
||||
ImVec2(color_button_size, color_button_size))) {
|
||||
selected_color_index_ = i;
|
||||
editing_color_ = col;
|
||||
}
|
||||
|
||||
if (is_selected) {
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
// Tooltip showing color index and SNES value
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Color %d\nSNES: 0x%04X\nRGB: (%d, %d, %d)",
|
||||
i, color.snes(),
|
||||
(int)color.rgb().x, (int)color.rgb().y, (int)color.rgb().z);
|
||||
}
|
||||
|
||||
// Layout: 15 per row
|
||||
if ((i + 1) % colors_per_row != 0 && i < num_colors - 1) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::DrawColorPicker() {
|
||||
ImGui::SeparatorText(absl::StrFormat("Edit Color %d", selected_color_index_).c_str());
|
||||
|
||||
auto& dungeon_pal_group = rom_->mutable_palette_group()->dungeon_main;
|
||||
auto palette = dungeon_pal_group[current_palette_id_]; // Get copy, not reference
|
||||
ImGui::SeparatorText(
|
||||
absl::StrFormat("Edit Color %d", selected_color_index_).c_str());
|
||||
|
||||
auto &dungeon_pal_group = rom_->mutable_palette_group()->dungeon_main;
|
||||
auto palette = dungeon_pal_group[current_palette_id_];
|
||||
auto original_color = palette[selected_color_index_];
|
||||
|
||||
// Color picker
|
||||
if (ImGui::ColorEdit3("Color", &editing_color_.x,
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_PickerHueWheel)) {
|
||||
// Convert ImGui color (0-1) to SNES color (0-31 per channel)
|
||||
|
||||
if (ImGui::ColorEdit3("Color", &editing_color_.x,
|
||||
ImGuiColorEditFlags_NoAlpha |
|
||||
ImGuiColorEditFlags_PickerHueWheel)) {
|
||||
int r = static_cast<int>(editing_color_.x * 31.0f);
|
||||
int g = static_cast<int>(editing_color_.y * 31.0f);
|
||||
int b = static_cast<int>(editing_color_.z * 31.0f);
|
||||
|
||||
// Create SNES color (15-bit BGR555 format)
|
||||
uint16_t snes_color = (b << 10) | (g << 5) | r;
|
||||
|
||||
// Update palette in ROM (need to write back through the group)
|
||||
|
||||
palette[selected_color_index_] = gfx::SnesColor(snes_color);
|
||||
dungeon_pal_group[current_palette_id_] = palette; // Write back
|
||||
|
||||
// Notify that palette changed
|
||||
dungeon_pal_group[current_palette_id_] = palette;
|
||||
|
||||
if (on_palette_changed_) {
|
||||
on_palette_changed_(current_palette_id_);
|
||||
}
|
||||
}
|
||||
|
||||
// Show RGB values
|
||||
ImGui::Text("RGB (0-255): (%d, %d, %d)",
|
||||
(int)(editing_color_.x * 255),
|
||||
(int)(editing_color_.y * 255),
|
||||
(int)(editing_color_.z * 255));
|
||||
|
||||
// Show SNES BGR555 value
|
||||
|
||||
ImGui::Text("RGB (0-255): (%d, %d, %d)", (int)(editing_color_.x * 255),
|
||||
(int)(editing_color_.y * 255), (int)(editing_color_.z * 255));
|
||||
ImGui::Text("SNES BGR555: 0x%04X", original_color.snes());
|
||||
|
||||
// Reset button
|
||||
|
||||
if (ImGui::Button("Reset to Original")) {
|
||||
editing_color_ = ImVec4(original_color.rgb().x / 255.0f,
|
||||
original_color.rgb().y / 255.0f,
|
||||
original_color.rgb().z / 255.0f,
|
||||
1.0f);
|
||||
original_color.rgb().y / 255.0f,
|
||||
original_color.rgb().z / 255.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Modal/Popup Methods (from feature-rich widget) ---
|
||||
|
||||
void PaletteEditorWidget::ShowPaletteEditor(gfx::SnesPalette &palette,
|
||||
const std::string &title) {
|
||||
if (ImGui::BeginPopupModal(title.c_str(), nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Enhanced Palette Editor");
|
||||
ImGui::Separator();
|
||||
|
||||
DrawPaletteGrid(palette);
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::CollapsingHeader("Palette Analysis")) {
|
||||
DrawPaletteAnalysis(palette);
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("ROM Palette Manager") && rom_) {
|
||||
DrawROMPaletteSelector();
|
||||
|
||||
if (ImGui::Button("Apply ROM Palette") && !rom_palette_groups_.empty()) {
|
||||
if (current_group_index_ <
|
||||
static_cast<int>(rom_palette_groups_.size())) {
|
||||
palette = rom_palette_groups_[current_group_index_];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Button("Save Backup")) {
|
||||
SavePaletteBackup(palette);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Restore Backup")) {
|
||||
RestorePaletteBackup(palette);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Close")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::ShowROMPaletteManager() {
|
||||
if (!show_rom_manager_) return;
|
||||
|
||||
if (ImGui::Begin("ROM Palette Manager", &show_rom_manager_)) {
|
||||
if (!rom_) {
|
||||
ImGui::Text("No ROM loaded");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rom_palettes_loaded_) {
|
||||
LoadROMPalettes();
|
||||
}
|
||||
|
||||
DrawROMPaletteSelector();
|
||||
|
||||
if (current_group_index_ < static_cast<int>(rom_palette_groups_.size())) {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Preview of %s:",
|
||||
palette_group_names_[current_group_index_].c_str());
|
||||
|
||||
const auto &preview_palette = rom_palette_groups_[current_group_index_];
|
||||
DrawPaletteGrid(const_cast<gfx::SnesPalette &>(preview_palette));
|
||||
DrawPaletteAnalysis(preview_palette);
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::ShowColorAnalysis(const gfx::Bitmap &bitmap,
|
||||
const std::string &title) {
|
||||
if (!show_color_analysis_) return;
|
||||
|
||||
if (ImGui::Begin(title.c_str(), &show_color_analysis_)) {
|
||||
ImGui::Text("Bitmap Color Analysis");
|
||||
ImGui::Separator();
|
||||
|
||||
if (!bitmap.is_active()) {
|
||||
ImGui::Text("Bitmap is not active");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
std::map<uint8_t, int> pixel_counts;
|
||||
const auto &data = bitmap.vector();
|
||||
|
||||
for (uint8_t pixel : data) {
|
||||
uint8_t palette_index = pixel & 0x0F;
|
||||
pixel_counts[palette_index]++;
|
||||
}
|
||||
|
||||
ImGui::Text("Bitmap Size: %d x %d (%zu pixels)", bitmap.width(),
|
||||
bitmap.height(), data.size());
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Pixel Distribution:");
|
||||
|
||||
int total_pixels = static_cast<int>(data.size());
|
||||
for (const auto &[index, count] : pixel_counts) {
|
||||
float percentage = (static_cast<float>(count) / total_pixels) * 100.0f;
|
||||
ImGui::Text("Index %d: %d pixels (%.1f%%)", index, count, percentage);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::ProgressBar(percentage / 100.0f, ImVec2(100, 0));
|
||||
|
||||
if (index < static_cast<int>(bitmap.palette().size())) {
|
||||
ImGui::SameLine();
|
||||
auto color = bitmap.palette()[index];
|
||||
ImVec4 display_color = color.rgb();
|
||||
ImGui::ColorButton(("##color" + std::to_string(index)).c_str(),
|
||||
display_color, ImGuiColorEditFlags_NoTooltip,
|
||||
ImVec2(20, 20));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("SNES Color: 0x%04X\nRGB: (%d, %d, %d)",
|
||||
color.snes(),
|
||||
static_cast<int>(display_color.x * 255),
|
||||
static_cast<int>(display_color.y * 255),
|
||||
static_cast<int>(display_color.z * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool PaletteEditorWidget::ApplyROMPalette(gfx::Bitmap *bitmap, int group_index,
|
||||
int palette_index) {
|
||||
if (!bitmap || !rom_palettes_loaded_ || group_index < 0 ||
|
||||
group_index >= static_cast<int>(rom_palette_groups_.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const auto &selected_palette = rom_palette_groups_[group_index];
|
||||
SavePaletteBackup(bitmap->palette());
|
||||
|
||||
if (palette_index >= 0 && palette_index < 8) {
|
||||
bitmap->SetPaletteWithTransparent(selected_palette, palette_index);
|
||||
} else {
|
||||
bitmap->SetPalette(selected_palette);
|
||||
}
|
||||
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, bitmap);
|
||||
|
||||
current_group_index_ = group_index;
|
||||
current_palette_index_ = palette_index;
|
||||
return true;
|
||||
} catch (const std::exception &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const gfx::SnesPalette *PaletteEditorWidget::GetSelectedROMPalette() const {
|
||||
if (!rom_palettes_loaded_ || current_group_index_ < 0 ||
|
||||
current_group_index_ >= static_cast<int>(rom_palette_groups_.size())) {
|
||||
return nullptr;
|
||||
}
|
||||
return &rom_palette_groups_[current_group_index_];
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::SavePaletteBackup(const gfx::SnesPalette &palette) {
|
||||
backup_palette_ = palette;
|
||||
}
|
||||
|
||||
bool PaletteEditorWidget::RestorePaletteBackup(gfx::SnesPalette &palette) {
|
||||
if (backup_palette_.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
palette = backup_palette_;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Unified grid drawing function
|
||||
void PaletteEditorWidget::DrawPaletteGrid(gfx::SnesPalette &palette, int cols) {
|
||||
for (int i = 0; i < static_cast<int>(palette.size()); i++) {
|
||||
if (i % cols != 0) ImGui::SameLine();
|
||||
|
||||
auto color = palette[i];
|
||||
ImVec4 display_color = color.rgb();
|
||||
|
||||
ImGui::PushID(i);
|
||||
if (ImGui::ColorButton("##color", display_color,
|
||||
ImGuiColorEditFlags_NoTooltip, ImVec2(30, 30))) {
|
||||
editing_color_index_ = i;
|
||||
selected_color_index_ = i;
|
||||
temp_color_ = display_color;
|
||||
editing_color_ = display_color;
|
||||
}
|
||||
|
||||
if (ImGui::BeginPopupContextItem()) {
|
||||
ImGui::Text("Color %d (0x%04X)", i, color.snes());
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Edit Color")) {
|
||||
editing_color_index_ = i;
|
||||
selected_color_index_ = i;
|
||||
temp_color_ = display_color;
|
||||
editing_color_ = display_color;
|
||||
}
|
||||
if (ImGui::MenuItem("Reset to Black")) {
|
||||
palette[i] = gfx::SnesColor(0);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Color %d\nSNES: 0x%04X\nRGB: (%d, %d, %d)", i,
|
||||
color.snes(), static_cast<int>(display_color.x * 255),
|
||||
static_cast<int>(display_color.y * 255),
|
||||
static_cast<int>(display_color.z * 255));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
if (editing_color_index_ >= 0) {
|
||||
ImGui::OpenPopup("Edit Color");
|
||||
if (ImGui::BeginPopupModal("Edit Color", nullptr,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Editing Color %d", editing_color_index_);
|
||||
if (ImGui::ColorEdit4("Color", &temp_color_.x,
|
||||
ImGuiColorEditFlags_NoAlpha |
|
||||
ImGuiColorEditFlags_DisplayRGB)) {
|
||||
auto new_snes_color = gfx::SnesColor(temp_color_);
|
||||
palette[editing_color_index_] = new_snes_color;
|
||||
}
|
||||
if (ImGui::Button("Apply")) {
|
||||
editing_color_index_ = -1;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
editing_color_index_ = -1;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::DrawROMPaletteSelector() {
|
||||
if (!rom_palettes_loaded_) {
|
||||
LoadROMPalettes();
|
||||
}
|
||||
|
||||
if (rom_palette_groups_.empty()) {
|
||||
ImGui::Text("No ROM palettes available");
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Text("Palette Group:");
|
||||
if (ImGui::Combo(
|
||||
"##PaletteGroup", ¤t_group_index_,
|
||||
[](void *data, int idx, const char **out_text) -> bool {
|
||||
auto *names = static_cast<std::vector<std::string> *>(data);
|
||||
if (idx < 0 || idx >= static_cast<int>(names->size())) return false;
|
||||
*out_text = (*names)[idx].c_str();
|
||||
return true;
|
||||
},
|
||||
&palette_group_names_,
|
||||
static_cast<int>(palette_group_names_.size()))) {
|
||||
}
|
||||
|
||||
ImGui::Text("Palette Index:");
|
||||
ImGui::SliderInt("##PaletteIndex", ¤t_palette_index_, 0, 7, "%d");
|
||||
|
||||
if (current_group_index_ < static_cast<int>(rom_palette_groups_.size())) {
|
||||
ImGui::Text("Preview:");
|
||||
const auto &preview_palette = rom_palette_groups_[current_group_index_];
|
||||
for (int i = 0; i < 8 && i < static_cast<int>(preview_palette.size());
|
||||
i++) {
|
||||
if (i > 0) ImGui::SameLine();
|
||||
auto color = preview_palette[i];
|
||||
ImVec4 display_color = color.rgb();
|
||||
ImGui::ColorButton(("##preview" + std::to_string(i)).c_str(),
|
||||
display_color, ImGuiColorEditFlags_NoTooltip,
|
||||
ImVec2(20, 20));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::DrawColorEditControls(gfx::SnesColor &color,
|
||||
int color_index) {
|
||||
ImVec4 rgba = color.rgb();
|
||||
|
||||
ImGui::PushID(color_index);
|
||||
|
||||
if (ImGui::ColorEdit4("##color_edit", &rgba.x,
|
||||
ImGuiColorEditFlags_NoAlpha |
|
||||
ImGuiColorEditFlags_DisplayRGB)) {
|
||||
color = gfx::SnesColor(rgba);
|
||||
}
|
||||
|
||||
ImGui::Text("SNES Color: 0x%04X", color.snes());
|
||||
|
||||
int r = (color.snes() & 0x1F);
|
||||
int g = (color.snes() >> 5) & 0x1F;
|
||||
int b = (color.snes() >> 10) & 0x1F;
|
||||
|
||||
if (ImGui::SliderInt("Red", &r, 0, 31)) {
|
||||
uint16_t new_color = (color.snes() & 0xFFE0) | (r & 0x1F);
|
||||
color = gfx::SnesColor(new_color);
|
||||
}
|
||||
if (ImGui::SliderInt("Green", &g, 0, 31)) {
|
||||
uint16_t new_color = (color.snes() & 0xFC1F) | ((g & 0x1F) << 5);
|
||||
color = gfx::SnesColor(new_color);
|
||||
}
|
||||
if (ImGui::SliderInt("Blue", &b, 0, 31)) {
|
||||
uint16_t new_color = (color.snes() & 0x83FF) | ((b & 0x1F) << 10);
|
||||
color = gfx::SnesColor(new_color);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::DrawPaletteAnalysis(
|
||||
const gfx::SnesPalette &palette) {
|
||||
ImGui::Text("Palette Information:");
|
||||
ImGui::Text("Size: %zu colors", palette.size());
|
||||
|
||||
std::map<uint16_t, int> color_frequency;
|
||||
for (int i = 0; i < static_cast<int>(palette.size()); i++) {
|
||||
color_frequency[palette[i].snes()]++;
|
||||
}
|
||||
|
||||
ImGui::Text("Unique Colors: %zu", color_frequency.size());
|
||||
|
||||
if (color_frequency.size() < palette.size()) {
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 1), "Warning: Duplicate colors detected!");
|
||||
if (ImGui::TreeNode("Duplicate Colors")) {
|
||||
for (const auto &[snes_color, count] : color_frequency) {
|
||||
if (count > 1) {
|
||||
ImVec4 display_color = gfx::SnesColor(snes_color).rgb();
|
||||
ImGui::ColorButton(("##dup" + std::to_string(snes_color)).c_str(),
|
||||
display_color, ImGuiColorEditFlags_NoTooltip,
|
||||
ImVec2(16, 16));
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("0x%04X appears %d times", snes_color, count);
|
||||
}
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
float total_brightness = 0.0f;
|
||||
float min_brightness = 1.0f;
|
||||
float max_brightness = 0.0f;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(palette.size()); i++) {
|
||||
ImVec4 color = palette[i].rgb();
|
||||
float brightness = (color.x + color.y + color.z) / 3.0f;
|
||||
total_brightness += brightness;
|
||||
min_brightness = std::min(min_brightness, brightness);
|
||||
max_brightness = std::max(max_brightness, brightness);
|
||||
}
|
||||
|
||||
float avg_brightness = total_brightness / palette.size();
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Brightness Analysis:");
|
||||
ImGui::Text("Average: %.2f", avg_brightness);
|
||||
ImGui::Text("Range: %.2f - %.2f", min_brightness, max_brightness);
|
||||
|
||||
ImGui::Text("Brightness Distribution:");
|
||||
ImGui::ProgressBar(avg_brightness, ImVec2(-1, 0), "Avg");
|
||||
}
|
||||
|
||||
void PaletteEditorWidget::LoadROMPalettes() {
|
||||
if (!rom_ || rom_palettes_loaded_) return;
|
||||
|
||||
try {
|
||||
const auto &palette_groups = rom_->palette_group();
|
||||
rom_palette_groups_.clear();
|
||||
palette_group_names_.clear();
|
||||
|
||||
if (palette_groups.overworld_main.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.overworld_main[0]);
|
||||
palette_group_names_.push_back("Overworld Main");
|
||||
}
|
||||
if (palette_groups.overworld_aux.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.overworld_aux[0]);
|
||||
palette_group_names_.push_back("Overworld Aux");
|
||||
}
|
||||
if (palette_groups.overworld_animated.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.overworld_animated[0]);
|
||||
palette_group_names_.push_back("Overworld Animated");
|
||||
}
|
||||
if (palette_groups.dungeon_main.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.dungeon_main[0]);
|
||||
palette_group_names_.push_back("Dungeon Main");
|
||||
}
|
||||
if (palette_groups.global_sprites.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.global_sprites[0]);
|
||||
palette_group_names_.push_back("Global Sprites");
|
||||
}
|
||||
if (palette_groups.armors.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.armors[0]);
|
||||
palette_group_names_.push_back("Armor");
|
||||
}
|
||||
if (palette_groups.swords.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.swords[0]);
|
||||
palette_group_names_.push_back("Swords");
|
||||
}
|
||||
|
||||
rom_palettes_loaded_ = true;
|
||||
} catch (const std::exception &e) {
|
||||
LOG_ERROR("Enhanced Palette Editor", "Failed to load ROM palettes");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
#define YAZE_APP_GUI_WIDGETS_PALETTE_EDITOR_WIDGET_H
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/gfx/types/snes_palette.h"
|
||||
#include "app/rom.h"
|
||||
#include "imgui/imgui.h"
|
||||
@@ -11,42 +13,72 @@
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
|
||||
/**
|
||||
* @brief Simple visual palette editor with color picker
|
||||
*
|
||||
* Displays dungeon palettes in a grid, allows editing colors,
|
||||
* and notifies when palettes change so rooms can re-render.
|
||||
*/
|
||||
class PaletteEditorWidget {
|
||||
public:
|
||||
PaletteEditorWidget() = default;
|
||||
|
||||
void Initialize(Rom* rom);
|
||||
|
||||
void Initialize(Rom *rom);
|
||||
|
||||
// Embedded drawing function, like the old PaletteEditorWidget
|
||||
void Draw();
|
||||
|
||||
|
||||
// Modal dialogs from the more feature-rich PaletteWidget
|
||||
void ShowPaletteEditor(gfx::SnesPalette &palette,
|
||||
const std::string &title = "Palette Editor");
|
||||
void ShowROMPaletteManager();
|
||||
void ShowColorAnalysis(const gfx::Bitmap &bitmap,
|
||||
const std::string &title = "Color Analysis");
|
||||
|
||||
bool ApplyROMPalette(gfx::Bitmap *bitmap, int group_index, int palette_index);
|
||||
const gfx::SnesPalette *GetSelectedROMPalette() const;
|
||||
void SavePaletteBackup(const gfx::SnesPalette &palette);
|
||||
bool RestorePaletteBackup(gfx::SnesPalette &palette);
|
||||
|
||||
// Callback when palette is modified
|
||||
void SetOnPaletteChanged(std::function<void(int palette_id)> callback) {
|
||||
on_palette_changed_ = callback;
|
||||
}
|
||||
|
||||
|
||||
// Get/Set current editing palette
|
||||
int current_palette_id() const { return current_palette_id_; }
|
||||
void set_current_palette_id(int id) { current_palette_id_ = id; }
|
||||
|
||||
int GetCurrentPaletteId() const { return current_palette_id_; }
|
||||
void SetCurrentPaletteId(int id) { current_palette_id_ = id; }
|
||||
|
||||
bool IsROMLoaded() const { return rom_ != nullptr; }
|
||||
int GetCurrentGroupIndex() const { return current_group_index_; }
|
||||
void DrawROMPaletteSelector();
|
||||
|
||||
private:
|
||||
void DrawPaletteGrid(gfx::SnesPalette &palette, int cols = 15);
|
||||
void DrawColorEditControls(gfx::SnesColor &color, int color_index);
|
||||
void DrawPaletteAnalysis(const gfx::SnesPalette &palette);
|
||||
void LoadROMPalettes();
|
||||
|
||||
// For embedded view
|
||||
void DrawPaletteSelector();
|
||||
void DrawColorGrid();
|
||||
void DrawColorPicker();
|
||||
|
||||
Rom* rom_ = nullptr;
|
||||
|
||||
Rom *rom_ = nullptr;
|
||||
std::vector<gfx::SnesPalette> rom_palette_groups_;
|
||||
std::vector<std::string> palette_group_names_;
|
||||
gfx::SnesPalette backup_palette_;
|
||||
|
||||
int current_group_index_ = 0;
|
||||
int current_palette_index_ = 0; // used by ROM palette selector
|
||||
bool rom_palettes_loaded_ = false;
|
||||
bool show_color_analysis_ = false;
|
||||
bool show_rom_manager_ = false;
|
||||
|
||||
// State for embedded editor
|
||||
int current_palette_id_ = 0;
|
||||
int selected_color_index_ = -1;
|
||||
|
||||
ImVec4 editing_color_{0, 0, 0, 1};
|
||||
|
||||
// Callback for palette changes
|
||||
std::function<void(int palette_id)> on_palette_changed_;
|
||||
|
||||
// Temp color for editing (RGB 0-1 range for ImGui)
|
||||
ImVec4 editing_color_{0, 0, 0, 1};
|
||||
|
||||
// Color editing state
|
||||
int editing_color_index_ = -1;
|
||||
ImVec4 temp_color_ = ImVec4(0, 0, 0, 1);
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
@@ -1,462 +0,0 @@
|
||||
#include "app/gui/widgets/palette_widget.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include "app/gfx/resource/arena.h"
|
||||
#include "app/gui/color.h"
|
||||
#include "util/log.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
|
||||
void PaletteWidget::Initialize(Rom* rom) {
|
||||
rom_ = rom;
|
||||
rom_palettes_loaded_ = false;
|
||||
if (rom_) {
|
||||
LoadROMPalettes();
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteWidget::ShowPaletteEditor(gfx::SnesPalette& palette, const std::string& title) {
|
||||
if (ImGui::BeginPopupModal(title.c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Enhanced Palette Editor");
|
||||
ImGui::Separator();
|
||||
|
||||
// Palette grid editor
|
||||
DrawPaletteGrid(palette);
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Analysis and tools
|
||||
if (ImGui::CollapsingHeader("Palette Analysis")) {
|
||||
DrawPaletteAnalysis(palette);
|
||||
}
|
||||
|
||||
if (ImGui::CollapsingHeader("ROM Palette Manager") && rom_) {
|
||||
DrawROMPaletteSelector();
|
||||
|
||||
if (ImGui::Button("Apply ROM Palette") && !rom_palette_groups_.empty()) {
|
||||
if (current_group_index_ < static_cast<int>(rom_palette_groups_.size())) {
|
||||
palette = rom_palette_groups_[current_group_index_];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Action buttons
|
||||
if (ImGui::Button("Save Backup")) {
|
||||
SavePaletteBackup(palette);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Restore Backup")) {
|
||||
RestorePaletteBackup(palette);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Close")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteWidget::ShowROMPaletteManager() {
|
||||
if (!show_rom_manager_) return;
|
||||
|
||||
if (ImGui::Begin("ROM Palette Manager", &show_rom_manager_)) {
|
||||
if (!rom_) {
|
||||
ImGui::Text("No ROM loaded");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rom_palettes_loaded_) {
|
||||
LoadROMPalettes();
|
||||
}
|
||||
|
||||
DrawROMPaletteSelector();
|
||||
|
||||
if (current_group_index_ < static_cast<int>(rom_palette_groups_.size())) {
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Preview of %s:", palette_group_names_[current_group_index_].c_str());
|
||||
|
||||
const auto& preview_palette = rom_palette_groups_[current_group_index_];
|
||||
DrawPaletteGrid(const_cast<gfx::SnesPalette&>(preview_palette));
|
||||
|
||||
DrawPaletteAnalysis(preview_palette);
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void PaletteWidget::ShowColorAnalysis(const gfx::Bitmap& bitmap, const std::string& title) {
|
||||
if (!show_color_analysis_) return;
|
||||
|
||||
if (ImGui::Begin(title.c_str(), &show_color_analysis_)) {
|
||||
ImGui::Text("Bitmap Color Analysis");
|
||||
ImGui::Separator();
|
||||
|
||||
if (!bitmap.is_active()) {
|
||||
ImGui::Text("Bitmap is not active");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// Analyze pixel distribution
|
||||
std::map<uint8_t, int> pixel_counts;
|
||||
const auto& data = bitmap.vector();
|
||||
|
||||
for (uint8_t pixel : data) {
|
||||
uint8_t palette_index = pixel & 0x0F; // 4-bit palette index
|
||||
pixel_counts[palette_index]++;
|
||||
}
|
||||
|
||||
ImGui::Text("Bitmap Size: %d x %d (%zu pixels)",
|
||||
bitmap.width(), bitmap.height(), data.size());
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Pixel Distribution:");
|
||||
|
||||
// Show distribution as bars
|
||||
int total_pixels = static_cast<int>(data.size());
|
||||
for (const auto& [index, count] : pixel_counts) {
|
||||
float percentage = (static_cast<float>(count) / total_pixels) * 100.0f;
|
||||
ImGui::Text("Index %d: %d pixels (%.1f%%)", index, count, percentage);
|
||||
|
||||
// Progress bar visualization
|
||||
ImGui::SameLine();
|
||||
ImGui::ProgressBar(percentage / 100.0f, ImVec2(100, 0));
|
||||
|
||||
// Color swatch if palette is available
|
||||
if (index < static_cast<int>(bitmap.palette().size())) {
|
||||
ImGui::SameLine();
|
||||
auto color = bitmap.palette()[index];
|
||||
ImVec4 display_color = color.rgb();
|
||||
ImGui::ColorButton(("##color" + std::to_string(index)).c_str(),
|
||||
display_color, ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("SNES Color: 0x%04X\nRGB: (%d, %d, %d)",
|
||||
color.snes(),
|
||||
static_cast<int>(display_color.x * 255),
|
||||
static_cast<int>(display_color.y * 255),
|
||||
static_cast<int>(display_color.z * 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool PaletteWidget::ApplyROMPalette(gfx::Bitmap* bitmap, int group_index, int palette_index) {
|
||||
if (!bitmap || !rom_palettes_loaded_ ||
|
||||
group_index < 0 || group_index >= static_cast<int>(rom_palette_groups_.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const auto& selected_palette = rom_palette_groups_[group_index];
|
||||
|
||||
// Save current palette as backup
|
||||
SavePaletteBackup(bitmap->palette());
|
||||
|
||||
// Apply new palette
|
||||
if (palette_index >= 0 && palette_index < 8) {
|
||||
bitmap->SetPaletteWithTransparent(selected_palette, palette_index);
|
||||
} else {
|
||||
bitmap->SetPalette(selected_palette);
|
||||
}
|
||||
|
||||
// Queue texture update via Arena's deferred system
|
||||
gfx::Arena::Get().QueueTextureCommand(
|
||||
gfx::Arena::TextureCommandType::UPDATE, bitmap);
|
||||
|
||||
current_group_index_ = group_index;
|
||||
current_palette_index_ = palette_index;
|
||||
|
||||
return true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const gfx::SnesPalette* PaletteWidget::GetSelectedROMPalette() const {
|
||||
if (!rom_palettes_loaded_ || current_group_index_ < 0 ||
|
||||
current_group_index_ >= static_cast<int>(rom_palette_groups_.size())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &rom_palette_groups_[current_group_index_];
|
||||
}
|
||||
|
||||
void PaletteWidget::SavePaletteBackup(const gfx::SnesPalette& palette) {
|
||||
backup_palette_ = palette;
|
||||
}
|
||||
|
||||
bool PaletteWidget::RestorePaletteBackup(gfx::SnesPalette& palette) {
|
||||
if (backup_palette_.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
palette = backup_palette_;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PaletteWidget::DrawPaletteGrid(gfx::SnesPalette& palette, int cols) {
|
||||
for (int i = 0; i < static_cast<int>(palette.size()); i++) {
|
||||
if (i % cols != 0) ImGui::SameLine();
|
||||
|
||||
auto color = palette[i];
|
||||
ImVec4 display_color = color.rgb();
|
||||
|
||||
ImGui::PushID(i);
|
||||
|
||||
// Color button with editing capability
|
||||
if (ImGui::ColorButton("##color", display_color,
|
||||
ImGuiColorEditFlags_NoTooltip, ImVec2(30, 30))) {
|
||||
editing_color_index_ = i;
|
||||
temp_color_ = display_color;
|
||||
}
|
||||
|
||||
// Context menu for individual colors
|
||||
if (ImGui::BeginPopupContextItem()) {
|
||||
ImGui::Text("Color %d (0x%04X)", i, color.snes());
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Edit Color")) {
|
||||
editing_color_index_ = i;
|
||||
temp_color_ = display_color;
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Copy Color")) {
|
||||
// Could implement color clipboard here
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Reset to Black")) {
|
||||
palette[i] = gfx::SnesColor(0);
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Tooltip with detailed info
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Color %d\nSNES: 0x%04X\nRGB: (%d, %d, %d)\nClick to edit",
|
||||
i, color.snes(),
|
||||
static_cast<int>(display_color.x * 255),
|
||||
static_cast<int>(display_color.y * 255),
|
||||
static_cast<int>(display_color.z * 255));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
// Color editor popup
|
||||
if (editing_color_index_ >= 0) {
|
||||
ImGui::OpenPopup("Edit Color");
|
||||
|
||||
if (ImGui::BeginPopupModal("Edit Color", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::Text("Editing Color %d", editing_color_index_);
|
||||
|
||||
if (ImGui::ColorEdit4("Color", &temp_color_.x,
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
|
||||
// Update the palette color in real-time
|
||||
auto new_snes_color = gfx::SnesColor(temp_color_);
|
||||
palette[editing_color_index_] = new_snes_color;
|
||||
}
|
||||
|
||||
if (ImGui::Button("Apply")) {
|
||||
editing_color_index_ = -1;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
editing_color_index_ = -1;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteWidget::DrawROMPaletteSelector() {
|
||||
if (!rom_palettes_loaded_) {
|
||||
LoadROMPalettes();
|
||||
}
|
||||
|
||||
if (rom_palette_groups_.empty()) {
|
||||
ImGui::Text("No ROM palettes available");
|
||||
return;
|
||||
}
|
||||
|
||||
// Group selector
|
||||
ImGui::Text("Palette Group:");
|
||||
if (ImGui::Combo("##PaletteGroup", ¤t_group_index_,
|
||||
[](void* data, int idx, const char** out_text) -> bool {
|
||||
auto* names = static_cast<std::vector<std::string>*>(data);
|
||||
if (idx < 0 || idx >= static_cast<int>(names->size())) return false;
|
||||
*out_text = (*names)[idx].c_str();
|
||||
return true;
|
||||
}, &palette_group_names_, static_cast<int>(palette_group_names_.size()))) {
|
||||
// Group changed - could trigger preview update
|
||||
}
|
||||
|
||||
// Palette index selector
|
||||
ImGui::Text("Palette Index:");
|
||||
ImGui::SliderInt("##PaletteIndex", ¤t_palette_index_, 0, 7, "%d");
|
||||
|
||||
// Quick palette preview
|
||||
if (current_group_index_ < static_cast<int>(rom_palette_groups_.size())) {
|
||||
ImGui::Text("Preview:");
|
||||
const auto& preview_palette = rom_palette_groups_[current_group_index_];
|
||||
|
||||
// Show just first 8 colors in a row
|
||||
for (int i = 0; i < 8 && i < static_cast<int>(preview_palette.size()); i++) {
|
||||
if (i > 0) ImGui::SameLine();
|
||||
auto color = preview_palette[i];
|
||||
ImVec4 display_color = color.rgb();
|
||||
ImGui::ColorButton(("##preview" + std::to_string(i)).c_str(),
|
||||
display_color, ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteWidget::DrawColorEditControls(gfx::SnesColor& color, int color_index) {
|
||||
ImVec4 rgba = color.rgb();
|
||||
|
||||
ImGui::PushID(color_index);
|
||||
|
||||
if (ImGui::ColorEdit4("##color_edit", &rgba.x,
|
||||
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_DisplayRGB)) {
|
||||
color = gfx::SnesColor(rgba);
|
||||
}
|
||||
|
||||
// SNES-specific controls
|
||||
ImGui::Text("SNES Color: 0x%04X", color.snes());
|
||||
|
||||
// Individual RGB component sliders (0-31 for SNES)
|
||||
int r = (color.snes() & 0x1F);
|
||||
int g = (color.snes() >> 5) & 0x1F;
|
||||
int b = (color.snes() >> 10) & 0x1F;
|
||||
|
||||
if (ImGui::SliderInt("Red", &r, 0, 31)) {
|
||||
uint16_t new_color = (color.snes() & 0xFFE0) | (r & 0x1F);
|
||||
color = gfx::SnesColor(new_color);
|
||||
}
|
||||
|
||||
if (ImGui::SliderInt("Green", &g, 0, 31)) {
|
||||
uint16_t new_color = (color.snes() & 0xFC1F) | ((g & 0x1F) << 5);
|
||||
color = gfx::SnesColor(new_color);
|
||||
}
|
||||
|
||||
if (ImGui::SliderInt("Blue", &b, 0, 31)) {
|
||||
uint16_t new_color = (color.snes() & 0x83FF) | ((b & 0x1F) << 10);
|
||||
color = gfx::SnesColor(new_color);
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
void PaletteWidget::DrawPaletteAnalysis(const gfx::SnesPalette& palette) {
|
||||
ImGui::Text("Palette Information:");
|
||||
ImGui::Text("Size: %zu colors", palette.size());
|
||||
|
||||
// Color distribution analysis
|
||||
std::map<uint16_t, int> color_frequency;
|
||||
for (int i = 0; i < static_cast<int>(palette.size()); i++) {
|
||||
color_frequency[palette[i].snes()]++;
|
||||
}
|
||||
|
||||
ImGui::Text("Unique Colors: %zu", color_frequency.size());
|
||||
|
||||
if (color_frequency.size() < palette.size()) {
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 1), "Warning: Duplicate colors detected!");
|
||||
|
||||
if (ImGui::TreeNode("Duplicate Colors")) {
|
||||
for (const auto& [snes_color, count] : color_frequency) {
|
||||
if (count > 1) {
|
||||
ImVec4 display_color = gfx::SnesColor(snes_color).rgb();
|
||||
ImGui::ColorButton(("##dup" + std::to_string(snes_color)).c_str(),
|
||||
display_color, ImGuiColorEditFlags_NoTooltip, ImVec2(16, 16));
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("0x%04X appears %d times", snes_color, count);
|
||||
}
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
// Brightness analysis
|
||||
float total_brightness = 0.0f;
|
||||
float min_brightness = 1.0f;
|
||||
float max_brightness = 0.0f;
|
||||
|
||||
for (int i = 0; i < static_cast<int>(palette.size()); i++) {
|
||||
ImVec4 color = palette[i].rgb();
|
||||
float brightness = (color.x + color.y + color.z) / 3.0f;
|
||||
total_brightness += brightness;
|
||||
min_brightness = std::min(min_brightness, brightness);
|
||||
max_brightness = std::max(max_brightness, brightness);
|
||||
}
|
||||
|
||||
float avg_brightness = total_brightness / palette.size();
|
||||
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Brightness Analysis:");
|
||||
ImGui::Text("Average: %.2f", avg_brightness);
|
||||
ImGui::Text("Range: %.2f - %.2f", min_brightness, max_brightness);
|
||||
|
||||
// Show brightness as progress bar
|
||||
ImGui::Text("Brightness Distribution:");
|
||||
ImGui::ProgressBar(avg_brightness, ImVec2(-1, 0), "Avg");
|
||||
}
|
||||
|
||||
void PaletteWidget::LoadROMPalettes() {
|
||||
if (!rom_ || rom_palettes_loaded_) return;
|
||||
|
||||
try {
|
||||
const auto& palette_groups = rom_->palette_group();
|
||||
rom_palette_groups_.clear();
|
||||
palette_group_names_.clear();
|
||||
|
||||
// Load all available palette groups
|
||||
if (palette_groups.overworld_main.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.overworld_main[0]);
|
||||
palette_group_names_.push_back("Overworld Main");
|
||||
}
|
||||
if (palette_groups.overworld_aux.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.overworld_aux[0]);
|
||||
palette_group_names_.push_back("Overworld Aux");
|
||||
}
|
||||
if (palette_groups.overworld_animated.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.overworld_animated[0]);
|
||||
palette_group_names_.push_back("Overworld Animated");
|
||||
}
|
||||
if (palette_groups.dungeon_main.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.dungeon_main[0]);
|
||||
palette_group_names_.push_back("Dungeon Main");
|
||||
}
|
||||
if (palette_groups.global_sprites.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.global_sprites[0]);
|
||||
palette_group_names_.push_back("Global Sprites");
|
||||
}
|
||||
if (palette_groups.armors.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.armors[0]);
|
||||
palette_group_names_.push_back("Armor");
|
||||
}
|
||||
if (palette_groups.swords.size() > 0) {
|
||||
rom_palette_groups_.push_back(palette_groups.swords[0]);
|
||||
palette_group_names_.push_back("Swords");
|
||||
}
|
||||
|
||||
rom_palettes_loaded_ = true;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERROR("Enhanced Palette Editor", "Failed to load ROM palettes");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace yaze
|
||||
@@ -1,99 +0,0 @@
|
||||
#ifndef YAZE_APP_GUI_PALETTE_WIDGET_H
|
||||
#define YAZE_APP_GUI_PALETTE_WIDGET_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "app/gfx/types/snes_palette.h"
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/rom.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gui {
|
||||
|
||||
/**
|
||||
* @brief Palette widget with ROM integration, analysis tools, and AI tool call support
|
||||
*
|
||||
* This widget provides comprehensive palette editing capabilities including:
|
||||
* - Grid-based color editing with preview
|
||||
* - ROM palette browser and manager
|
||||
* - Color analysis and statistics
|
||||
* - Export/import functionality
|
||||
* - AI agent tool call integration for programmatic palette access
|
||||
*/
|
||||
class PaletteWidget {
|
||||
public:
|
||||
PaletteWidget() = default;
|
||||
|
||||
/**
|
||||
* @brief Initialize the palette editor with ROM data
|
||||
*/
|
||||
void Initialize(Rom* rom);
|
||||
|
||||
/**
|
||||
* @brief Show the main palette editor window
|
||||
*/
|
||||
void ShowPaletteEditor(gfx::SnesPalette& palette, const std::string& title = "Palette Editor");
|
||||
|
||||
/**
|
||||
* @brief Show the ROM palette manager window
|
||||
*/
|
||||
void ShowROMPaletteManager();
|
||||
|
||||
/**
|
||||
* @brief Show color analysis window for a bitmap
|
||||
*/
|
||||
void ShowColorAnalysis(const gfx::Bitmap& bitmap, const std::string& title = "Color Analysis");
|
||||
|
||||
/**
|
||||
* @brief Apply a ROM palette group to a bitmap
|
||||
*/
|
||||
bool ApplyROMPalette(gfx::Bitmap* bitmap, int group_index, int palette_index);
|
||||
|
||||
/**
|
||||
* @brief Get the currently selected ROM palette
|
||||
*/
|
||||
const gfx::SnesPalette* GetSelectedROMPalette() const;
|
||||
|
||||
/**
|
||||
* @brief Save current palette as backup
|
||||
*/
|
||||
void SavePaletteBackup(const gfx::SnesPalette& palette);
|
||||
|
||||
/**
|
||||
* @brief Restore palette from backup
|
||||
*/
|
||||
bool RestorePaletteBackup(gfx::SnesPalette& palette);
|
||||
|
||||
// Accessors
|
||||
bool IsROMLoaded() const { return rom_ != nullptr; }
|
||||
int GetCurrentGroupIndex() const { return current_group_index_; }
|
||||
int GetCurrentPaletteIndex() const { return current_palette_index_; }
|
||||
void DrawROMPaletteSelector();
|
||||
|
||||
private:
|
||||
void DrawPaletteGrid(gfx::SnesPalette& palette, int cols = 8);
|
||||
void DrawColorEditControls(gfx::SnesColor& color, int color_index);
|
||||
void DrawPaletteAnalysis(const gfx::SnesPalette& palette);
|
||||
void LoadROMPalettes();
|
||||
|
||||
Rom* rom_ = nullptr;
|
||||
std::vector<gfx::SnesPalette> rom_palette_groups_;
|
||||
std::vector<std::string> palette_group_names_;
|
||||
gfx::SnesPalette backup_palette_;
|
||||
|
||||
int current_group_index_ = 0;
|
||||
int current_palette_index_ = 0;
|
||||
bool rom_palettes_loaded_ = false;
|
||||
bool show_color_analysis_ = false;
|
||||
bool show_rom_manager_ = false;
|
||||
|
||||
// Color editing state
|
||||
int editing_color_index_ = -1;
|
||||
ImVec4 temp_color_ = ImVec4(0, 0, 0, 1);
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_GUI_WIDGETS_PALETTE_WIDGET_H
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "app/gui/themed_widgets.h"
|
||||
#include "app/gui/widgets/themed_widgets.h"
|
||||
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "app/gfx/types/snes_color.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef YAZE_APP_GUI_THEMED_WIDGETS_H
|
||||
#define YAZE_APP_GUI_THEMED_WIDGETS_H
|
||||
|
||||
#include "app/gui/color.h"
|
||||
#include "app/gui/layout_helpers.h"
|
||||
#include "app/gui/theme_manager.h"
|
||||
#include "app/gui/core/color.h"
|
||||
#include "app/gui/core/layout_helpers.h"
|
||||
#include "app/gui/core/theme_manager.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "app/gfx/core/bitmap.h"
|
||||
#include "app/gui/canvas.h"
|
||||
#include "app/gui/canvas/canvas.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze::gui {
|
||||
|
||||
Reference in New Issue
Block a user