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"
26#include "app/gfx/core/bitmap.h"
29#include "rom/rom.h"
30#include "zelda3/game_data.h"
31
32namespace yaze {
33namespace editor {
34
35class GraphicsEditorSaveStoplossTestPeer;
36
37// Super Donkey prototype graphics offsets (from leaked dev materials)
38const std::string kSuperDonkeyTiles[] = {
39 "97C05", "98219", "9871E", "98C00", "99084", "995AF", "99DE0", "9A27E",
40 "9A741", "9AC31", "9B07E", "9B55C", "9B963", "9BB99", "9C009", "9C4B4",
41 "9C92B", "9CDD6", "9D2C2", "9E037", "9E527", "9EA56", "9EF65", "9FCD1",
42 "A0193", "A059E", "A0B17", "A0FB6", "A14A5", "A1988", "A1E66", "A232B",
43 "A27F0", "A2B6E", "A302C", "A3453", "A38CA", "A42BB", "A470C", "A4BA9",
44 "A5089", "A5385", "A5742", "A5BCC", "A6017", "A6361", "A66F8"};
45
46const std::string kSuperDonkeySprites[] = {
47 "A8E5D", "A9435", "A9934", "A9D83", "AA2F1", "AA6D4", "AABE4", "AB127",
48 "AB65A", "ABBDD", "AC38D", "AC797", "ACCC8", "AD0AE", "AD245", "AD554",
49 "ADAAC", "ADECC", "AE453", "AE9D2", "AEF40", "AF3C9", "AF92E", "AFE9D",
50 "B03D2", "B09AC", "B0F0C", "B1430", "B1859", "B1E01", "B229A", "B2854",
51 "B2D27", "B31D7", "B3B58", "B40B5", "B45A5", "B4D64", "B5031", "B555F",
52 "B5F30", "B6858", "B70DD", "B7526", "B79EC", "B7C83", "B80F7", "B85CC",
53 "B8A3F", "B8F97", "B94F2", "B9A20", "B9E9A", "BA3A2", "BA8F6", "BACDC",
54 "BB1F9", "BB781", "BBCCA", "BC26D", "BC7D4", "BCBB0", "BD082", "BD5FC",
55 "BE115", "BE5C2", "BEB63", "BF0CB", "BF607", "BFA55", "BFD71", "C017D",
56 "C0567", "C0981", "C0BA7", "C116D", "C166A", "C1FE0", "C24CE", "C2B19"};
57
72class GraphicsEditor : public Editor {
73 public:
74 explicit GraphicsEditor(Rom* rom = nullptr) : rom_(rom) {
76 }
77
78 void SetDependencies(const EditorDependencies& deps) override {
80 if (gfx_group_panel_) {
81 gfx_group_panel_->SetWorkspaceState(deps.gfx_group_workspace);
82 }
83 }
84
87 main_graphics_usage_ = std::move(callback);
89 gfx_group_panel_->SetMainUsageCallback(main_graphics_usage_);
90 }
98 room_usage_provider_ = std::move(provider);
100 usage_preview_view_->SetLiveRoomProvider(room_usage_provider_);
101 }
104 gfx_group_panel_->DetachRuntimeContext();
108 }
109 void Initialize() override;
110 absl::Status Load() override;
111 absl::Status Save() override;
112 absl::Status Update() override;
113 // Cut, Copy and Paste use the system clipboard as PNG (pixel editor).
119 absl::StatusOr<std::vector<GraphicsSavePlanEntry>> PlanGraphicsSave();
120
121 absl::Status Cut() override;
122 absl::Status Copy() override;
123 absl::Status Paste() override;
124 absl::Status Undo() override;
125 absl::Status Redo() override;
126 absl::Status Find() override { return absl::UnimplementedError("Find"); }
127 void ContributeStatus(StatusBar* status_bar) override;
129
132 (pixel_editor_panel_ && pixel_editor_panel_->HasActiveStroke());
133 }
134
135 // Coordinated ROM save: Save() clears the modified-sheet set, so a failed
136 // save elsewhere must put it back (the ROM bytes are restored separately).
137 absl::Status BeginSaveTransaction() override {
138 // A floating paste has visible pixels but no committed sheet diff. Do not
139 // report it saved or choose its placement on the user's behalf.
141 return absl::FailedPreconditionError(
142 "Commit or cancel the floating paste in Graphics before saving "
143 "(Enter to commit, Esc to cancel)");
145 pixel_editor_panel_->FinishReleasedGesture();
146 if (pixel_editor_panel_->HasActiveStroke())
147 return absl::FailedPreconditionError(
148 "Finish the pixel stroke before saving");
149 }
151 return absl::OkStatus();
152 }
159 void CommitSaveTransaction() override {
161 }
162
163 // Set the ROM pointer (propagates to panels that cache `Rom*`.)
164 void set_rom(Rom* rom) {
165 if (rom_ != rom) {
167 state_.preview_palettes.clear();
168 }
169 rom_ = rom;
171 sheet_browser_panel_->SetDataSources(
173 [this]() -> const project::YazeProject* { return project(); });
174 }
176 pixel_editor_panel_->SetRom(rom);
177 }
178 if (link_sprite_panel_) {
179 link_sprite_panel_->SetRom(rom);
180 }
181 if (gfx_group_panel_) {
182 gfx_group_panel_->SetRom(rom);
183 }
184 if (paletteset_panel_) {
185 paletteset_panel_->SetRom(rom);
186 }
187 if (polyhedral_panel_) {
188 polyhedral_panel_->SetRom(rom);
189 }
191 usage_preview_view_->SetRom(rom);
192 }
193 }
194
195 // Set the game data pointer
200 sheet_browser_panel_->SetDataSources(
202 [this]() -> const project::YazeProject* { return project(); });
203 }
204 if (gfx_group_panel_) {
205 gfx_group_panel_->SetGameData(game_data);
206 }
207 if (paletteset_panel_) {
208 paletteset_panel_->SetGameData(game_data);
209 }
211 usage_preview_view_->SetGameData(game_data);
212 }
213 }
214
215 // Editor shortcuts
216 void NextSheet();
217 // Keyboard shortcut targets (shortcut_configurator.cc).
218 void SetPixelTool(PixelTool tool);
219 void ZoomIn();
220 void ZoomOut();
221 void ToggleGrid();
222 void PrevSheet();
223 void SelectSheet(uint16_t sheet_id);
224 void FinishPixelGesture();
225 // Opens only Pixel Editor and Usage Preview, retaining the source editor's
226 // resolved colors and live preview for this ROM session.
228 // Callable command only; the existing controls own its future UI entry point.
229 absl::Status ReorderSourcePalette(const std::vector<size_t>& targets,
230 const std::array<uint8_t, 8>& permutation);
231 void HighlightTile(uint16_t sheet_id, uint16_t tile_index,
232 const std::string& label = "", double duration_secs = 3.0);
233
234 // Get the ROM pointer
235 Rom* rom() const { return rom_; }
236
237 private:
241 std::vector<uint16_t> sheet_ids; // sheets to write
242 std::map<uint16_t, std::string> refusals; // sheet -> reason
243 };
244 // Checks shared by Save and PlanGraphicsSave.
245 absl::StatusOr<PreparedGraphicsSave> PrepareGraphicsSave();
246 // Read-back check run on every written sheet. Tests replace it to force a
247 // mismatch and exercise the abort path.
248 std::function<absl::Status(const Rom&, uint16_t, const std::vector<uint8_t>&,
251
254
255 // Applies `edit` to the active project (the copy that is saved) and to this
256 // session's project snapshot, then marks the project dirty. Fails when no
257 // project file backs this ROM session.
258 absl::Status EditProject(
259 const std::function<void(project::YazeProject&)>& edit);
260
261 // --- Panel-Based Architecture ---
263 std::optional<std::set<uint16_t>> save_transaction_modified_sheets_;
264 std::unique_ptr<SheetBrowserPanel> sheet_browser_panel_;
265 std::unique_ptr<PixelEditorPanel> pixel_editor_panel_;
266 std::unique_ptr<PaletteControlsPanel> palette_controls_panel_;
267 std::unique_ptr<LinkSpritePanel> link_sprite_panel_;
268 std::unique_ptr<GfxGroupEditor> gfx_group_panel_;
271 std::unique_ptr<PalettesetEditorPanel> paletteset_panel_;
272 std::unique_ptr<PolyhedralEditorPanel> polyhedral_panel_;
274 std::unique_ptr<UsagePreviewView> usage_preview_view_;
275
276 // --- Prototype Viewer (Super Donkey / Dev Format Imports) ---
277 void DrawPrototypeViewer();
278 absl::Status DrawCgxImport();
279 absl::Status DrawScrImport();
280 absl::Status DrawFileImport();
281 absl::Status DrawObjImport();
282 absl::Status DrawTilemapImport();
283 absl::Status DrawPaletteControls();
284 absl::Status DrawClipboardImport();
285 absl::Status DrawExperimentalFeatures();
286 absl::Status DrawMemoryEditor();
287 absl::Status DecompressImportData(int size);
288 absl::Status DecompressSuperDonkey();
289
290 // Prototype viewer state
292 uint64_t current_offset_ = 0;
297 uint64_t bin_size_ = 0;
298 uint64_t clipboard_offset_ = 0;
299 uint64_t clipboard_size_ = 0;
300 bool refresh_graphics_ = false;
302 bool gfx_loaded_ = false;
303 bool is_open_ = false;
304 bool super_donkey_ = false;
305 bool col_file_ = false;
306 bool cgx_loaded_ = false;
307 bool scr_loaded_ = false;
308 bool obj_loaded_ = false;
309 bool tilemap_loaded_ = false;
310
311 std::string file_path_;
312 std::string col_file_path_;
313 std::string col_file_name_;
314 std::string cgx_file_path_;
315 std::string cgx_file_name_;
316 std::string scr_file_path_;
317 std::string scr_file_name_;
318 std::string obj_file_path_;
321
324 std::vector<uint8_t> import_data_;
325 std::vector<uint8_t> decoded_cgx_;
326 std::vector<uint8_t> cgx_data_;
327 std::vector<uint8_t> extra_cgx_data_;
328 std::vector<SDL_Color> decoded_col_;
329 std::vector<uint8_t> scr_data_;
330 std::vector<uint8_t> decoded_scr_data_;
334 std::array<gfx::Bitmap, zelda3::kNumGfxSheets> gfx_sheets_;
341
342 // Last prototype import error (shown inside the Prototype Research panel).
344
345 // Status tracking
346 absl::Status status_;
347
348 // Core references
351};
352
353} // namespace editor
354} // namespace yaze
355
356#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:49
Interface for editor classes.
Definition editor.h:249
EditorContext context() const
Definition editor.h:364
project::YazeProject * project() const
Definition editor.h:358
virtual void SetDependencies(const EditorDependencies &deps)
Definition editor.h:254
zelda3::GameData * game_data() const
Definition editor.h:357
EditorType type_
Definition editor.h:369
std::function< absl::StatusOr< zelda3::RoomsetUsageReport >(int)> RoomsetUsageCallback
std::function< absl::StatusOr< zelda3::MainGroupUsageReport >(int, int)> MainUsageCallback
Shared state between GraphicsEditor panel components.
std::map< uint16_t, GraphicsPaletteSelection > preview_palettes
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
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 Find() override
std::vector< uint8_t > extra_cgx_data_
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::vector< uint8_t > decoded_scr_data_
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
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.
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:287
PC offsets of the bank, high and low byte pointer tables.
Rules a sheet write must follow.