yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
tile16_edit_history.cc
Go to the documentation of this file.
2
5#include "util/macro.h"
8
9namespace yaze::editor {
10namespace {
11bool SameDefinition(const gfx::Tile16& a, const gfx::Tile16& b) {
12 for (int q = 0; q < 4; ++q) {
15 return false;
16 }
17 }
18 return true;
19}
20
22 public:
23 using Apply = std::function<absl::Status(const std::vector<Tile16Commit>&)>;
24 Tile16DefinitionEditAction(std::vector<Tile16Commit> before,
25 std::vector<Tile16Commit> after, Apply apply)
26 : before_(std::move(before)),
27 after_(std::move(after)),
28 apply_(std::move(apply)) {}
29 absl::Status Undo() override { return apply_(before_); }
30 absl::Status Redo() override { return apply_(after_); }
31 std::string Description() const override {
32 return before_.size() == 1 ? "Edit Tile16 definition" : "Edit Tile16 stamp";
33 }
34 size_t MemoryUsage() const override {
35 return (before_.size() + after_.size()) * sizeof(Tile16Commit);
36 }
37
38 private:
39 std::vector<Tile16Commit> before_, after_;
41};
42} // namespace
43
44absl::StatusOr<gfx::Tile16> Tile16EditSession::ReadDocumentTile(int id) const {
46 if (id < 0 || id >= static_cast<int>(document_definitions_->size())) {
47 return absl::OutOfRangeError("Tile16 is outside the document");
48 }
49 return (*document_definitions_)[id];
50 }
51 const auto it = document_edits_.find(id);
52 if (it != document_edits_.end())
53 return it->second;
54 if (!rom_)
55 return absl::FailedPreconditionError("No Tile16 document");
57}
58
60 const std::vector<Tile16Commit>& definitions) {
61 // Validate and render the complete batch before publishing any definition.
62 // History stores metadata, not pixels tied to the map's graphics/palette.
63 std::vector<gfx::Bitmap> bitmaps(definitions.size());
64 for (size_t i = 0; i < definitions.size(); ++i) {
65 const auto& edit = definitions[i];
66 if (edit.tile_id < 0 || edit.tile_id >= zelda3::kNumTile16Individual ||
68 edit.tile_id >= static_cast<int>(document_definitions_->size()))) {
69 return absl::OutOfRangeError("Tile16 edit is outside the document");
70 }
71 RETURN_IF_ERROR(BuildTile16BitmapFromData(edit.tile_data, &bitmaps[i]));
72 bitmaps[i].SetPalette(current_tile16_bmp_.palette());
73 }
74 for (size_t i = 0; i < definitions.size(); ++i) {
75 const auto& edit = definitions[i];
76 document_edits_[edit.tile_id] = edit.tile_data;
77 edited_tile_bitmaps_[edit.tile_id] = bitmaps[i];
79 (*document_definitions_)[edit.tile_id] = edit.tile_data;
80 }
81 CopyTileBitmapToBlockset(edit.tile_id, bitmaps[i]);
82 }
84 preview_dirty_ = true;
87 on_document_changed_(definitions);
88 if (rom_)
89 rom_->set_dirty(true);
93 }
97 }
98 return absl::OkStatus();
99}
100
102 const std::function<absl::Status()>& operation) {
103 // A map stroke must enter history before the following definition edit.
104 if (before_edit_)
105 before_edit_();
106 const auto previous = document_edits_;
107 const auto old_current = current_tile16_data_;
108 const auto result = operation();
109 const auto proposed = document_edits_;
110 document_edits_ = previous;
111 current_tile16_data_ = old_current;
112
113 std::vector<Tile16Commit> before, after;
114 for (const auto& [id, data] : proposed) {
115 auto original = ReadDocumentTile(id);
116 if (!original.ok()) {
118 return original.status();
119 }
120 if (!SameDefinition(*original, data)) {
121 before.push_back({id, *original});
122 after.push_back({id, data});
123 }
124 }
125 if (!result.ok()) {
126 // Restore derived previews changed by a failed render/stamp operation.
127 for (const auto& edit : before) {
128 gfx::Bitmap bitmap;
129 if (BuildTile16BitmapFromData(edit.tile_data, &bitmap).ok()) {
130 CopyTileBitmapToBlockset(edit.tile_id, bitmap);
131 }
132 }
134 return result;
135 }
136 if (after.empty())
138 const auto applied = ApplyDefinitions(after);
139 if (!applied.ok()) {
140 (void)ApplyDefinitions(before);
141 document_edits_ = previous;
142 return applied;
143 }
144 history_->Push(std::make_unique<Tile16DefinitionEditAction>(
145 std::move(before), std::move(after),
146 [this](const std::vector<Tile16Commit>& edits) {
147 return ApplyDefinitions(edits);
148 }));
149 return absl::OkStatus();
150}
151
153 return RunEdit([&]() {
158 return absl::OkStatus();
159 });
160}
161} // namespace yaze::editor
absl::StatusOr< gfx::Tile16 > ReadTile16(uint32_t tile16_id, uint32_t tile16_ptr)
Definition rom.cc:821
void set_dirty(bool dirty)
Definition rom.h:189
absl::Status ApplyDefinitions(const std::vector< Tile16Commit > &definitions)
absl::Status RunEdit(const std::function< absl::Status()> &operation)
absl::StatusOr< gfx::Tile16 > ReadDocumentTile(int id) const
void CopyTileBitmapToBlockset(int tile_id, const gfx::Bitmap &tile_bitmap)
std::map< int, gfx::Bitmap > edited_tile_bitmaps_
absl::Status ReplaceCurrentTile(const gfx::Tile16 &data)
std::map< int, gfx::Tile16 > document_edits_
absl::Status BuildTile16BitmapFromData(const gfx::Tile16 &tile_data, gfx::Bitmap *output_bitmap) const
std::function< void(const std::vector< Tile16Commit > &) on_document_changed_)
std::vector< gfx::Tile16 > * document_definitions_
Abstract base for all undoable actions (Command pattern)
Definition undo_action.h:20
void Push(std::unique_ptr< UndoAction > action)
Tile16DefinitionEditAction(std::vector< Tile16Commit > before, std::vector< Tile16Commit > after, Apply apply)
size_t MemoryUsage() const override
Approximate memory footprint for budget enforcement.
std::function< absl::Status(const std::vector< Tile16Commit > &)> Apply
std::string Description() const override
Human-readable description (e.g., "Paint 12 tiles on map 5")
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Definition arena.cc:39
static Arena & Get()
Definition arena.cc:24
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:70
const SnesPalette & palette() const
Definition bitmap.h:393
bool is_active() const
Definition bitmap.h:414
Tile composition of four 8x8 tiles.
Definition snes_tile.h:142
bool SameDefinition(const gfx::Tile16 &a, const gfx::Tile16 &b)
Editors are the view controllers for the application.
uint16_t TileInfoToShort(TileInfo tile_info)
Definition snes_tile.cc:394
void SyncTile16TilesInfo(gfx::Tile16 *tile)
constexpr int kNumTile16Individual
Definition overworld.h:243
constexpr uint32_t kTile16Ptr
Definition game_data.h:61
const gfx::TileInfo & Tile16QuadrantInfo(const gfx::Tile16 &tile, int quadrant)
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22
Bitmap atlas
Master bitmap containing all tiles.
Definition tilemap.h:119