yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
tile16_edit_session.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_OVERWORLD_TILE16_TILE16_EDIT_SESSION_H_
2#define YAZE_APP_EDITOR_OVERWORLD_TILE16_TILE16_EDIT_SESSION_H_
3
4#include <algorithm>
5#include <array>
6#include <chrono>
7#include <functional>
8#include <map>
9#include <optional>
10#include <utility>
11#include <vector>
12
13#include "absl/status/status.h"
16#include "app/gfx/core/bitmap.h"
20#include "rom/rom.h"
24
25namespace yaze {
26namespace zelda3 {
27struct GameData;
28} // namespace zelda3
29
30namespace editor {
31
40 public:
43
46 std::array<uint8_t, 0x200>& all_tiles_types);
47
48 // Bind to the owning document before editing. Standalone sessions use their
49 // own history and read unchanged definitions from ROM.
50 void BindDocument(std::vector<gfx::Tile16>* definitions, UndoManager* history,
51 std::function<void()> before_edit) {
52 document_definitions_ = definitions;
53 history_ = history ? history : &undo_manager_;
54 before_edit_ = std::move(before_edit);
55 }
56 bool has_shared_history() const { return history_ != &undo_manager_; }
57 absl::Status ReplaceCurrentTile(const gfx::Tile16& data);
58
59 absl::Status LoadTile8();
60 absl::Status SetCurrentTile(int id);
61 void RequestTileSwitch(int target_tile_id);
62
63 absl::Status CopyTile16ToClipboard(int tile_id);
64 absl::Status PasteTile16FromClipboard();
65 absl::Status SaveTile16ToScratchSpace(int slot);
66 absl::Status LoadTile16FromScratchSpace(int slot);
67 absl::Status ClearScratchSpace(int slot);
68
69 absl::Status FlipTile16Horizontal();
70 absl::Status FlipTile16Vertical();
71 absl::Status RotateTile16();
72 absl::Status FillTile16WithTile8(int tile8_id);
73 absl::Status ClearTile16();
74
75 absl::Status CyclePalette(bool forward = true);
76 absl::Status ApplyPaletteToAll(uint8_t palette_id);
77 absl::Status ApplyPaletteToQuadrant(int quadrant, uint8_t palette_id);
78 absl::Status PreviewPaletteChange(uint8_t palette_id);
79
80 absl::Status Undo();
81 absl::Status Redo();
82 bool CanUndo() const { return history_->CanUndo(); }
83 bool CanRedo() const { return history_->CanRedo(); }
84
85 void EnableLivePreview(bool enable) { live_preview_enabled_ = enable; }
87 absl::Status UpdateLivePreview();
88
89 absl::Status ValidateTile16Data();
90 bool IsTile16Valid(int tile_id) const;
91
92 // Legacy standalone serialization adapters. Bound editor sessions use the
93 // owning document Save and shared Undo instead. Never exposed by the UI.
94 absl::Status SaveTile16ToROM();
95 absl::Status UpdateOverworldTilemap();
96 absl::Status CommitChangesToBlockset();
97 absl::Status CommitChangesToOverworld();
98 absl::Status DiscardChanges();
99
100 bool has_pending_changes() const { return !document_edits_.empty(); }
102 return static_cast<int>(document_edits_.size());
103 }
104 bool is_tile_modified(int tile_id) const {
105 return document_edits_.find(tile_id) != document_edits_.end();
106 }
107 const gfx::Bitmap* GetPendingTileBitmap(int tile_id) const {
108 auto it = edited_tile_bitmaps_.find(tile_id);
109 return it != edited_tile_bitmaps_.end() ? &it->second : nullptr;
110 }
111 const std::map<int, gfx::Tile16>& pending_tile16_changes() const {
112 return document_edits_;
113 }
114 const std::map<int, gfx::Bitmap>& pending_tile16_bitmaps() const {
116 }
117
118 absl::Status CommitAllChanges();
119 void DiscardAllChanges();
122
123 absl::Status UpdateTile8Palette(int tile8_id);
124 absl::Status RefreshAllPalettes();
125
126 int GetActualPaletteSlot(int palette_button, int sheet_index) const;
127 int GetSheetIndexForTile8(int tile8_id) const;
130 const gfx::SnesPalette& source, int target_row) const;
131 int GetEncodedPaletteRow(uint8_t pixel_value) const;
132
133 absl::Status UpdateROMTile16Data();
134 absl::Status RefreshTile16Blockset();
136 absl::Status RegenerateTile16BitmapFromROM();
137 absl::Status UpdateBlocksetBitmap();
138 absl::Status PickTile8FromTile16(Tile16LocalPos position);
139 absl::Status DrawToCurrentTile16(Tile16LocalPos pos,
140 const gfx::Bitmap* source_tile = nullptr);
141 // Render the exact proposed stamp without changing the document/history.
142 absl::Status BuildStampPreview(Tile16LocalPos pos, gfx::Bitmap* output) const;
143 absl::Status HandleTile16CanvasClick(Tile16LocalPos tile_position,
144 bool left_click, bool right_click);
145
147 Tile16LocalPos display_position);
148
149 absl::Status SaveLayoutToScratch(int slot);
150 absl::Status LoadLayoutFromScratch(int slot);
151
152 void SetRom(Rom* rom) { rom_ = rom; }
153 Rom* rom() const { return rom_; }
156
158
160 std::function<void(const std::vector<Tile16Commit>&)> callback) {
161 on_document_changed_ = std::move(callback);
162 }
164 std::function<absl::Status(const std::vector<Tile16Commit>&)> callback) {
165 on_changes_committed_ = std::move(callback);
166 }
167 void set_on_current_tile_changed(std::function<void(int)> callback) {
168 on_current_tile_changed_ = std::move(callback);
169 }
171 void set_on_tile_selection_changed(std::function<void(int)> callback) {
172 on_tile_selection_changed_ = std::move(callback);
173 }
176 std::function<void(float width, float height)> callback) {
177 on_tile8_sheet_resized_ = std::move(callback);
178 }
179
180 int current_palette() const { return current_palette_; }
182 current_palette_ = static_cast<uint8_t>(std::clamp(palette, 0, 7));
183 }
186 int current_tile16() const { return current_tile16_; }
187 int current_tile8() const { return current_tile8_; }
188 void set_current_tile8(int id) { current_tile8_ = id; }
189 int active_quadrant() const { return active_quadrant_; }
190 void set_active_quadrant(int quadrant) {
191 active_quadrant_ = std::clamp(quadrant, 0, 3);
192 }
195
196 bool x_flip() const { return x_flip_; }
197 bool y_flip() const { return y_flip_; }
198 bool priority_tile() const { return priority_tile_; }
199 bool* mutable_x_flip() { return &x_flip_; }
200 bool* mutable_y_flip() { return &y_flip_; }
202
204 void set_map_blockset_loaded(bool loaded) { map_blockset_loaded_ = loaded; }
205
208 std::chrono::steady_clock::time_point last_rom_write_time() const {
210 }
211
212 int jump_to_tile_id() const { return jump_to_tile_id_; }
214 bool scroll_to_current() const { return scroll_to_current_; }
215 void set_scroll_to_current(bool scroll) { scroll_to_current_ = scroll; }
216 int current_page() const { return current_page_; }
217 void set_current_page(int page) { current_page_ = page; }
218 static constexpr int kTilesPerPage = 64;
219 static constexpr int kTilesPerRow = 8;
220
226 }
227
231 const std::vector<zelda3::Tile8PixelData>& current_gfx_individual() const {
233 }
234 std::vector<zelda3::Tile8PixelData>& mutable_current_gfx_individual() {
236 }
237
240 const Tile16ScratchData& scratch_slot(int i) const {
241 return scratch_space_[i];
242 }
244
245 bool auto_tile_mode() const { return auto_tile_mode_; }
247 bool grid_snap_enabled() const { return grid_snap_enabled_; }
249 bool show_tile_info() const { return show_tile_info_; }
253 bool show_tile_grid() const { return show_tile_grid_; }
257 int tile8_stamp_size() const { return tile8_stamp_size_; }
258 void set_tile8_stamp_size(int size) { tile8_stamp_size_ = size; }
268
275 }
281
282 const gfx::SnesPalette& palette() const { return palette_; }
284 return overworld_palette_;
285 }
286 const std::array<uint8_t, 0x200>& all_tiles_types() const {
287 return all_tiles_types_;
288 }
289
290 absl::Status RebuildTile8UsageCache();
297 }
298
300 void AnalyzeTile8SourceData() const;
301
303
304 bool HasCurrentGfxBitmap() const {
305 return current_gfx_bmp_ != nullptr && current_gfx_bmp_->is_active();
306 }
309 }
310
311 absl::Status BuildTile16BitmapFromData(const gfx::Tile16& tile_data,
312 gfx::Bitmap* output_bitmap) const;
313 void CopyTileBitmapToBlockset(int tile_id, const gfx::Bitmap& tile_bitmap);
314 void CopyTile16ToAtlas(int tile_id);
315
316 private:
317 absl::Status RunEdit(const std::function<absl::Status()>& operation);
318 absl::Status ApplyDefinitions(const std::vector<Tile16Commit>& definitions);
319 absl::StatusOr<gfx::Tile16> ReadDocumentTile(int id) const;
320 absl::Status PasteTile16FromClipboardImpl();
321 absl::Status LoadTile16FromScratchSpaceImpl(int slot);
322 absl::Status FlipTile16HorizontalImpl();
323 absl::Status FlipTile16VerticalImpl();
324 absl::Status RotateTile16Impl();
325 absl::Status FillTile16WithTile8Impl(int tile8_id);
326 absl::Status ClearTile16Impl();
327 absl::Status ApplyPaletteToAllImpl(uint8_t palette_id);
328 absl::Status ApplyPaletteToQuadrantImpl(int quadrant, uint8_t palette_id);
329 absl::StatusOr<std::vector<zelda3::Tile16StampMutation>> BuildStampMutations(
330 Tile16LocalPos pos) const;
332 const gfx::Bitmap* source_tile);
334 int target_row,
335 int tile8_id) const;
336 bool BitmapHasEncodedPaletteRows(const gfx::Bitmap& bitmap) const;
337
338 // Keep naturally aligned document/history data before small UI flags.
339 std::vector<gfx::Tile16>* document_definitions_ = nullptr;
341 Rom* rom_ = nullptr;
343 std::chrono::steady_clock::time_point last_rom_write_time_{};
347 std::map<int, gfx::Tile16> document_edits_;
348 std::map<int, gfx::Bitmap> edited_tile_bitmaps_;
349 std::vector<zelda3::Tile8PixelData> current_gfx_individual_;
350 std::function<void()> before_edit_;
351 std::function<void(const std::vector<Tile16Commit>&)> on_document_changed_;
352 std::function<absl::Status(const std::vector<Tile16Commit>&)>
354 std::function<void(int)> on_current_tile_changed_;
355 std::function<void(int)> on_tile_selection_changed_;
356 std::function<void(float, float)> on_tile8_sheet_resized_;
358 std::array<Tile16LayoutScratch, 4> layout_scratch_;
366 std::array<Tile16ScratchData, 4> scratch_space_;
379 bool x_flip_ = false;
380 bool y_flip_ = false;
381 bool priority_tile_ = false;
382 uint8_t current_palette_ = 0;
384 bool preview_dirty_ = false;
385 bool auto_tile_mode_ = false;
387 bool show_tile_info_ = true;
389 bool show_tile_grid_ = true;
397 bool scroll_to_current_ = false;
398 std::array<uint8_t, 0x200> all_tiles_types_{};
399};
400
401} // namespace editor
402} // namespace yaze
403
404#endif // YAZE_APP_EDITOR_OVERWORLD_TILE16_TILE16_EDIT_SESSION_H_
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:49
Domain session for Tile16 editing (no ImGui).
const std::map< int, gfx::Tile16 > & pending_tile16_changes() const
absl::Status ApplyDefinitions(const std::vector< Tile16Commit > &definitions)
gfx::SnesPalette CreateRemappedPaletteForTile8(const gfx::SnesPalette &source, int target_row, int tile8_id) const
absl::Status ApplyPaletteToAllImpl(uint8_t palette_id)
int GetActualPaletteSlot(int palette_button, int sheet_index) const
gfx::SnesPalette CreateRemappedPaletteForViewing(const gfx::SnesPalette &source, int target_row) const
void set_on_current_tile_changed(std::function< void(int)> callback)
const Tile16ClipboardData & clipboard() const
std::array< Tile16ScratchData, 4 > scratch_space_
bool IsTile16Valid(int tile_id) const
absl::Status HandleTile16CanvasClick(Tile16LocalPos tile_position, bool left_click, bool right_click)
const std::vector< zelda3::Tile8PixelData > & current_gfx_individual() const
absl::Status RunEdit(const std::function< absl::Status()> &operation)
absl::Status ApplyPaletteToQuadrantImpl(int quadrant, uint8_t palette_id)
zelda3::GameData * game_data() const
absl::StatusOr< gfx::Tile16 > ReadDocumentTile(int id) const
absl::Status FillTile16WithTile8Impl(int tile8_id)
void CopyTileBitmapToBlockset(int tile_id, const gfx::Bitmap &tile_bitmap)
void set_palette(const gfx::SnesPalette &palette)
const std::array< uint8_t, 0x200 > & all_tiles_types() const
void set_on_document_changed(std::function< void(const std::vector< Tile16Commit > &)> callback)
std::map< int, gfx::Bitmap > edited_tile_bitmaps_
absl::Status CyclePalette(bool forward=true)
absl::Status InitializeBitmaps(gfx::Bitmap &tile16_blockset_bmp, gfx::Bitmap &current_gfx_bmp, std::array< uint8_t, 0x200 > &all_tiles_types)
const gfx::SnesPalette & overworld_palette() const
absl::Status PickTile8FromTile16(Tile16LocalPos position)
absl::Status ApplyPaletteToAll(uint8_t palette_id)
absl::Status ReplaceCurrentTile(const gfx::Tile16 &data)
std::array< uint8_t, 0x200 > all_tiles_types_
Tile16ScratchData & scratch_slot(int i)
absl::Status BuildStampPreview(Tile16LocalPos pos, gfx::Bitmap *output) const
const gfx::Bitmap & current_tile16_bmp() const
void SetGameData(zelda3::GameData *game_data)
absl::Status DrawToCurrentTile16Impl(Tile16LocalPos pos, const gfx::Bitmap *source_tile)
std::chrono::steady_clock::time_point last_rom_write_time() const
absl::Status DrawToCurrentTile16(Tile16LocalPos pos, const gfx::Bitmap *source_tile=nullptr)
std::function< void(int)> on_tile_selection_changed_
void set_on_tile_selection_changed(std::function< void(int)> callback)
Optional: UI can sync blockset selector when current tile changes.
absl::Status LoadLayoutFromScratch(int slot)
std::function< void(int)> on_current_tile_changed_
absl::Status CopyTile16ToClipboard(int tile_id)
std::chrono::steady_clock::time_point last_rom_write_time_
std::map< int, gfx::Tile16 > document_edits_
absl::Status PreviewPaletteChange(uint8_t palette_id)
absl::Status BuildTile16BitmapFromData(const gfx::Tile16 &tile_data, gfx::Bitmap *output_bitmap) const
Tile16LayoutScratch & layout_scratch(int i)
const std::map< int, gfx::Bitmap > & pending_tile16_bitmaps() const
absl::Status SaveLayoutToScratch(int slot)
Tile16EditSession(Rom *rom, gfx::Tilemap *tile16_blockset)
const gfx::Tile16 & current_tile16_data() const
absl::Status FillTile16WithTile8(int tile8_id)
absl::Status ApplyPaletteToQuadrant(int quadrant, uint8_t palette_id)
std::function< void(float, float)> on_tile8_sheet_resized_
absl::Status LoadTile16FromScratchSpace(int slot)
std::array< Tile16LayoutScratch, 4 > layout_scratch_
zelda3::Tile8UsageIndex tile8_usage_cache_
void RequestTileSwitch(int target_tile_id)
std::vector< zelda3::Tile8PixelData > & mutable_current_gfx_individual()
absl::Status SaveTile16ToScratchSpace(int slot)
std::function< void(const std::vector< Tile16Commit > &) on_document_changed_)
const Tile16ScratchData & scratch_slot(int i) const
void set_on_changes_committed(std::function< absl::Status(const std::vector< Tile16Commit > &)> callback)
std::function< absl::Status(const std::vector< Tile16Commit > &) on_changes_committed_)
absl::Status UpdateTile8Palette(int tile8_id)
int GetEncodedPaletteRow(uint8_t pixel_value) const
const gfx::SnesPalette & palette() const
const gfx::SnesPalette * ResolveDisplayPalette() const
int GetSheetIndexForTile8(int tile8_id) const
static Tile16LocalPos Tile16PreviewDisplayPixelToTilePosition(Tile16LocalPos display_position)
bool BitmapHasEncodedPaletteRows(const gfx::Bitmap &bitmap) const
const gfx::Bitmap & Tile8PreviewBitmap() const
bool is_tile_modified(int tile_id) const
const zelda3::Tile8UsageIndex & tile8_usage_cache() const
void set_on_tile8_sheet_resized(std::function< void(float width, float height)> callback)
Optional: UI updates Tile8 source canvas size after LoadTile8.
absl::Status LoadTile16FromScratchSpaceImpl(int slot)
const gfx::Bitmap * GetPendingTileBitmap(int tile_id) const
std::vector< gfx::Tile16 > * document_definitions_
absl::StatusOr< std::vector< zelda3::Tile16StampMutation > > BuildStampMutations(Tile16LocalPos pos) const
std::vector< zelda3::Tile8PixelData > current_gfx_individual_
void BindDocument(std::vector< gfx::Tile16 > *definitions, UndoManager *history, std::function< void()> before_edit)
void set_edit_mode(Tile16EditMode mode)
absl::Status ClearScratchSpace(int slot)
Manages undo/redo stacks for a single editor.
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
bool is_active() const
Definition bitmap.h:414
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
Tile composition of four 8x8 tiles.
Definition snes_tile.h:142
std::array< std::vector< Tile8UsageHit >, kMaxTile8UsageId > Tile8UsageIndex
Tilemap structure for SNES tile-based graphics management.
Definition tilemap.h:118