6#include "absl/status/status.h"
8#include "imgui/imgui.h"
25 constexpr float kWorldSize = 512.0f * 8.0f;
26 return ImVec2(kWorldSize * scale, kWorldSize * scale);
31 ImVec2 visible_size) {
32 float max_scroll_x = std::max(0.0f, content_size.x - visible_size.x);
33 float max_scroll_y = std::max(0.0f, content_size.y - visible_size.y);
35 float clamped_x = std::clamp(scroll.x, -max_scroll_x, 0.0f);
36 float clamped_y = std::clamp(scroll.y, -max_scroll_y, 0.0f);
38 return ImVec2(clamped_x, clamped_y);
42 const int clamped_world = std::clamp(world, 0, 2);
43 const int world_start = clamped_world * 0x40;
44 const int maps_available =
46 return (maps_available + 7) / 8;
50 ImVec2 scaled_position) {
64 if (map_x < 0 || map_x >= 8 || map_y < 0 || map_y >= 8) {
72 int map_id = map_x + map_y * 8;
146 return absl::OkStatus();
149 const int large_map_size = 1024;
151 const auto hovered_map =
153 if (!hovered_map.has_value()) {
154 SetHoveredMap(
ctx_, -1);
155 return absl::OkStatus();
157 SetHoveredMap(
ctx_, *hovered_map);
162 bool should_build =
false;
170 ImGui::IsMouseClicked(ImGuiMouseButton_Left) ||
171 ImGui::IsMouseClicked(ImGuiMouseButton_Right);
185 if (current_highlighted_map < 0 ||
188 return absl::OkStatus();
193 bool use_v3_area_sizes =
197 if (use_v3_area_sizes) {
201 const int highlight_parent =
208 parent_map_x = highlight_parent % 8;
209 parent_map_y = highlight_parent / 8;
211 parent_map_x = (highlight_parent - 0x40) % 8;
212 parent_map_y = (highlight_parent - 0x40) / 8;
214 parent_map_x = (highlight_parent - 0x80) % 8;
215 parent_map_y = (highlight_parent - 0x80) / 8;
220 case AreaSizeEnum::LargeArea:
223 large_map_size, large_map_size);
225 case AreaSizeEnum::WideArea:
230 case AreaSizeEnum::TallArea:
235 case AreaSizeEnum::SmallArea:
248 const int highlight_parent =
254 parent_map_x = highlight_parent % 8;
255 parent_map_y = highlight_parent / 8;
257 parent_map_x = (highlight_parent - 0x40) % 8;
258 parent_map_y = (highlight_parent - 0x40) / 8;
260 parent_map_x = (highlight_parent - 0x80) % 8;
261 parent_map_y = (highlight_parent - 0x80) / 8;
266 large_map_size, large_map_size);
271 current_map_x = current_highlighted_map % 8;
272 current_map_y = current_highlighted_map / 8;
274 current_map_x = (current_highlighted_map - 0x40) % 8;
275 current_map_y = (current_highlighted_map - 0x40) / 8;
277 current_map_x = (current_highlighted_map - 0x80) % 8;
278 current_map_y = (current_highlighted_map - 0x80) / 8;
316 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
322 return absl::OkStatus();
342 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
356 auto map_from_cursor = [&]() -> std::optional<int> {
363 const auto hovered_map = map_from_cursor();
364 if (!hovered_map.has_value()) {
368 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
372 if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
377 if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle)) {
396 bool should_pan =
false;
398 if (ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
400 }
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left) &&
416 ImVec2 delta = ImGui::GetIO().MouseDelta;
417 float new_scroll_x = ImGui::GetScrollX() - delta.x;
418 float new_scroll_y = ImGui::GetScrollY() - delta.y;
421 float max_scroll_x = ImGui::GetScrollMaxX();
422 float max_scroll_y = ImGui::GetScrollMaxY();
425 new_scroll_x = std::clamp(new_scroll_x, 0.0f, max_scroll_x);
426 new_scroll_y = std::clamp(new_scroll_y, 0.0f, max_scroll_y);
428 ImGui::SetScrollX(new_scroll_x);
429 ImGui::SetScrollY(new_scroll_y);
460 ImGui::SetScrollX(0);
461 ImGui::SetScrollY(0);
477 ImVec2 viewport_px = ImGui::GetContentRegionAvail();
484 float scroll_x = center_x - viewport_px.x / 2.0f;
485 float scroll_y = center_y - viewport_px.y / 2.0f;
488 scroll_x = std::clamp(scroll_x, 0.0f, ImGui::GetScrollMaxX());
489 scroll_y = std::clamp(scroll_y, 0.0f, ImGui::GetScrollMaxY());
491 ImGui::SetScrollX(scroll_x);
492 ImGui::SetScrollY(scroll_y);
548 int world_offset = (center_map / 64) * 64;
549 int local_index = center_map % 64;
550 int map_x = local_index % 8;
551 int map_y = local_index / 8;
555 static const int dx[] = {-1, 1, 0, 0};
556 static const int dy[] = {0, 0, -1, 1};
558 for (
int i = 0; i < 4; ++i) {
559 int nx = map_x + dx[i];
560 int ny = map_y + dy[i];
563 if (nx >= 0 && nx < 8 && ny >= 0 && ny < max_rows) {
564 int neighbor_index = world_offset + ny * 8 + nx;
595 "Background preload of map %d failed: %s", map_to_preload,
596 status.message().data());
void ScrollBlocksetCanvasToCurrentTile()
Scroll the blockset (tile16 selector) to show the currently selected tile16.
static constexpr float kHoverBuildDelay
absl::Status CheckForCurrentMap()
Detect which map the mouse is over, trigger lazy loading, draw the selection outline,...
void UpdateBlocksetSelectorState()
Push current tile count and selection into the blockset widget.
void ProcessPreloadQueue()
Process one map from the preload queue (call once per frame).
CanvasNavigationCallbacks callbacks_
CanvasNavigationContext ctx_
void HandleOverworldPan()
Pan the overworld canvas via middle-click or left-click drag (in MOUSE mode when not hovering an enti...
void QueueAdjacentMapsForPreload(int center_map)
Queue the 4-connected neighbors of center_map for lazy build.
static constexpr float kPreloadStartDelay
std::vector< int > preload_queue_
void Initialize(const CanvasNavigationContext &context, const CanvasNavigationCallbacks &callbacks)
Initialize with shared state and callbacks.
void HandleMapInteraction()
Handle tile-mode right-click (eyedropper) and middle-click (lock/properties toggle),...
void ZoomOut()
Decrease canvas zoom by one step.
void CenterOverworldView()
Center the viewport on the current map.
void CheckForMousePan()
Legacy wrapper – delegates to HandleOverworldPan().
void ZoomIn()
Increase canvas zoom by one step.
void ResetOverworldView()
Reset scroll to top-left and scale to 1.0.
void HandleOverworldZoom()
No-op stub preserved for API compatibility.
void ClampOverworldScroll()
No-op stub – ImGui handles scroll clamping automatically.
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
auto global_scale() const
auto hover_mouse_pos() const
void set_global_scale(float scale)
bool IsMouseHovering() const
void DrawOutline(int x, int y, int w, int h)
static OverworldVersion GetVersion(const Rom &rom)
Detect ROM version from ASM marker byte.
static bool SupportsAreaEnum(OverworldVersion version)
Check if ROM supports area enum system (v3+ only)
void set_current_world(int world)
auto overworld_map(int i) const
void set_current_map(int i)
absl::Status EnsureMapBuilt(int map_index)
Build a map on-demand if it hasn't been built yet.
#define LOG_DEBUG(category, format,...)
void SelectMapForEditing(const CanvasNavigationContext &ctx, const CanvasNavigationCallbacks &callbacks, int map_id, bool respect_pin)
void SetHoveredMap(const CanvasNavigationContext &ctx, int map_id)
ImVec2 CalculateOverworldContentSize(float scale)
std::optional< int > MapFromCanvasPosition(const CanvasNavigationContext &ctx, ImVec2 scaled_position)
int AllocatedRowsForWorld(int world)
ImVec2 ClampScrollPosition(ImVec2 scroll, ImVec2 content_size, ImVec2 visible_size)
void SelectMapFallback(const CanvasNavigationContext &ctx, int map_id, bool respect_pin)
Editors are the view controllers for the application.
constexpr unsigned int kOverworldMapSize
constexpr float kOverworldMaxZoom
constexpr float kOverworldMinZoom
constexpr float kOverworldZoomStep
constexpr int kNumTile16Individual
constexpr int kSpecialWorldMapIdStart
constexpr int kNumOverworldMaps
AreaSizeEnum
Area size enumeration for v3+ ROMs.
#define RETURN_IF_ERROR(expr)
Callbacks for operations that remain in the OverworldEditor.
std::function< void()> refresh_overworld_map
std::function< absl::Status()> refresh_tile16_blockset
std::function< void(int, bool)> select_map_for_editing
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
Bitmap atlas
Master bitmap containing all tiles.