6#include "absl/status/status.h"
9#include "imgui/imgui.h"
26 constexpr float kWorldSize = 512.0f * 8.0f;
27 return ImVec2(kWorldSize * scale, kWorldSize * scale);
32 ImVec2 visible_size) {
33 float max_scroll_x = std::max(0.0f, content_size.x - visible_size.x);
34 float max_scroll_y = std::max(0.0f, content_size.y - visible_size.y);
36 float clamped_x = std::clamp(scroll.x, -max_scroll_x, 0.0f);
37 float clamped_y = std::clamp(scroll.y, -max_scroll_y, 0.0f);
39 return ImVec2(clamped_x, clamped_y);
43 const int clamped_world = std::clamp(world, 0, 2);
44 const int world_start = clamped_world * 0x40;
45 const int maps_available =
47 return (maps_available + 7) / 8;
51 ImVec2 scaled_position) {
65 if (map_x < 0 || map_x >= 8 || map_y < 0 || map_y >= 8) {
73 int map_id = map_x + map_y * 8;
147 return absl::OkStatus();
154 SetHoveredMap(
ctx_, -1);
155 return absl::OkStatus();
158 const int large_map_size = 1024;
160 const auto hovered_map =
162 if (!hovered_map.has_value()) {
163 SetHoveredMap(
ctx_, -1);
164 return absl::OkStatus();
166 SetHoveredMap(
ctx_, *hovered_map);
179 bool should_build =
false;
187 ImGui::IsMouseClicked(ImGuiMouseButton_Left) ||
188 ImGui::IsMouseClicked(ImGuiMouseButton_Right);
202 if (current_highlighted_map < 0 ||
205 return absl::OkStatus();
210 bool use_v3_area_sizes =
214 if (use_v3_area_sizes) {
218 const int highlight_parent =
225 parent_map_x = highlight_parent % 8;
226 parent_map_y = highlight_parent / 8;
228 parent_map_x = (highlight_parent - 0x40) % 8;
229 parent_map_y = (highlight_parent - 0x40) / 8;
231 parent_map_x = (highlight_parent - 0x80) % 8;
232 parent_map_y = (highlight_parent - 0x80) / 8;
237 case AreaSizeEnum::LargeArea:
240 large_map_size, large_map_size);
242 case AreaSizeEnum::WideArea:
247 case AreaSizeEnum::TallArea:
252 case AreaSizeEnum::SmallArea:
265 const int highlight_parent =
271 parent_map_x = highlight_parent % 8;
272 parent_map_y = highlight_parent / 8;
274 parent_map_x = (highlight_parent - 0x40) % 8;
275 parent_map_y = (highlight_parent - 0x40) / 8;
277 parent_map_x = (highlight_parent - 0x80) % 8;
278 parent_map_y = (highlight_parent - 0x80) / 8;
283 large_map_size, large_map_size);
288 current_map_x = current_highlighted_map % 8;
289 current_map_y = current_highlighted_map / 8;
291 current_map_x = (current_highlighted_map - 0x40) % 8;
292 current_map_y = (current_highlighted_map - 0x40) / 8;
294 current_map_x = (current_highlighted_map - 0x80) % 8;
295 current_map_y = (current_highlighted_map - 0x80) / 8;
333 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
339 return absl::OkStatus();
359 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
373 auto map_from_cursor = [&]() -> std::optional<int> {
380 const auto hovered_map = map_from_cursor();
381 if (!hovered_map.has_value()) {
385 if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
389 if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
394 if (ImGui::IsMouseClicked(ImGuiMouseButton_Middle)) {
413 bool should_pan =
false;
415 if (ImGui::IsMouseDragging(ImGuiMouseButton_Middle)) {
417 }
else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left) &&
433 ImVec2 delta = ImGui::GetIO().MouseDelta;
434 float new_scroll_x = ImGui::GetScrollX() - delta.x;
435 float new_scroll_y = ImGui::GetScrollY() - delta.y;
438 float max_scroll_x = ImGui::GetScrollMaxX();
439 float max_scroll_y = ImGui::GetScrollMaxY();
442 new_scroll_x = std::clamp(new_scroll_x, 0.0f, max_scroll_x);
443 new_scroll_y = std::clamp(new_scroll_y, 0.0f, max_scroll_y);
445 ImGui::SetScrollX(new_scroll_x);
446 ImGui::SetScrollY(new_scroll_y);
477 ImGui::SetScrollX(0);
478 ImGui::SetScrollY(0);
494 ImVec2 viewport_px = ImGui::GetContentRegionAvail();
501 float scroll_x = center_x - viewport_px.x / 2.0f;
502 float scroll_y = center_y - viewport_px.y / 2.0f;
505 scroll_x = std::clamp(scroll_x, 0.0f, ImGui::GetScrollMaxX());
506 scroll_y = std::clamp(scroll_y, 0.0f, ImGui::GetScrollMaxY());
508 ImGui::SetScrollX(scroll_x);
509 ImGui::SetScrollY(scroll_y);
565 int world_offset = (center_map / 64) * 64;
566 int local_index = center_map % 64;
567 int map_x = local_index % 8;
568 int map_y = local_index / 8;
572 static const int dx[] = {-1, 1, 0, 0};
573 static const int dy[] = {0, 0, -1, 1};
575 for (
int i = 0; i < 4; ++i) {
576 int nx = map_x + dx[i];
577 int ny = map_y + dy[i];
580 if (nx >= 0 && nx < 8 && ny >= 0 && ny < max_rows) {
581 int neighbor_index = world_offset + ny * 8 + nx;
612 "Background preload of map %d failed: %s", map_to_preload,
613 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
std::string FormatOverworldMapStatusSegment(int current_map, int hovered_map)
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.