1#ifndef YAZE_APP_EDITOR_OVERWORLD_UNDO_ACTIONS_H_
2#define YAZE_APP_EDITOR_OVERWORLD_UNDO_ACTIONS_H_
9#include <unordered_map>
13#include "absl/status/status.h"
14#include "absl/strings/str_format.h"
58 std::function<
void()> refresh_fn)
64 timestamp_(std::chrono::steady_clock::now()) {}
66 absl::Status
Undo()
override {
68 return absl::InternalError(
"Overworld pointer is null");
72 world_tiles[change.x][change.y] = change.old_tile_id;
77 return absl::OkStatus();
80 absl::Status
Redo()
override {
82 return absl::InternalError(
"Overworld pointer is null");
86 world_tiles[change.x][change.y] = change.new_tile_id;
91 return absl::OkStatus();
95 return absl::StrFormat(
"Paint %d tile%s on map %d",
tile_changes_.size(),
104 const auto* prev_paint =
108 if (prev_paint->map_id_ !=
map_id_)
110 if (prev_paint->world_ !=
world_)
113 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
124 std::unordered_map<int64_t, size_t> coord_index;
126 int64_t key = (
static_cast<int64_t
>(
tile_changes_[i].x) << 32) |
128 coord_index[key] = i;
131 for (
const auto& prev_change : prev_paint.tile_changes_) {
132 int64_t key = (
static_cast<int64_t
>(prev_change.x) << 32) |
133 static_cast<int64_t
>(prev_change.y);
134 auto it = coord_index.find(key);
135 if (it != coord_index.end()) {
137 tile_changes_[it->second].old_tile_id = prev_change.old_tile_id;
170 std::vector<zelda3::OverworldItem>
items;
186 std::string description)
194 return absl::InternalError(
195 "OverworldItemsEditAction: no restore callback");
198 return absl::OkStatus();
203 return absl::InternalError(
204 "OverworldItemsEditAction: no restore callback");
207 return absl::OkStatus();
213 const size_t before_size =
215 const size_t after_size =
217 return sizeof(*this) + before_size + after_size;
Undoable action for overworld item mutations.
bool CanMergeWith(const UndoAction &) const override
std::string Description() const override
Human-readable description (e.g., "Paint 12 tiles on map 5")
OverworldItemsEditAction(OverworldItemsSnapshot before, OverworldItemsSnapshot after, RestoreFn restore, std::string description)
absl::Status Redo() override
absl::Status Undo() override
std::function< void(const OverworldItemsSnapshot &)> RestoreFn
OverworldItemsSnapshot before_
OverworldItemsSnapshot after_
size_t MemoryUsage() const override
Approximate memory footprint for budget enforcement.
Undoable action for painting tiles on the overworld map.
std::function< void()> refresh_fn_
size_t MemoryUsage() const override
Approximate memory footprint for budget enforcement.
void MergeWith(UndoAction &prev) override
bool CanMergeWith(const UndoAction &prev) const override
static constexpr int kMergeWindowMs
Merge window: consecutive paints within this duration become one step.
OverworldTilePaintAction(int map_id, int world, std::vector< OverworldTileChange > tile_changes, zelda3::Overworld *overworld, std::function< void()> refresh_fn)
std::string Description() const override
Human-readable description (e.g., "Paint 12 tiles on map 5")
std::vector< OverworldTileChange > tile_changes_
const std::vector< OverworldTileChange > & tile_changes() const
absl::Status Redo() override
zelda3::Overworld * overworld_
std::chrono::steady_clock::time_point timestamp_
absl::Status Undo() override
Abstract base for all undoable actions (Command pattern)
Represents the full Overworld data, light and dark world.
OverworldBlockset & GetMapTiles(int world_type)
Snapshot of overworld item list + current item selection.
std::vector< zelda3::OverworldItem > items
std::optional< zelda3::OverworldItem > selected_item_identity
A single tile coordinate + old/new value pair for undo/redo.