19 return lhs.
id_ == rhs.
id_ && lhs.
x() == rhs.
x() && lhs.
y() == rhs.
y() &&
51 int pixel_w,
int pixel_h) {
53 const int x = std::clamp(pixel_x, 0, kDungeonCanvasPixelSize - 1);
54 const int y = std::clamp(pixel_y, 0, kDungeonCanvasPixelSize - 1);
56 std::clamp(pixel_w, 1, std::max(1, kDungeonCanvasPixelSize - x));
58 std::clamp(pixel_h, 1, std::max(1, kDungeonCanvasPixelSize - y));
64 const std::vector<zelda3::RoomObject>& previous_objects,
65 const std::vector<zelda3::RoomObject>& next_objects) {
69 const auto [x, y, w, h] =
75 const size_t count = std::max(previous_objects.size(), next_objects.size());
76 for (
size_t i = 0; i < count; ++i) {
77 const bool has_previous = i < previous_objects.size();
78 const bool has_next = i < next_objects.size();
79 if (has_previous && has_next &&
80 HasSameObjectIdentity(previous_objects[i], next_objects[i])) {
84 append_object_rect(previous_objects[i]);
87 append_object_rect(next_objects[i]);
100 auto apply_list = [](std::array<bool, 256>& dest,
101 const std::vector<uint16_t>& values) {
103 for (uint16_t value : values) {
109 auto ids_valid = [](
const std::vector<uint16_t>& values) {
110 std::array<bool, 256> seen{};
111 for (uint16_t value : values) {
112 if (value >= seen.size() || seen[value]) {
120 std::vector<uint16_t> default_track_tile_list;
121 for (uint16_t tile = 0xB0; tile <= 0xBE; ++tile) {
122 default_track_tile_list.push_back(tile);
124 const std::vector<uint16_t> default_stop_tile_list = {0xB7, 0xB8, 0xB9, 0xBA};
125 const std::vector<uint16_t> default_switch_tile_list = {0xD0, 0xD1, 0xD2,
128 const auto& track_tiles =
131 : default_track_tile_list;
135 const auto& stop_tiles =
138 : default_stop_tile_list;
141 const auto& switch_tiles =
144 : default_switch_tile_list;
154 std::vector<uint16_t> minecart_ids = {0xA3};
158 for (uint16_t
id : minecart_ids) {
228 if (active_room !=
nullptr) {
243 !ImGui::GetCurrentContext()) {
248 if (elapsed >= kChangePingDurationSeconds) {
258 if (index >= objects.size()) {
261 const auto [x, y, w, h] =
264 rects.push_back(
ChangePingRect{x, y, std::max(w, 8), std::max(h, 8)});
267 auto selected_entities =
273 switch (entity.type) {
275 const auto& doors = room.
GetDoors();
276 if (entity.index < doors.size()) {
277 const auto [x, y, w, h] = doors[entity.index].GetEditorBounds();
285 if (entity.index < sprites.size()) {
287 sprites[entity.index].y() * 16, 16,
294 if (entity.index < pot_items.size()) {
295 rects.push_back(
ChangePingRect{pot_items[entity.index].GetPixelX(),
296 pot_items[entity.index].GetPixelY(),
310 ChangePingRect{0, 0, kDungeonCanvasPixelSize, kDungeonCanvasPixelSize});
313 const float progress =
314 static_cast<float>(elapsed / kChangePingDurationSeconds);
315 const float remaining = std::clamp(1.0f - progress, 0.0f, 1.0f);
316 const float expand = 4.0f + 12.0f * progress;
318 ImVec4 fill = theme.dungeon_selection_pulsing;
319 fill.w = 0.18f * remaining;
320 ImVec4 border = theme.dungeon_selection_primary;
321 border.w = 0.95f * remaining;
322 const ImU32 fill_color = ImGui::GetColorU32(fill);
323 const ImU32 border_color = ImGui::GetColorU32(border);
325 const ImVec2 viewport_min = canvas_rt.
canvas_p0;
331 static_cast<float>(rect.x) * canvas_rt.
scale - expand,
333 static_cast<float>(rect.y) * canvas_rt.
scale - expand);
335 min.x +
static_cast<float>(rect.w) * canvas_rt.
scale + expand * 2.0f,
336 min.y +
static_cast<float>(rect.h) * canvas_rt.
scale + expand * 2.0f);
338 const bool visible = max.x >= viewport_min.x && min.x <= viewport_max.x &&
339 max.y >= viewport_min.y && min.y <= viewport_max.y;
341 canvas_rt.
draw_list->AddRectFilled(min, max, fill_color, 2.0f);
342 canvas_rt.
draw_list->AddRect(min, max, border_color, 2.0f, 0,
343 2.0f + 2.0f * remaining);
349 (
static_cast<float>(rect.x) +
static_cast<float>(rect.w) * 0.5f) *
352 (
static_cast<float>(rect.y) +
static_cast<float>(rect.h) * 0.5f) *
354 const float marker_min_x = viewport_min.x + 8.0f;
355 const float marker_min_y = viewport_min.y + 8.0f;
356 const float marker_max_x = std::max(marker_min_x, viewport_max.x - 8.0f);
357 const float marker_max_y = std::max(marker_min_y, viewport_max.y - 8.0f);
358 const ImVec2 clamped(std::clamp(center.x, marker_min_x, marker_max_x),
359 std::clamp(center.y, marker_min_y, marker_max_y));
360 canvas_rt.
draw_list->AddCircleFilled(clamped, 5.0f + 4.0f * remaining,
362 canvas_rt.
draw_list->AddCircle(clamped, 7.0f + 6.0f * remaining,
363 border_color, 18, 2.0f);
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
void RecordVisitedRoom(int room_id)
void PopulateCanvasContextMenu(int room_id)
void DrawChangePingOverlay(const gui::CanvasRuntime &canvas_rt, const zelda3::Room &room)
void ApplyTrackCollisionConfig()
std::vector< int > recently_visited_rooms_
std::bitset< 256 > minecart_sprite_ids_
std::vector< uint16_t > track_tile_order_
DungeonRoomStore * rooms() const
void SyncCanvasCaptureRegion(const gui::CanvasRuntime &canvas_rt)
void DrawPersistentDebugWindows(int room_id)
void SetProject(const project::YazeProject *project)
void SyncCanvasConfigFromViewerState()
zelda3::GameData * game_data() const
std::vector< uint16_t > switch_tile_order_
zelda3::Room * PrepareActiveRoomForCanvasFrame(int room_id)
void RefreshRomBackedState(Rom *rom, zelda3::GameData *game_data, DungeonRoomStore *rooms, int room_id)
DungeonObjectInteraction object_interaction_
uint64_t last_palette_hash_
void DrawRoomCanvasContent(const gui::CanvasRuntime &canvas_rt, zelda3::Room &room, int room_id)
double change_ping_start_time_
void DrawCoordinateOverlayHud(int room_id)
void ClearPreviewObject()
void TriggerCanvasPingRect(int pixel_x, int pixel_y, int pixel_w, int pixel_h)
const project::YazeProject * project_
void DrawCompactLayerToggles(int room_id)
int last_connected_matrix_room_id_
std::unordered_map< int, DungeonRenderingHelpers::CollisionOverlayCache > collision_overlay_cache_
bool track_direction_map_enabled_
void TriggerObjectChangePing(const std::vector< zelda3::RoomObject > &previous_objects, const std::vector< zelda3::RoomObject > &next_objects)
bool ValidateRoomCanvasRequest(int room_id)
gui::CanvasFrameOptions BuildRoomCanvasFrameOptions() const
const project::YazeProject * project() const
gui::CanvasTouchHandler touch_handler_
void ConsumePendingCanvasScroll(const gui::CanvasRuntime &canvas_rt)
void DrawDungeonCanvas(int room_id)
void SyncViewerStateFromCanvasConfig()
std::map< int, zelda3::RoomLayerManager > room_layer_managers_
std::vector< ObjectRenderCache > object_render_cache_
DungeonRenderingHelpers::TrackCollisionConfig track_collision_config_
void SetRooms(DungeonRoomStore *rooms)
std::vector< ChangePingRect > change_ping_rects_
void DrawHeaderHiddenMetadataHud(int room_id)
void DrawRoomCanvasOverlays(const gui::CanvasRuntime &rt, zelda3::Room &room, int room_id)
void SetGameData(zelda3::GameData *game_data)
SelectedEntity GetSelectedEntity() const
void SetCurrentRoom(DungeonRoomStore *rooms, int room_id)
std::vector< size_t > GetSelectedObjectIndices() const
InteractionModeManager & mode_manager()
InteractionCoordinator & entity_coordinator()
Get the interaction coordinator for entity handling.
bool HasEntitySelection() const
const std::vector< SelectedEntity > & GetSelectedEntities() const
void ClearAllEntitySelections()
Clear all entity selections.
void CancelCurrentMode()
Cancel current mode and return to Select.
void Update()
Update touch state each frame.
void ProcessForCanvas(ImVec2 canvas_p0, ImVec2 canvas_sz, bool is_hovered)
Process touch gestures for the current canvas bounds.
static DimensionService & Get()
std::tuple< int, int, int, int > GetSelectionBoundsPixels(const RoomObject &obj) const
uint8_t GetLayerValue() const
const std::vector< Door > & GetDoors() const
const std::vector< zelda3::Sprite > & GetSprites() const
const std::vector< RoomObject > & GetTileObjects() const
const std::vector< PotItem > & GetPotItems() const
const AgentUITheme & GetTheme()
constexpr double kChangePingDurationSeconds
constexpr size_t kRecentRoomLimit
constexpr int kDungeonCanvasPixelSize
bool HasSameObjectIdentity(const zelda3::RoomObject &lhs, const zelda3::RoomObject &rhs)
Editors are the view controllers for the application.
void EndCanvas(Canvas &canvas)
void BeginCanvas(Canvas &canvas, ImVec2 child_size)
constexpr int kNumberOfRooms
std::array< bool, 256 > stop_tiles
std::array< bool, 256 > switch_tiles
std::array< bool, 256 > track_tiles
Represents a selected entity in the dungeon editor.
std::vector< uint16_t > minecart_sprite_ids
std::vector< uint16_t > track_stop_tiles
std::vector< uint16_t > track_tiles
std::vector< uint16_t > track_switch_tiles
Modern project structure with comprehensive settings consolidation.
DungeonOverlaySettings dungeon_overlay