yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
graphics_editor.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_GRAPHICS_EDITOR_H
2#define YAZE_APP_EDITOR_GRAPHICS_EDITOR_H
3
4#include <array>
5#include <functional>
6#include <memory>
7#include <optional>
8#include <set>
9#include <string>
10#include <vector>
11
12#include <map>
13#include "absl/status/status.h"
14#include "app/editor/editor.h"
28#include "app/gfx/core/bitmap.h"
31#include "rom/rom.h"
32#include "zelda3/game_data.h"
33
34namespace yaze {
35namespace editor {
36
37class GraphicsEditorSaveStoplossTestPeer;
38
39// Super Donkey prototype graphics offsets (from leaked dev materials)
40const std::string kSuperDonkeyTiles[] = {
41 "97C05", "98219", "9871E", "98C00", "99084", "995AF", "99DE0", "9A27E",
42 "9A741", "9AC31", "9B07E", "9B55C", "9B963", "9BB99", "9C009", "9C4B4",
43 "9C92B", "9CDD6", "9D2C2", "9E037", "9E527", "9EA56", "9EF65", "9FCD1",
44 "A0193", "A059E", "A0B17", "A0FB6", "A14A5", "A1988", "A1E66", "A232B",
45 "A27F0", "A2B6E", "A302C", "A3453", "A38CA", "A42BB", "A470C", "A4BA9",
46 "A5089", "A5385", "A5742", "A5BCC", "A6017", "A6361", "A66F8"};
47
48const std::string kSuperDonkeySprites[] = {
49 "A8E5D", "A9435", "A9934", "A9D83", "AA2F1", "AA6D4", "AABE4", "AB127",
50 "AB65A", "ABBDD", "AC38D", "AC797", "ACCC8", "AD0AE", "AD245", "AD554",
51 "ADAAC", "ADECC", "AE453", "AE9D2", "AEF40", "AF3C9", "AF92E", "AFE9D",
52 "B03D2", "B09AC", "B0F0C", "B1430", "B1859", "B1E01", "B229A", "B2854",
53 "B2D27", "B31D7", "B3B58", "B40B5", "B45A5", "B4D64", "B5031", "B555F",
54 "B5F30", "B6858", "B70DD", "B7526", "B79EC", "B7C83", "B80F7", "B85CC",
55 "B8A3F", "B8F97", "B94F2", "B9A20", "B9E9A", "BA3A2", "BA8F6", "BACDC",
56 "BB1F9", "BB781", "BBCCA", "BC26D", "BC7D4", "BCBB0", "BD082", "BD5FC",
57 "BE115", "BE5C2", "BEB63", "BF0CB", "BF607", "BFA55", "BFD71", "C017D",
58 "C0567", "C0981", "C0BA7", "C116D", "C166A", "C1FE0", "C24CE", "C2B19"};
59
74class GraphicsEditor : public Editor {
75 public:
76 explicit GraphicsEditor(Rom* rom = nullptr) : rom_(rom) {
78 }
79
80 void SetDependencies(const EditorDependencies& deps) override {
82 if (gfx_group_panel_) {
83 gfx_group_panel_->SetWorkspaceState(deps.gfx_group_workspace);
84 }
85 }
86
89 main_graphics_usage_ = std::move(callback);
91 gfx_group_panel_->SetMainUsageCallback(main_graphics_usage_);
92 }
100 room_usage_provider_ = std::move(provider);
102 usage_preview_view_->SetLiveRoomProvider(room_usage_provider_);
103 }
106 overworld_usage_provider_ = std::move(provider);
108 usage_preview_view_->SetLiveOverworldProvider(overworld_usage_provider_);
109 }
112 gfx_group_panel_->DetachRuntimeContext();
117 }
118 void Initialize() override;
119 absl::Status Load() override;
120 absl::Status Save() override;
121 // Detached assets save independently of ROM sheet serialization settings.
122 absl::Status SaveScratchAssets();
123 absl::Status Update() override;
124 // Cut, Copy and Paste use the system clipboard as PNG (pixel editor).
130 absl::StatusOr<std::vector<GraphicsSavePlanEntry>> PlanGraphicsSave();
131
132 absl::Status Cut() override;
133 absl::Status Copy() override;
134 absl::Status Paste() override;
135 absl::Status Undo() override;
136 absl::Status Redo() override;
137 absl::Status Find() override { return absl::UnimplementedError("Find"); }
138 void ContributeStatus(StatusBar* status_bar) override;
140
143 (pixel_editor_panel_ && pixel_editor_panel_->HasActiveStroke()) ||
144 (scratch_view_ && scratch_view_->HasPendingChanges());
145 }
146
147 // Coordinated ROM save: Save() clears the modified-sheet set, so a failed
148 // save elsewhere must put it back (the ROM bytes are restored separately).
149 absl::Status BeginSaveTransaction() override {
150 // A floating paste has visible pixels but no committed sheet diff. Do not
151 // report it saved or choose its placement on the user's behalf.
153 return absl::FailedPreconditionError(
154 "Commit or cancel the floating paste in Graphics before saving "
155 "(Enter to commit, Esc to cancel)");
157 pixel_editor_panel_->FinishReleasedGesture();
158 if (pixel_editor_panel_->HasActiveStroke())
159 return absl::FailedPreconditionError(
160 "Finish the pixel stroke before saving");
161 }
163 return absl::OkStatus();
164 }
171 void CommitSaveTransaction() override {
173 }
174
175 // Set the ROM pointer (propagates to panels that cache `Rom*`.)
176 void set_rom(Rom* rom) {
177 if (rom_ != rom) {
180 }
181 rom_ = rom;
183 sheet_browser_panel_->SetDataSources(
185 [this]() -> const project::YazeProject* { return project(); });
186 }
188 pixel_editor_panel_->SetRom(rom);
189 }
190 if (link_sprite_panel_) {
191 link_sprite_panel_->SetRom(rom);
192 }
193 if (gfx_group_panel_) {
194 gfx_group_panel_->SetRom(rom);
195 }
196 if (paletteset_panel_) {
197 paletteset_panel_->SetRom(rom);
198 }
199 if (polyhedral_panel_) {
200 polyhedral_panel_->SetRom(rom);
201 }
203 usage_preview_view_->SetRom(rom);
204 }
205 }
206
207 // Set the game data pointer
212 sheet_browser_panel_->SetDataSources(
214 [this]() -> const project::YazeProject* { return project(); });
215 }
216 if (gfx_group_panel_) {
217 gfx_group_panel_->SetGameData(game_data);
218 }
219 if (paletteset_panel_) {
220 paletteset_panel_->SetGameData(game_data);
221 }
223 usage_preview_view_->SetGameData(game_data);
224 }
225 }
226
227 // Editor shortcuts
228 void NextSheet();
229 // Keyboard shortcut targets (shortcut_configurator.cc).
230 void SetPixelTool(PixelTool tool);
231 void ZoomIn();
232 void ZoomOut();
233 void ToggleGrid();
234 void PrevSheet();
235 void SelectSheet(uint16_t sheet_id);
236 void FinishPixelGesture();
237 // Opens only Pixel Editor and Usage Preview, retaining the source editor's
238 // resolved colors and live preview for this ROM session.
240 absl::Status ImportScratchBin(const std::string& path, int bpp, size_t offset,
241 const gfx::SnesPalette& palette = {});
242 void SetScratchPreview(std::string label, ScratchPreviewCallback callback);
243 // Callable command only; the existing controls own its future UI entry point.
244 absl::Status ReorderSourcePalette(const std::vector<size_t>& targets,
245 const std::array<uint8_t, 8>& permutation);
246 void HighlightTile(uint16_t sheet_id, uint16_t tile_index,
247 const std::string& label = "", double duration_secs = 3.0);
248
249 // Get the ROM pointer
250 Rom* rom() const { return rom_; }
251
252 private:
256 std::vector<uint16_t> sheet_ids; // sheets to write
257 std::map<uint16_t, std::string> refusals; // sheet -> reason
258 };
259 // Checks shared by Save and PlanGraphicsSave.
260 absl::StatusOr<PreparedGraphicsSave> PrepareGraphicsSave();
261 // Read-back check run on every written sheet. Tests replace it to force a
262 // mismatch and exercise the abort path.
263 std::function<absl::Status(const Rom&, uint16_t, const std::vector<uint8_t>&,
266
271
272 // Applies `edit` to the active project (the copy that is saved) and to this
273 // session's project snapshot, then marks the project dirty. Fails when no
274 // project file backs this ROM session.
275 absl::Status EditProject(
276 const std::function<void(project::YazeProject&)>& edit);
277
278 // --- Panel-Based Architecture ---
280 std::optional<std::set<uint16_t>> save_transaction_modified_sheets_;
281 std::unique_ptr<SheetBrowserPanel> sheet_browser_panel_;
282 std::unique_ptr<PixelEditorPanel> pixel_editor_panel_;
283 std::unique_ptr<PaletteControlsPanel> palette_controls_panel_;
284 std::unique_ptr<LinkSpritePanel> link_sprite_panel_;
285 std::unique_ptr<GfxGroupEditor> gfx_group_panel_;
288 std::unique_ptr<PalettesetEditorPanel> paletteset_panel_;
289 std::unique_ptr<PolyhedralEditorPanel> polyhedral_panel_;
290 std::unique_ptr<ImageImportView> image_import_view_;
293 std::unique_ptr<UsagePreviewView> usage_preview_view_;
294 std::unique_ptr<GraphicsScratchView> scratch_view_;
295
296 // --- Prototype Viewer (Super Donkey / Dev Format Imports) ---
297 void DrawPrototypeViewer();
298 absl::Status DrawCgxImport();
299 absl::Status DrawScrImport();
300 absl::Status DrawFileImport();
301 absl::Status DrawObjImport();
302 absl::Status DrawTilemapImport();
303 absl::Status DrawPaletteControls();
304 absl::Status DrawClipboardImport();
305 absl::Status DrawExperimentalFeatures();
306 absl::Status DrawMemoryEditor();
307 absl::Status DecompressImportData(int size);
308 absl::Status DecompressSuperDonkey();
309
310 // Prototype viewer state
312 uint64_t current_offset_ = 0;
317 uint64_t bin_size_ = 0;
318 uint64_t clipboard_offset_ = 0;
319 uint64_t clipboard_size_ = 0;
320 bool refresh_graphics_ = false;
322 bool gfx_loaded_ = false;
323 bool is_open_ = false;
324 bool super_donkey_ = false;
325 bool col_file_ = false;
326 bool cgx_loaded_ = false;
327 bool scr_loaded_ = false;
328 bool obj_loaded_ = false;
329 bool tilemap_loaded_ = false;
330
331 std::string file_path_;
332 std::string col_file_path_;
333 std::string col_file_name_;
334 std::string cgx_file_path_;
335 std::string cgx_file_name_;
336 std::string scr_file_path_;
337 std::string scr_file_name_;
338 std::string obj_file_path_;
341
344 std::vector<uint8_t> import_data_;
345 std::vector<uint8_t> decoded_cgx_;
346 std::vector<uint8_t> cgx_data_;
347 std::vector<uint8_t> extra_cgx_data_;
348 std::vector<SDL_Color> decoded_col_;
349 std::vector<uint8_t> scr_data_;
350 std::vector<uint8_t> decoded_scr_data_;
354 std::array<gfx::Bitmap, zelda3::kNumGfxSheets> gfx_sheets_;
361
362 // Last prototype import error (shown inside the Prototype Research panel).
364
365 // Status tracking
366 absl::Status status_;
367
368 // Core references
371};
372
373} // namespace editor
374} // namespace yaze
375
376#endif // YAZE_APP_EDITOR_GRAPHICS_EDITOR_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:52
Interface for editor classes.
Definition editor.h:252
EditorContext context() const
Definition editor.h:376
project::YazeProject * project() const
Definition editor.h:370
virtual void SetDependencies(const EditorDependencies &deps)
Definition editor.h:257
zelda3::GameData * game_data() const
Definition editor.h:369
EditorType type_
Definition editor.h:381
std::function< absl::StatusOr< zelda3::RoomsetUsageReport >(int)> RoomsetUsageCallback
std::function< absl::StatusOr< zelda3::MainGroupUsageReport >(int, int)> MainUsageCallback
Shared state between GraphicsEditor panel components.
bool HasUnsavedChanges() const
Check if any sheets have unsaved changes.
Allows the user to edit graphics sheets from the game or view prototype graphics.
usage_preview::LiveRoomProvider room_usage_provider_
friend class GraphicsEditorSaveStoplossTestPeer
std::vector< uint8_t > scr_data_
void SetRoomsetGraphicsUsageCallback(GfxGroupEditor::RoomsetUsageCallback callback)
absl::Status Save() override
GraphicsEditor(Rom *rom=nullptr)
void HighlightTile(uint16_t sheet_id, uint16_t tile_index, const std::string &label="", double duration_secs=3.0)
absl::Status ReorderSourcePalette(const std::vector< size_t > &targets, const std::array< uint8_t, 8 > &permutation)
GfxGroupEditor::RoomsetUsageCallback roomset_graphics_usage_
void SetPixelTool(PixelTool tool)
void RollbackSaveTransaction() override
gfx::PaletteGroup col_file_palette_group_
void SelectSheet(uint16_t sheet_id)
absl::Status Load() override
std::unique_ptr< GfxGroupEditor > gfx_group_panel_
std::unique_ptr< PaletteControlsPanel > palette_controls_panel_
std::vector< uint8_t > decoded_cgx_
EditorContextSnapshot BuildContextSnapshot() const override
absl::Status Copy() override
std::unique_ptr< GraphicsScratchView > scratch_view_
GfxGroupEditor::MainUsageCallback main_graphics_usage_
absl::Status EditProject(const std::function< void(project::YazeProject &)> &edit)
std::vector< uint8_t > cgx_data_
std::unique_ptr< PixelEditorPanel > pixel_editor_panel_
absl::Status Redo() override
std::unique_ptr< PolyhedralEditorPanel > polyhedral_panel_
std::unique_ptr< PalettesetEditorPanel > paletteset_panel_
std::function< absl::Status(const Rom &, uint16_t, const std::vector< uint8_t > &, const zelda3::GfxSheetPointerTables &) verify_written_sheet_)
absl::Status Cut() override
std::vector< uint8_t > import_data_
absl::Status Paste() override
absl::StatusOr< std::vector< GraphicsSavePlanEntry > > PlanGraphicsSave()
Graphics save preflight: every dirty sheet written to a scratch copy of the ROM (placement,...
std::vector< SDL_Color > decoded_col_
absl::Status BeginSaveTransaction() override
absl::Status Undo() override
absl::StatusOr< PreparedGraphicsSave > PrepareGraphicsSave()
absl::Status Update() override
absl::Status OpenInContext(GraphicsEditContext context)
void SetRoomUsageProvider(usage_preview::LiveRoomProvider provider)
void CommitSaveTransaction() override
absl::Status ImportScratchBin(const std::string &path, int bpp, size_t offset, const gfx::SnesPalette &palette={})
absl::Status Find() override
usage_preview::LiveOverworldProvider overworld_usage_provider_
std::vector< uint8_t > extra_cgx_data_
void SetScratchPreview(std::string label, ScratchPreviewCallback callback)
std::optional< std::set< uint16_t > > save_transaction_modified_sheets_
std::array< gfx::Bitmap, zelda3::kNumGfxSheets > gfx_sheets_
void SetDependencies(const EditorDependencies &deps) override
std::unique_ptr< ImageImportView > image_import_view_
std::vector< uint8_t > decoded_scr_data_
void SetOverworldUsageProvider(usage_preview::LiveOverworldProvider provider)
void SetGameData(zelda3::GameData *game_data) override
std::unique_ptr< LinkSpritePanel > link_sprite_panel_
void SetMainGraphicsUsageCallback(GfxGroupEditor::MainUsageCallback callback)
void PrepareForSessionTeardown() override
absl::Status DecompressImportData(int size)
void ContributeStatus(StatusBar *status_bar) override
std::unique_ptr< UsagePreviewView > usage_preview_view_
std::unique_ptr< SheetBrowserPanel > sheet_browser_panel_
A session-aware status bar displayed at the bottom of the application.
Definition status_bar.h:57
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
Modern, robust canvas for drawing and manipulating graphics.
Definition canvas.h:64
The Graphics editor's path for sheet pixel writes.
std::function< LiveRoomContexts()> LiveRoomProvider
std::function< zelda3::Overworld *()> LiveOverworldProvider
const std::string kSuperDonkeySprites[]
void AttachSheetStore(GraphicsEditorState &state, zelda3::GameData *game_data)
const std::string kSuperDonkeyTiles[]
absl::Status VerifyWrittenSheetPixels(const Rom &rom, uint16_t sheet_id, const std::vector< uint8_t > &expected_pixels, const zelda3::GfxSheetPointerTables &tables)
PixelTool
Pixel editing tool types for the graphics editor.
std::function< absl::StatusOr< usage_preview::PreviewImage >( const GraphicsScratchAsset &)> ScratchPreviewCallback
Unified dependency container for all editor types.
Definition editor.h:170
GfxGroupWorkspaceState * gfx_group_workspace
Definition editor.h:179
Represents a group of palettes.
Modern project structure with comprehensive settings consolidation.
Definition project.h:290
PC offsets of the bank, high and low byte pointer tables.
Rules a sheet write must follow.