14#include "absl/status/status.h"
15#include "absl/strings/str_format.h"
16#include "absl/types/span.h"
60#include "imgui/imgui.h"
92 viewer->TriggerChangePing();
97 description.empty() ?
"Undid last dungeon edit"
98 : absl::StrFormat(
"Undid: %s", description),
123 viewer->TriggerChangePing();
128 description.empty() ?
"Redid last dungeon edit"
129 : absl::StrFormat(
"Redid: %s", description),
139 viewer->object_interaction().HandleCopySelected();
140 viewer->object_interaction().HandleDeleteSelected();
142 return absl::OkStatus();
147 viewer->object_interaction().HandleCopySelected();
149 return absl::OkStatus();
154 viewer->object_interaction().HandlePasteObjects();
156 return absl::OkStatus();
160 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
166 "BeginUndoSnapshot called twice without FinalizeUndoAction. "
167 "Previous snapshot for room %d is being leaked. Finalizing now.",
182 viewer->object_interaction().GetSelectedObjectIndices();
190 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
193 auto after_objects =
rooms_[room_id].GetTileObjects();
194 std::vector<size_t> after_selection;
198 after_selection = viewer->object_interaction().GetSelectedObjectIndices();
201 auto action = std::make_unique<DungeonObjectsAction>(
204 std::move(after_selection),
205 [
this](
int rid,
const std::vector<zelda3::RoomObject>& objects,
206 const std::vector<size_t>& selected_indices) {
207 RestoreRoomObjects(rid, objects, selected_indices);
218 int room_id,
const std::vector<zelda3::RoomObject>& objects,
219 const std::vector<size_t>& selected_indices) {
220 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
223 auto& room =
rooms_[room_id];
224 const auto previous_objects = room.GetTileObjects();
225 room.SetTileObjects(objects);
226 room.RenderRoomGraphics();
228 std::vector<size_t> valid_selection;
229 for (
size_t index : selected_indices) {
230 if (index < objects.size()) {
231 valid_selection.push_back(index);
235 viewer->object_interaction().SetSelectedObjects(valid_selection);
237 viewer->TriggerObjectChangePing(previous_objects, objects);
243 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
259 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
262 auto after =
rooms_[room_id].custom_collision();
270 auto action = std::make_unique<DungeonCustomCollisionAction>(
273 RestoreRoomCustomCollision(rid, map);
283 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
286 auto& room =
rooms_[room_id];
287 room.custom_collision() = map;
288 room.MarkCustomCollisionDirty();
299 for (
size_t i = 0; i < zone.tiles.size(); ++i) {
300 if (zone.tiles[i] != 0) {
301 snap.
offsets.push_back(
static_cast<uint16_t
>(i));
310 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
326 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
329 auto after = MakeWaterFillSnapshot(
rooms_[room_id]);
337 auto action = std::make_unique<DungeonWaterFillAction>(
340 RestoreRoomWaterFill(rid, snap);
350 if (room_id < 0 || room_id >=
static_cast<int>(
rooms_.
size()))
353 auto& room =
rooms_[room_id];
354 room.ClearWaterFillZone();
356 for (uint16_t off : snap.
offsets) {
357 const int x =
static_cast<int>(off % 64);
358 const int y =
static_cast<int>(off / 64);
359 room.SetWaterFillTile(x, y,
true);
361 room.MarkWaterFillDirty();
void BeginCollisionUndoSnapshot(int room_id)
void RestoreRoomWaterFill(int room_id, const WaterFillSnapshot &snap)
PendingUndo pending_undo_
void FinalizeWaterFillUndoAction(int room_id)
absl::Status Copy() override
void RestoreRoomObjects(int room_id, const std::vector< zelda3::RoomObject > &objects, const std::vector< size_t > &selected_indices)
bool IsWorkbenchWorkflowEnabled() const
PendingCollisionUndo pending_collision_undo_
PendingWaterFillUndo pending_water_fill_undo_
absl::Status Cut() override
absl::Status Paste() override
void FinalizeUndoAction(int room_id)
DungeonCanvasViewer * GetViewerForRoom(int room_id)
void BeginWaterFillUndoSnapshot(int room_id)
absl::Status Undo() override
absl::Status Redo() override
void BeginUndoSnapshot(int room_id)
void RestoreRoomCustomCollision(int room_id, const zelda3::CustomCollisionMap &map)
bool undo_restore_triggered_ping_
void FinalizeCollisionUndoAction(int room_id)
UndoManager undo_manager_
EditorDependencies dependencies_
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
void Push(std::unique_ptr< UndoAction > action)
absl::Status Redo()
Redo the top action. Returns error if stack is empty.
std::string GetRedoDescription() const
Description of the action that would be redone (for UI)
std::string GetUndoDescription() const
Description of the action that would be undone (for UI)
absl::Status Undo()
Undo the top action. Returns error if stack is empty.
const WaterFillZoneMap & water_fill_zone() const
uint8_t water_fill_sram_bit_mask() const
#define LOG_ERROR(category, format,...)
WaterFillSnapshot MakeWaterFillSnapshot(const zelda3::Room &room)
Editors are the view controllers for the application.
zelda3::CustomCollisionMap before
std::vector< size_t > before_selection
std::vector< zelda3::RoomObject > before_objects
ToastManager * toast_manager
std::vector< uint16_t > offsets
std::array< uint8_t, 64 *64 > tiles