5#define IM_PI 3.14159265358979323846f
22#include <unordered_map>
27#include "absl/status/status.h"
28#include "absl/strings/str_format.h"
29#include "imgui/imgui.h"
103 for (
size_t i = 0; i < lhs.
items.size(); ++i) {
128 "Gfx Groups: selection syncs with the Graphics editor for this ROM "
130 "(this surface uses its own preview canvases).");
139 std::make_unique<EntityMutationService>(
overworld_);
173 toolbar_ = std::make_unique<OverworldToolbar>();
174 toolbar_->on_refresh_graphics = [
this]() {
180 toolbar_->on_refresh_map = [
this]() {
184 toolbar_->on_save_to_scratch = [
this]() {
187 toolbar_->on_load_from_scratch = [
this]() {
190 toolbar_->on_upgrade_rom_version = [
this](int) {
191 ImGui::OpenPopup(
"UpgradeROMVersion");
230 const int step = shift_held ? 16 : 1;
237 "overworld.entity_workbench"));
247 switch (entity->entity_type_) {
264 const size_t session_id =
279 const size_t session_id =
294 std::make_unique<OverworldInteractionCoordinator>(std::move(sink));
334 tile_painting_ = std::make_unique<TilePaintingManager>(deps, callbacks);
371 canvas_nav_ = std::make_unique<CanvasNavigationManager>();
397 LOG_DEBUG(
"OverworldEditor",
"Loading overworld.");
399 return absl::FailedPreconditionError(
"ROM not loaded");
431 "Overworld editor refreshed after Tile16 changes");
432 return absl::OkStatus();
438 [
this](
const std::string& entity_type) {
452 [
this](
const std::string& group_name,
int palette_index) {
454 if (group_name ==
"ow_main" || group_name ==
"ow_animated" ||
455 group_name ==
"ow_aux" || group_name ==
"grass") {
457 "Palette change detected: %s, refreshing current map",
465 LOG_DEBUG(
"OverworldEditor",
"Registered as palette listener (ID: %d)",
477 return absl::OkStatus();
486 return absl::OkStatus();
491 return absl::OkStatus();
527 ImGui::SetNextWindowSize(ImVec2(400, 500), ImGuiCond_FirstUseEver);
541 ImGui::SetNextWindowSize(ImVec2(500, 450), ImGuiCond_FirstUseEver);
542 if (ImGui::Begin(
ICON_MD_LAYERS " Visual Effects Editor###OverlayEditor",
559 workbench->DrawPopups();
562 if (ImGui::BeginPopupModal(
"UpgradeROMVersion",
nullptr,
563 ImGuiWindowFlags_AlwaysAutoResize)) {
567 "This will apply the ZSCustomOverworld ASM patch to your ROM,\n"
568 "enabling advanced overworld features.");
571 const uint8_t current_version =
574 ImGui::Text(
"Current Version: %s",
575 current_version == 0xFF
577 : absl::StrFormat(
"v%d", current_version).c_str());
579 static int target_version = 3;
580 ImGui::RadioButton(
"v2 (Basic features)", &target_version, 2);
582 ImGui::RadioButton(
"v3 (All features)", &target_version, 3);
586 if (ImGui::Button(
ICON_MD_CHECK " Apply Upgrade", ImVec2(150.0f, 0.0f))) {
587 auto upgrade_status =
590 : absl::FailedPreconditionError(
"Upgrade system not initialized");
591 if (upgrade_status.ok()) {
597 ImGui::CloseCurrentPopup();
600 LOG_ERROR(
"OverworldEditor",
"Upgrade failed: %s",
601 upgrade_status.message().data());
605 if (ImGui::Button(
ICON_MD_CANCEL " Cancel", ImVec2(150.0f, 0.0f))) {
606 ImGui::CloseCurrentPopup();
621 return absl::OkStatus();
642 "overworld.entity_workbench"));
656 "overworld.entity_workbench"));
668 "overworld.entity_workbench"));
684 workbench->SetActiveEntity(item);
707 *items = snapshot.
items;
710 auto* selected_item =
715 workbench->SetActiveEntity(selected_item);
731 std::string description) {
733 if (ItemSnapshotsEqual(before, after)) {
738 std::move(before), std::move(after),
742 std::move(description)));
747 if (!selected_item) {
750 "Select an overworld item first (Item Mode: key 5)",
760 *selected_item, offset_x, offset_y);
764 if (duplicate_or.ok()) {
765 duplicate_result.
entity = *duplicate_or;
766 duplicate_result.
status = absl::OkStatus();
768 duplicate_result.
status = duplicate_or.status();
770 "Failed to duplicate overworld item: " +
771 std::string(duplicate_or.status().message());
774 if (!duplicate_result.
ok()) {
778 ?
"Failed to duplicate overworld item"
785 auto* duplicated_item =
790 workbench->SetActiveEntity(duplicated_item);
793 absl::StrFormat(
"Duplicate overworld item 0x%02X",
794 static_cast<int>(duplicated_item->id_)));
798 absl::StrFormat(
"Duplicated item 0x%02X",
799 static_cast<int>(duplicated_item->id_)),
807 if (!selected_item) {
812 auto status =
NudgeItem(selected_item, delta_x, delta_y);
824 workbench->SetActiveEntity(selected_item);
827 std::move(before_snapshot),
828 absl::StrFormat(
"Move overworld item 0x%02X (%+d,%+d)",
829 static_cast<int>(selected_item->id_), delta_x, delta_y));
836 if (!selected_item) {
842 const uint8_t deleted_item_id = selected_identity.
id_;
843 absl::Status remove_status =
844 absl::FailedPreconditionError(
"Entity mutation service not initialized");
851 if (!remove_status.ok()) {
867 workbench->SetActiveEntity(nearest_item);
874 absl::StrFormat(
"Delete overworld item 0x%02X",
875 static_cast<int>(deleted_item_id)));
880 absl::StrFormat(
"Deleted item 0x%02X (selected nearest 0x%02X)",
881 static_cast<int>(deleted_item_id),
882 static_cast<int>(nearest_item->id_)),
886 absl::StrFormat(
"Deleted overworld item 0x%02X",
887 static_cast<int>(deleted_item_id)),
900 return absl::FailedPreconditionError(
"Clipboard unavailable");
905 std::vector<int> ids;
910 static_cast<int>(std::floor(std::min(start.x, end.x) / 16.0f));
912 static_cast<int>(std::floor(std::max(start.x, end.x) / 16.0f));
914 static_cast<int>(std::floor(std::min(start.y, end.y) / 16.0f));
916 static_cast<int>(std::floor(std::max(start.y, end.y) / 16.0f));
917 const int width = end_x - start_x + 1;
918 const int height = end_y - start_y + 1;
919 ids.reserve(width * height);
922 for (
int y = start_y; y <= end_y; ++y) {
923 for (
int x = start_x; x <= end_x; ++x) {
932 return absl::OkStatus();
940 return absl::OkStatus();
942 return absl::FailedPreconditionError(
"Nothing selected to copy");
947 return absl::FailedPreconditionError(
"Clipboard unavailable");
950 return absl::FailedPreconditionError(
"Clipboard empty");
954 return absl::FailedPreconditionError(
"No paste target");
963 const ImVec2 anchor =
964 ImVec2(scaled_anchor.x / scale, scaled_anchor.y / scale);
972 auto& selected_world =
979 const int superY = local_map / 8;
980 const int superX = local_map % 8;
987 if (width * height !=
static_cast<int>(ids.size())) {
988 return absl::InternalError(
"Clipboard dimensions mismatch");
991 bool any_changed =
false;
992 for (
int dy = 0; dy < height; ++dy) {
993 for (
int dx = 0; dx < width; ++dx) {
994 const int id = ids[dy * width + dx];
995 const int gx = tile16_x + dx;
996 const int gy = tile16_y + dy;
998 const int global_x = superX * 32 + gx;
999 const int global_y = superY * 32 + gy;
1000 if (global_x < 0 || global_x >= 256 || global_y < 0 || global_y >= 256)
1002 const int old_tile_id = selected_world[global_x][global_y];
1003 if (old_tile_id ==
id) {
1008 selected_world[global_x][global_y] = id;
1018 return absl::OkStatus();
1024 return absl::OkStatus();
1033 return absl::OkStatus();
1043 const bool saving_maps =
1055 manifest, write_policy, ranges,
"overworld maps",
"OverworldEditor",
1078 return absl::OkStatus();
1098 auto now = std::chrono::steady_clock::now();
1117 .tile_changes = {{{x, y}, old_tile_id}},
1131 std::vector<OverworldTileChange> changes;
1133 for (
const auto& [coords, old_tile_id] :
1135 auto [x, y] = coords;
1136 int new_tile_id = world_tiles[x][y];
1137 changes.push_back({x, y, old_tile_id, new_tile_id});
1139 auto action = std::make_unique<OverworldTilePaintAction>(
1141 std::move(changes), &
overworld_, [
this]() { RefreshOverworldMap(); });
1162 LOG_DEBUG(
"OverworldEditor",
"Loading overworld.");
1178 LOG_DEBUG(
"OverworldEditor",
"Loading overworld graphics (optimized).");
1192 "Loading overworld tileset (deferred textures).");
1205 LOG_DEBUG(
"OverworldEditor",
"Loading overworld tile16 graphics.");
1234 return absl::OkStatus();
1239 const int depth = 0x10;
1240 for (
int i = 0; i < 3; i++)
1242 int width = sprite.width();
1243 int height = sprite.height();
1244 if (width == 0 || height == 0) {
1251 *sprite.preview_graphics());
1257 return absl::OkStatus();
1267 int refresh_count = 0;
1268 const int max_refreshes_per_frame = 2;
1270 auto try_refresh_map = [&](
int map_index) {
1274 if (refresh_count >= max_refreshes_per_frame) {
1289 for (
int i = world_start;
1290 i < world_end && refresh_count < max_refreshes_per_frame; ++i) {
1306 LOG_ERROR(
"OverworldEditor",
"Failed to build map %d: %s", map_index,
1314 if (!bitmap.is_active()) {
1320 bitmap.SetPalette(palette);
1321 }
catch (
const std::bad_alloc& e) {
1322 LOG_ERROR(
"OverworldEditor",
"Error allocating bitmap for map %d: %s",
1323 map_index, e.what());
1328 if (!bitmap.texture() && bitmap.is_active()) {
1355 map_refresh_ = std::make_unique<MapRefreshCoordinator>(ctx);
1390 const size_t session_id =
1415 return absl::OkStatus();
1432 const char* world_label =
"LW";
1448 "Map", absl::StrFormat(
"%s #%02X", world_label,
current_map_ & 0xFF));
1452 const char* mode_label =
"Draw";
1455 mode_label =
"Entrances";
1458 mode_label =
"Exits";
1461 mode_label =
"Items";
1464 mode_label =
"Sprites";
1467 mode_label =
"Transports";
1470 mode_label =
"Music";
1475 mode_label =
"Mouse";
1478 mode_label =
"Draw";
1481 mode_label =
"Fill";
void set_dirty(bool dirty)
bool loaded() const
Check if the manifest has been loaded.
UndoManager undo_manager_
EditorDependencies dependencies_
void SetHostSurfaceHint(std::string hint)
Main UI class for editing overworld maps in A Link to the Past.
std::unique_ptr< UsageStatisticsCard > usage_stats_card_
absl::Status Clear() override
std::unique_ptr< MapPropertiesSystem > map_properties_system_
std::unique_ptr< OverworldCanvasRenderer > canvas_renderer_
OverworldEntityWorkbench * GetWorkbench()
Resolve the entity workbench window content (may be null).
void HandleMapInteraction()
bool overworld_canvas_fullscreen_
bool map_blockset_loaded_
zelda3::OverworldEntranceTileTypes entrance_tiletypes_
void HandleTile16Edit()
Handle tile16 editing from context menu (MOUSE mode) Gets the tile16 under the cursor and opens the T...
std::optional< OverworldUndoPoint > current_paint_operation_
void PushItemUndoAction(OverworldItemsSnapshot before, std::string description)
absl::Status CheckForCurrentMap()
Check for map changes and refresh if needed.
void CreateUndoPoint(int map_id, int world, int x, int y, int old_tile_id)
absl::Status LoadScratchToSelection()
void ForceRefreshGraphics(int map_index)
void RequestTile16Selection(int tile_id)
void RestoreItemUndoSnapshot(const OverworldItemsSnapshot &snapshot)
std::vector< int > selected_tile16_ids_
gfx::Bitmap current_gfx_bmp_
gfx::Tilemap tile16_blockset_
void InitCanvasNavigationManager()
Initialize the canvas navigation manager (called during Initialize)
void InitMapRefreshCoordinator()
Initialize the map refresh coordinator (called during Initialize)
std::optional< zelda3::OverworldItem > selected_item_identity_
void CycleTileSelection(int delta)
Tile16Editor tile16_editor_
std::unique_ptr< zelda3::OverworldUpgradeSystem > upgrade_system_
gui::Canvas ow_map_canvas_
void NotifyEntityModified(zelda3::GameEntity *entity)
Notify that an entity has been modified, marking ROM as dirty.
absl::Status Undo() override
void HandleEntityInsertion(const std::string &entity_type)
Handle entity insertion from context menu.
std::unique_ptr< MapRefreshCoordinator > map_refresh_
std::array< gfx::Bitmap, zelda3::kNumOverworldMaps > maps_bmp_
bool PickTile16FromHoveredCanvas()
bool show_map_properties_panel_
void RefreshOverworldMap()
void CheckForOverworldEdits()
Check for tile edits - delegates to TilePaintingManager.
void UpdateBlocksetWithPendingTileChanges()
void RefreshMapProperties()
void ContributeStatus(StatusBar *status_bar) override
void RefreshSiblingMapGraphics(int map_index, bool include_self=false)
void RefreshOverworldMapOnDemand(int map_index)
void Initialize() override
bool show_overlay_editor_
std::unique_ptr< OverworldSidebar > sidebar_
absl::Status Redo() override
void SetupCanvasAutomation()
std::chrono::steady_clock::time_point last_paint_time_
void InvalidateGraphicsCache(int map_id=-1)
Invalidate cached graphics for a specific map or all maps.
std::optional< int > pending_tile16_selection_after_gfx_
absl::Status SaveCurrentSelectionToScratch()
zelda3::OverworldItem * GetSelectedItem()
Resolve selected item identity to the current live item pointer.
bool DuplicateSelectedItem(int offset_x=16, int offset_y=0)
Duplicate selected item with optional pixel offset.
absl::Status RefreshMapPalette()
absl::Status RefreshTile16Blockset()
zelda3::Overworld & overworld()
Access the underlying Overworld data.
void SetCurrentEntity(zelda3::GameEntity *entity)
Set the currently active entity for editing.
void UpdateBlocksetSelectorState()
void FinalizePaintOperation()
std::unique_ptr< OverworldEntityRenderer > entity_renderer_
auto & GetWorldTiles(int world)
absl::Status Load() override
absl::Status UpdateGfxGroupEditor()
void EnsureMapTexture(int map_index)
Ensure a specific map has its texture created.
std::vector< gfx::Bitmap > sprite_previews_
std::unique_ptr< CanvasNavigationManager > canvas_nav_
absl::Status Copy() override
bool NudgeSelectedItem(int delta_x, int delta_y)
Move selected item by signed pixel deltas.
EntityEditMode entity_edit_mode_
std::unique_ptr< OverworldToolbar > toolbar_
GfxGroupEditor gfx_group_editor_
void ProcessDeferredTextures()
Create textures for deferred map bitmaps on demand.
absl::Status Update() final
std::unique_ptr< gui::TileSelectorWidget > blockset_selector_
absl::Status Paste() override
void ScrollBlocksetCanvasToCurrentTile()
Scroll the blockset canvas to show the current selected tile16.
static constexpr auto kPaintBatchTimeout
bool DeleteSelectedItem()
Delete selected item and preserve nearest-item selection continuity.
std::unique_ptr< TilePaintingManager > tile_painting_
gfx::BitmapTable current_graphics_set_
bool show_custom_bg_color_editor_
zelda3::Overworld overworld_
absl::Status LoadGraphics()
Load the Bitmap objects for each OverworldMap.
absl::Status LoadSpriteGraphics()
gfx::IRenderer * renderer_
OverworldItemsSnapshot CaptureItemUndoSnapshot() const
absl::Status Save() override
void InitInteractionCoordinator()
std::unique_ptr< DebugWindowCard > debug_window_card_
std::unique_ptr< OverworldInteractionCoordinator > interaction_coordinator_
zelda3::GameEntity * current_entity_
void HandleKeyboardShortcuts()
Handle overworld keyboard shortcuts and edit-mode hotkeys.
std::unique_ptr< EntityMutationService > entity_mutation_service_
gfx::SnesPalette palette_
gfx::Bitmap tile16_blockset_bmp_
void ClearSelectedItem()
Clear active item selection.
void InitTilePaintingManager()
Initialize the tile painting manager (called after graphics load)
bool SelectItemByIdentity(const zelda3::OverworldItem &item_identity)
Select an overworld item using value identity matching.
Authoritative component for entity editing state and UI.
void OpenContextMenuFor(zelda3::GameEntity *entity)
void SetActiveEntity(zelda3::GameEntity *entity)
A session-aware status bar displayed at the bottom of the application.
void SetCustomSegment(const std::string &key, const std::string &value)
Set a custom segment with key-value pair.
void SetEditorMode(const std::string &mode)
Set the current editor mode or tool.
int current_tile16() const
bool has_pending_changes() const
Check if any tiles have uncommitted changes.
void RequestTileSwitch(int target_tile_id)
absl::Status Initialize(gfx::Bitmap &tile16_blockset_bmp, gfx::Bitmap ¤t_gfx_bmp, std::array< uint8_t, 0x200 > &all_tiles_types)
bool is_tile_modified(int tile_id) const
Check if a specific tile has pending changes.
void set_palette(const gfx::SnesPalette &palette)
void set_on_current_tile_changed(std::function< void(int)> callback)
void set_on_changes_committed(std::function< absl::Status()> callback)
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.
absl::Status Undo()
Undo the top action. Returns error if stack is empty.
size_t GetActiveSessionId() const
bool OpenWindow(size_t session_id, const std::string &base_window_id)
WindowContent * GetWindowContent(const std::string &window_id)
Get a WindowContent instance by ID.
bool ToggleWindow(size_t session_id, const std::string &base_window_id)
void RegisterPanelAlias(const std::string &legacy_base_id, const std::string &canonical_base_id)
Register a legacy panel ID alias that resolves to a canonical ID.
void MarkWindowRecentlyUsed(const std::string &window_id)
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
int RegisterPaletteListener(PaletteChangeCallback callback)
Register a callback for palette change notifications.
void ProcessTextureQueue(IRenderer *renderer)
void UnregisterPaletteListener(int listener_id)
Unregister a palette change listener.
Represents a bitmap image optimized for SNES ROM hacking.
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
SDL_Surface * surface() const
RAII timer for automatic timing management.
auto selected_tile_pos() const
auto global_scale() const
auto select_rect_active() const
void SetUsageMode(CanvasUsage usage)
auto drawn_tile_position() const
const ImVector< ImVec2 > & points() const
auto selected_points() const
Base class for all overworld and dungeon entities.
enum yaze::zelda3::GameEntity::EntityType entity_type_
Represents an overworld exit that transitions from dungeon to overworld.
void set_current_world(int world)
absl::Status Load(Rom *rom)
Load all overworld data from ROM.
const std::vector< uint8_t > & current_graphics() const
absl::Status SaveMapProperties()
Save per-area graphics, palettes, and messages.
std::vector< std::pair< uint32_t, uint32_t > > GetProjectedWriteRanges() const
Get the projected write ranges (PC offsets) for overworld map saves.
absl::Status SaveMap32Tiles()
Save tile32 definitions to ROM.
const gfx::SnesPalette & current_area_palette() const
absl::Status SaveMap16Tiles()
Save tile16 definitions to ROM.
absl::Status CreateTile32Tilemap()
Build tile32 tilemap from current tile16 data.
const std::vector< uint8_t > & tile16_blockset_data() const
void set_current_map(int i)
absl::Status SaveEntrances()
Save entrance warp points to ROM.
absl::Status SaveExits()
Save exit return points to ROM.
absl::Status EnsureMapBuilt(int map_index)
Build a map on-demand if it hasn't been built yet.
absl::Status SaveItems()
Save hidden overworld items to ROM.
uint16_t GetTile(int x, int y) const
absl::Status SaveOverworldMaps()
Save compressed map tile data to ROM.
auto mutable_all_tiles_types()
const std::vector< uint8_t > & current_map_bitmap_data() const
auto mutable_sprites(int state)
absl::Status SaveMusic()
Save per-area music IDs.
#define ICON_MD_FORMAT_COLOR_FILL
#define LOG_DEBUG(category, format,...)
#define LOG_ERROR(category, format,...)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
bool ItemIdentityMatchesForUndo(const zelda3::OverworldItem &lhs, const zelda3::OverworldItem &rhs)
bool ItemSnapshotsEqual(const OverworldItemsSnapshot &lhs, const OverworldItemsSnapshot &rhs)
Editors are the view controllers for the application.
absl::Status ValidateHackManifestSaveConflicts(const core::HackManifest &manifest, project::RomWritePolicy write_policy, const std::vector< std::pair< uint32_t, uint32_t > > &ranges, absl::string_view save_scope, const char *log_tag, ToastManager *toast_manager)
absl::Status RemoveItemByIdentity(zelda3::Overworld *overworld, const zelda3::OverworldItem &item_identity)
Remove an item by value identity instead of pointer identity.
constexpr unsigned int kOverworldMapSize
absl::Status NudgeItem(zelda3::OverworldItem *item, int delta_x, int delta_y)
Move an item by pixel deltas with overworld bounds clamping.
zelda3::OverworldItem * FindNearestItemForSelection(zelda3::Overworld *overworld, const zelda3::OverworldItem &anchor_identity)
Find the best next item to keep selection continuity after deletion.
zelda3::OverworldItem * FindItemByIdentity(zelda3::Overworld *overworld, const zelda3::OverworldItem &item_identity)
Find a live item by value identity.
constexpr int kTile16Size
absl::StatusOr< zelda3::OverworldItem * > DuplicateItemByIdentity(zelda3::Overworld *overworld, const zelda3::OverworldItem &item_identity, int offset_x, int offset_y)
Duplicate an existing item by identity with a positional offset.
Tilemap CreateTilemap(IRenderer *renderer, const std::vector< uint8_t > &data, int width, int height, int tile_size, int num_tiles, const SnesPalette &palette)
void CenterText(const char *text)
constexpr int kNumTile16Individual
constexpr int kNumOverworldMaps
constexpr int OverworldCustomASMHasBeenApplied
absl::StatusOr< OverworldEntranceTileTypes > LoadEntranceTileTypes(Rom *rom)
#define RETURN_IF_ERROR(expr)
struct yaze::core::FeatureFlags::Flags::Overworld overworld
Callbacks for operations that remain in the OverworldEditor.
std::function< void()> refresh_overworld_map
std::function< absl::Status()> refresh_tile16_blockset
std::function< bool()> is_entity_hovered
Returns true if an entity is currently hovered (for pan suppression).
std::function< bool()> pick_tile16_from_hovered_canvas
std::function< void(int)> ensure_map_texture
Shared state pointers that the navigation manager reads/writes.
bool * show_map_properties_panel
std::unique_ptr< gui::TileSelectorWidget > * blockset_selector
std::array< gfx::Bitmap, zelda3::kNumOverworldMaps > * maps_bmp
gui::Canvas * ow_map_canvas
zelda3::Overworld * overworld
bool * is_dragging_entity
gfx::Tilemap * tile16_blockset
EditingMode * current_mode
project::YazeProject * project
ToastManager * toast_manager
SharedClipboard * shared_clipboard
gfx::IRenderer * renderer
WorkspaceWindowManager * window_manager
std::string error_message
zelda3::GameEntity * entity
Context struct holding all data dependencies for map refresh operations. All pointers/references must...
gfx::Tilemap * tile16_blockset
gfx::SnesPalette * palette
zelda3::Overworld * overworld
std::function< void(int map_index)> ensure_map_texture
Callback to ensure a map texture is created (stays in OverworldEditor)
gfx::IRenderer * renderer
Tile16Editor * tile16_editor
std::array< gfx::Bitmap, zelda3::kNumOverworldMaps > * maps_bmp
gfx::Bitmap * current_gfx_bmp
bool * map_blockset_loaded
gfx::BitmapTable * current_graphics_set
Sink for high-level commands emitted by the interaction coordinator.
std::function< void(zelda3::GameEntity *) on_entity_double_click)
std::function< void()> on_pick_tile_from_hover
std::function< void()> on_toggle_fullscreen
std::function< void(zelda3::GameEntity *) on_entity_context_menu)
std::function< bool()> can_edit_items
std::function< void()> on_toggle_tile16_editor
std::function< void()> on_toggle_brush
std::function< void()> on_duplicate_selected
std::function< void(int, int, bool)> on_nudge_selected
std::function< void()> on_undo
std::function< void(EditingMode)> on_set_editor_mode
std::function< void()> on_redo
std::function< void()> on_activate_fill
std::function< void(EntityEditMode)> on_set_entity_mode
std::function< void()> on_toggle_lock
std::function< void()> on_toggle_item_list
Snapshot of overworld item list + current item selection.
std::vector< zelda3::OverworldItem > items
std::optional< zelda3::OverworldItem > selected_item_identity
static constexpr const char * kItemList
static constexpr const char * kTile16Editor
std::vector< int > overworld_tile16_ids
bool has_overworld_tile16
Callbacks for undo integration and map refresh.
std::function< void(int tile_id)> request_tile16_selection
When set, eyedropper routes here (guarded RequestTileSwitch path).
std::function< void(int map_index)> refresh_overworld_map_on_demand
std::function< void()> scroll_blockset_to_current_tile
std::function< void()> finalize_paint_operation
std::function< void()> refresh_overworld_map
std::function< void(int map_id, int world, int x, int y, int old_tile_id)> create_undo_point
Shared state for the tile painting system.
Tile16Editor * tile16_editor
gui::Canvas * ow_map_canvas
zelda3::Overworld * overworld
std::vector< int > * selected_tile16_ids
std::array< gfx::Bitmap, zelda3::kNumOverworldMaps > * maps_bmp
gfx::Tilemap * tile16_blockset
EditingMode * current_mode
Bitmap atlas
Master bitmap containing all tiles.
core::HackManifest hack_manifest