yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_editor_v2_minecart.cc
Go to the documentation of this file.
2
5#include "util/macro.h"
6
7namespace yaze::editor {
8namespace {
9class CartStartAction final : public UndoAction {
10 public:
11 explicit CartStartAction(std::function<absl::Status(bool)> restore)
12 : restore_(std::move(restore)) {}
13 absl::Status Undo() override { return restore_(false); }
14 absl::Status Redo() override { return restore_(true); }
15 std::string Description() const override { return "Edit cart start"; }
16
17 private:
18 std::function<absl::Status(bool)> restore_;
19};
20} // namespace
21
23 const MinecartTrack& before, const MinecartTrack& after, bool move_cart) {
24 auto* panel = minecart_track_editor_panel_;
25 if (!panel)
26 return absl::FailedPreconditionError("Track document is unavailable");
27 if (before == after)
28 return absl::OkStatus();
30 const uint64_t generation = panel->track_generation();
31 std::optional<size_t> sprite_index;
32 std::optional<zelda3::Sprite> old_sprite, new_sprite;
33 if (move_cart) {
34 if (before.room_id != after.room_id || before.id != after.id)
35 return absl::InvalidArgumentError(
36 "Move a start within its existing room");
37 auto* room = rooms_.GetIfLoaded(before.room_id);
38 if (!room)
39 return absl::FailedPreconditionError("Load the start room first");
40 ASSIGN_OR_RETURN(const size_t index, FindCartStartSprite(*room, before));
42 sprite_index = index;
43 old_sprite = room->GetSprites()[index];
44 const auto local = *MinecartLocalPosition(after);
45 for (size_t other = 0; other < room->GetSprites().size(); ++other) {
46 const auto& sprite = room->GetSprites()[other];
47 if (other != index && !sprite.deleted() && sprite.id() == 0xA3 &&
48 sprite.layer() == 0 && sprite.x() * 16 == local.first &&
49 sprite.y() * 16 == local.second)
50 return absl::FailedPreconditionError("Another cart occupies this stop");
51 }
52 new_sprite.emplace(old_sprite->id(), local.first / 16, local.second / 16,
53 old_sprite->subtype(), old_sprite->layer());
54 new_sprite->set_key_drop(old_sprite->key_drop());
55 new_sprite->set_deleted(old_sprite->deleted());
56 auto candidates = room->GetSprites();
57 candidates[index] = *new_sprite;
59 }
60 auto restore = [this, generation, before, after, sprite_index, old_sprite,
61 new_sprite](bool forward) -> absl::Status {
62 auto* current_panel = minecart_track_editor_panel_;
63 if (!current_panel)
64 return absl::FailedPreconditionError("Track document closed");
65 const auto& expected = forward ? before : after;
66 const auto& replacement = forward ? after : before;
67 zelda3::Room* room = nullptr;
68 if (sprite_index) {
69 room = rooms_.GetIfLoaded(before.room_id);
70 if (!room || *sprite_index >= room->GetSprites().size())
71 return absl::FailedPreconditionError(
72 "The paired cart is no longer loaded");
73 const auto& current = room->GetSprites()[*sprite_index];
74 const auto& wanted = forward ? *old_sprite : *new_sprite;
75 if (current.id() != wanted.id() || current.x() != wanted.x() ||
76 current.y() != wanted.y() || current.subtype() != wanted.subtype() ||
77 current.layer() != wanted.layer() ||
78 current.deleted() != wanted.deleted() ||
79 current.key_drop() != wanted.key_drop())
80 return absl::FailedPreconditionError(
81 "The paired cart changed; repeat the edit");
82 }
84 current_panel->RestoreTrackDraft(generation, expected, replacement));
85 if (room) {
86 room->GetSprites()[*sprite_index] = forward ? *new_sprite : *old_sprite;
87 room->MarkSpritesDirty();
88 current_panel->MarkPairedTrackDraft();
89 if (rom_)
90 rom_->set_dirty(true);
91 }
92 return absl::OkStatus();
93 };
94 RETURN_IF_ERROR(restore(true));
95 undo_manager_.Push(std::make_unique<CartStartAction>(std::move(restore)));
96 return absl::OkStatus();
97}
98} // namespace yaze::editor
void set_dirty(bool dirty)
Definition rom.h:189
class MinecartTrackEditorPanel * minecart_track_editor_panel_
absl::Status PreflightSpriteMutation(int room_id, const std::vector< zelda3::Sprite > &sprites)
absl::Status ApplyMinecartTrackEdit(const MinecartTrack &before, const MinecartTrack &after, bool move_cart)
zelda3::Room * GetIfLoaded(int room_id)
UndoManager undo_manager_
Definition editor.h:371
Abstract base for all undoable actions (Command pattern)
Definition undo_action.h:20
void Push(std::unique_ptr< UndoAction > action)
std::string Description() const override
Human-readable description (e.g., "Paint 12 tiles on map 5")
void MarkSpritesDirty()
Definition room.h:319
const std::vector< zelda3::Sprite > & GetSprites() const
Definition room.h:316
#define ASSIGN_OR_RETURN(type_variable_name, expression)
Definition macro.h:62
Editors are the view controllers for the application.
std::optional< std::pair< int, int > > MinecartLocalPosition(const MinecartTrack &track)
absl::StatusOr< size_t > FindCartStartSprite(const zelda3::Room &room, const MinecartTrack &start)
absl::Status ValidateCartStartDestination(const zelda3::Room &room, const MinecartTrack &start)
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22