Refactor EditorManager and OverworldEditor for enhanced functionality and error handling

- Updated EditorManager to improve welcome screen logic, ensuring it only displays in truly empty states and not when a ROM is loaded but current_rom_ is null.
- Enhanced error handling in EditorManager by routing editor errors to the toast manager for better user feedback.
- Improved OverworldEditor with enhanced tile interaction detection and added scratch space functionality for better layout management.
- Introduced a new ScratchSpaceSlot structure in OverworldEditor to manage scratch space for tile16 layouts, allowing for more flexible editing and selection.
- Added utility functions in canvas_utils for grid alignment and effective scaling, improving overall canvas interaction.
- Implemented an enhanced palette editor with ROM integration, providing users with tools for color analysis and palette management.
This commit is contained in:
scawful
2025-09-27 15:24:58 -04:00
parent 261032b1bd
commit a9ead0a45c
17 changed files with 4434 additions and 821 deletions

View File

@@ -2,6 +2,8 @@
#define YAZE_APP_EDITOR_TILE16EDITOR_H
#include <array>
#include <chrono>
#include <functional>
#include <vector>
#include "absl/status/status.h"
@@ -19,29 +21,43 @@
namespace yaze {
namespace editor {
// Constants for tile editing
constexpr int kTile16Size = 16;
constexpr int kTile8Size = 8;
constexpr int kTilesheetEditorWidth = 0x100;
constexpr int kTilesheetEditorHeight = 0x4000;
constexpr int kTile16CanvasSize = 0x20;
constexpr int kTile8CanvasHeight = 0x175;
constexpr int kNumScratchSlots = 4;
constexpr int kNumPalettes = 8;
constexpr int kTile8PixelCount = 64;
constexpr int kTile16PixelCount = 256;
/**
* @brief Popup window to edit Tile16 data
*/
class Tile16Editor : public gfx::GfxContext {
public:
Tile16Editor(Rom *rom, gfx::Tilemap *tile16_blockset)
Tile16Editor(Rom* rom, gfx::Tilemap* tile16_blockset)
: rom_(rom), tile16_blockset_(tile16_blockset) {}
absl::Status Initialize(const gfx::Bitmap &tile16_blockset_bmp,
const gfx::Bitmap &current_gfx_bmp,
std::array<uint8_t, 0x200> &all_tiles_types);
absl::Status Initialize(const gfx::Bitmap& tile16_blockset_bmp,
const gfx::Bitmap& current_gfx_bmp,
std::array<uint8_t, 0x200>& all_tiles_types);
absl::Status Update();
void DrawTile16Editor();
absl::Status UpdateTile16Transfer();
absl::Status UpdateBlockset();
// Scratch space for tile16 layouts
void DrawScratchSpace();
absl::Status SaveLayoutToScratch(int slot);
absl::Status LoadLayoutFromScratch(int slot);
absl::Status DrawToCurrentTile16(ImVec2 pos);
absl::Status UpdateTile16Edit();
absl::Status UpdateTransferTileCanvas();
absl::Status LoadTile8();
absl::Status SetCurrentTile(int id);
@@ -53,14 +69,61 @@ class Tile16Editor : public gfx::GfxContext {
absl::Status LoadTile16FromScratchSpace(int slot);
absl::Status ClearScratchSpace(int slot);
void set_rom(Rom *rom) { rom_ = rom; }
Rom *rom() const { return rom_; }
// Advanced editing features
absl::Status FlipTile16Horizontal();
absl::Status FlipTile16Vertical();
absl::Status RotateTile16();
absl::Status FillTile16WithTile8(int tile8_id);
absl::Status AutoTileTile16();
absl::Status ClearTile16();
// Palette management
absl::Status CyclePalette(bool forward = true);
absl::Status ApplyPaletteToAll(uint8_t palette_id);
absl::Status PreviewPaletteChange(uint8_t palette_id);
// Batch operations
absl::Status ApplyToSelection(const std::function<void(int)>& operation);
absl::Status BatchEdit(const std::vector<int>& tile_ids,
const std::function<void(int)>& operation);
// History and undo system
absl::Status Undo();
absl::Status Redo();
void SaveUndoState();
// Live preview system
void EnableLivePreview(bool enable) { live_preview_enabled_ = enable; }
absl::Status UpdateLivePreview();
// Validation and integrity checks
absl::Status ValidateTile16Data();
bool IsTile16Valid(int tile_id) const;
// Integration with overworld system
absl::Status SaveTile16ToROM();
absl::Status UpdateOverworldTilemap();
absl::Status CommitChangesToBlockset();
// Helper methods for palette management
absl::Status UpdateTile8Palette(int tile8_id);
absl::Status RefreshAllPalettes();
void DrawPaletteSettings();
// ROM data access and modification
absl::Status UpdateROMTile16Data();
absl::Status RefreshTile16Blockset();
gfx::Tile16* GetCurrentTile16Data();
// Manual tile8 input controls
void DrawManualTile8Inputs();
void set_rom(Rom* rom) { rom_ = rom; }
Rom* rom() const { return rom_; }
private:
Rom *rom_ = nullptr;
Rom* rom_ = nullptr;
bool map_blockset_loaded_ = false;
bool transfer_started_ = false;
bool transfer_blockset_loaded_ = false;
bool x_flip = false;
bool y_flip = false;
bool priority_tile = false;
@@ -78,19 +141,67 @@ class Tile16Editor : public gfx::GfxContext {
std::array<gfx::Bitmap, 4> scratch_space_;
std::array<bool, 4> scratch_space_used_ = {false, false, false, false};
// Layout scratch space for tile16 arrangements (4 slots of 8x8 grids)
struct LayoutScratch {
std::array<std::array<int, 8>, 8> tile_layout; // 8x8 grid of tile16 IDs
bool in_use = false;
std::string name = "Empty";
};
std::array<LayoutScratch, 4> layout_scratch_;
// Undo/Redo system
struct UndoState {
int tile_id;
gfx::Bitmap tile_bitmap;
gfx::Tile16 tile_data;
uint8_t palette;
bool x_flip, y_flip, priority;
};
std::vector<UndoState> undo_stack_;
std::vector<UndoState> redo_stack_;
static constexpr size_t kMaxUndoStates_ = 50;
// Live preview system
bool live_preview_enabled_ = true;
gfx::Bitmap preview_tile16_;
bool preview_dirty_ = false;
// Selection system
std::vector<int> selected_tiles_;
int selection_start_tile_ = -1;
bool multi_select_mode_ = false;
// Advanced editing state
bool auto_tile_mode_ = false;
bool grid_snap_enabled_ = true;
bool show_tile_info_ = true;
bool show_palette_preview_ = true;
// Palette management settings
bool show_palette_settings_ = false;
int current_palette_group_ = 0; // 0=overworld_main, 1=aux1, 2=aux2, etc.
uint8_t palette_normalization_mask_ = 0x0F; // Default 4-bit mask
bool auto_normalize_pixels_ = true;
// Performance tracking
std::chrono::steady_clock::time_point last_edit_time_;
bool batch_mode_ = false;
util::NotifyValue<uint32_t> notify_tile16;
util::NotifyValue<uint8_t> notify_palette;
std::array<uint8_t, 0x200> all_tiles_types_;
// Tile16 blockset for selecting the tile to edit
gui::Canvas blockset_canvas_{"blocksetCanvas", ImVec2(0x100, 0x4000),
gui::CanvasGridSize::k32x32,};
gui::Canvas blockset_canvas_{
"blocksetCanvas", ImVec2(kTilesheetEditorWidth, kTilesheetEditorHeight),
gui::CanvasGridSize::k32x32};
gfx::Bitmap tile16_blockset_bmp_;
// Canvas for editing the selected tile
gui::Canvas tile16_edit_canvas_{"Tile16EditCanvas", ImVec2(0x40, 0x40),
gui::CanvasGridSize::k64x64};
// Canvas for editing the selected tile - smaller size for table fit
gui::Canvas tile16_edit_canvas_{"Tile16EditCanvas",
ImVec2(128, 128), // Reduced from kTile16CanvasSize to fit tables
gui::CanvasGridSize::k64x64, 2.0f}; // Reduced scale to fit tables
gfx::Bitmap current_tile16_bmp_;
// Tile8 canvas to get the tile to drawing in the tile16_edit_canvas_
@@ -100,23 +211,15 @@ class Tile16Editor : public gfx::GfxContext {
gui::CanvasGridSize::k32x32};
gfx::Bitmap current_gfx_bmp_;
gui::Canvas transfer_canvas_;
gfx::Bitmap transfer_blockset_bmp_;
gui::Table tile_edit_table_{"##TileEditTable", 3, ImGuiTableFlags_Borders};
gfx::Tilemap *tile16_blockset_ = nullptr;
gfx::Tilemap* tile16_blockset_ = nullptr;
std::vector<gfx::Bitmap> current_gfx_individual_;
PaletteEditor palette_editor_;
gfx::SnesPalette palette_;
absl::Status status_;
Rom *transfer_rom_ = nullptr;
zelda3::Overworld transfer_overworld_{transfer_rom_};
std::array<gfx::Bitmap, kNumGfxSheets> transfer_gfx_;
absl::Status transfer_status_;
};
} // namespace editor