19 return lhs.
id_ == rhs.
id_ && lhs.
x() == rhs.
x() && lhs.
y() == rhs.
y() &&
61 if (room && (!state.room_settings ||
62 state.room_settings->first != room->layer_merging() ||
63 state.room_settings->second != room->effect())) {
64 state.manager.ApplyLayerMerging(room->layer_merging());
65 state.manager.ApplyRoomEffect(room->effect());
66 state.room_settings = std::make_pair(room->layer_merging(), room->effect());
77 int pixel_w,
int pixel_h) {
79 const int x = std::clamp(pixel_x, 0, kDungeonCanvasPixelSize - 1);
80 const int y = std::clamp(pixel_y, 0, kDungeonCanvasPixelSize - 1);
82 std::clamp(pixel_w, 1, std::max(1, kDungeonCanvasPixelSize - x));
84 std::clamp(pixel_h, 1, std::max(1, kDungeonCanvasPixelSize - y));
90 const std::vector<zelda3::RoomObject>& previous_objects,
91 const std::vector<zelda3::RoomObject>& next_objects) {
95 const auto [x, y, w, h] =
101 const size_t count = std::max(previous_objects.size(), next_objects.size());
102 for (
size_t i = 0; i < count; ++i) {
103 const bool has_previous = i < previous_objects.size();
104 const bool has_next = i < next_objects.size();
105 if (has_previous && has_next &&
106 HasSameObjectIdentity(previous_objects[i], next_objects[i])) {
110 append_object_rect(previous_objects[i]);
113 append_object_rect(next_objects[i]);
126 auto apply_list = [](std::array<bool, 256>& dest,
127 const std::vector<uint16_t>& values) {
129 for (uint16_t value : values) {
135 auto ids_valid = [](
const std::vector<uint16_t>& values) {
136 std::array<bool, 256> seen{};
137 for (uint16_t value : values) {
138 if (value >= seen.size() || seen[value]) {
146 std::vector<uint16_t> default_track_tile_list;
147 for (uint16_t tile = 0xB0; tile <= 0xBE; ++tile) {
148 default_track_tile_list.push_back(tile);
150 const std::vector<uint16_t> default_stop_tile_list = {0xB7, 0xB8, 0xB9, 0xBA};
151 const std::vector<uint16_t> default_switch_tile_list = {0xD0, 0xD1, 0xD2,
154 const auto& track_tiles =
157 : default_track_tile_list;
161 const auto& stop_tiles =
164 : default_stop_tile_list;
167 const auto& switch_tiles =
170 : default_switch_tile_list;
180 std::vector<uint16_t> minecart_ids = {0xA3};
184 for (uint16_t
id : minecart_ids) {
237 if (ImGui::GetCurrentContext() ==
nullptr) {
240 const int frame = ImGui::GetFrameCount();
250 return item.second.last_used_frame >= 0 &&
251 item.second.last_used_frame < frame - 1;
273 if (active_room !=
nullptr) {
280 const bool pointer_pressed = ImGui::IsMouseClicked(ImGuiMouseButton_Left) ||
281 ImGui::IsMouseClicked(ImGuiMouseButton_Right) ||
282 ImGui::IsMouseClicked(ImGuiMouseButton_Middle);
284 ImGui::GetFrameCount());
296 if (active_room !=
nullptr) {
309 bool pointer_pressed,
312 if (pointer_pressed) {
318 int frame_index)
const {
326 !ImGui::GetCurrentContext()) {
331 if (elapsed >= kChangePingDurationSeconds) {
341 if (index >= objects.size()) {
344 const auto [x, y, w, h] =
347 rects.push_back(
ChangePingRect{x, y, std::max(w, 8), std::max(h, 8)});
350 auto selected_entities =
356 switch (entity.type) {
358 const auto& doors = room.
GetDoors();
359 if (entity.index < doors.size()) {
360 const auto [x, y, w, h] = doors[entity.index].GetEditorBounds();
368 if (entity.index < sprites.size()) {
370 sprites[entity.index].y() * 16, 16,
377 if (entity.index < pot_items.size()) {
378 rects.push_back(
ChangePingRect{pot_items[entity.index].GetPixelX(),
379 pot_items[entity.index].GetPixelY(),
393 ChangePingRect{0, 0, kDungeonCanvasPixelSize, kDungeonCanvasPixelSize});
396 const float progress =
397 static_cast<float>(elapsed / kChangePingDurationSeconds);
398 const float remaining = std::clamp(1.0f - progress, 0.0f, 1.0f);
399 const float expand = 4.0f + 12.0f * progress;
401 ImVec4 fill = theme.dungeon_selection_pulsing;
402 fill.w = 0.18f * remaining;
403 ImVec4 border = theme.dungeon_selection_primary;
404 border.w = 0.95f * remaining;
405 const ImU32 fill_color = ImGui::GetColorU32(fill);
406 const ImU32 border_color = ImGui::GetColorU32(border);
408 const ImVec2 viewport_min = canvas_rt.
canvas_p0;
414 static_cast<float>(rect.x) * canvas_rt.
scale - expand,
416 static_cast<float>(rect.y) * canvas_rt.
scale - expand);
418 min.x +
static_cast<float>(rect.w) * canvas_rt.
scale + expand * 2.0f,
419 min.y +
static_cast<float>(rect.h) * canvas_rt.
scale + expand * 2.0f);
421 const bool visible = max.x >= viewport_min.x && min.x <= viewport_max.x &&
422 max.y >= viewport_min.y && min.y <= viewport_max.y;
424 canvas_rt.
draw_list->AddRectFilled(min, max, fill_color, 2.0f);
425 canvas_rt.
draw_list->AddRect(min, max, border_color, 2.0f, 0,
426 2.0f + 2.0f * remaining);
432 (
static_cast<float>(rect.x) +
static_cast<float>(rect.w) * 0.5f) *
435 (
static_cast<float>(rect.y) +
static_cast<float>(rect.h) * 0.5f) *
437 const float marker_min_x = viewport_min.x + 8.0f;
438 const float marker_min_y = viewport_min.y + 8.0f;
439 const float marker_max_x = std::max(marker_min_x, viewport_max.x - 8.0f);
440 const float marker_max_y = std::max(marker_min_y, viewport_max.y - 8.0f);
441 const ImVec2 clamped(std::clamp(center.x, marker_min_x, marker_max_x),
442 std::clamp(center.y, marker_min_y, marker_max_y));
443 canvas_rt.
draw_list->AddCircleFilled(clamped, 5.0f + 4.0f * remaining,
445 canvas_rt.
draw_list->AddCircle(clamped, 7.0f + 6.0f * remaining,
446 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 PruneConnectedRoomCompositeOutputs()
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)
int connected_composite_prune_frame_
void UpdateRoomCanvasShortcutFocus(bool hovered, bool pointer_pressed, int frame_index)
RoomCompositeOutput primary_composite_output_
void DrawPersistentDebugWindows(int room_id)
zelda3::SpritePreviewResourceCache sprite_preview_resources_
void SetProject(const project::YazeProject *project)
void SyncCanvasConfigFromViewerState()
std::map< int, ConnectedRoomCompositeEntry > connected_composite_outputs_
zelda3::GameData * game_data() const
std::vector< uint16_t > switch_tile_order_
bool object_interaction_enabled_
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 ResetRoomCompositeOutputs()
void DrawCoordinateOverlayHud(int room_id)
void ClearPreviewObject()
bool room_canvas_shortcut_focus_
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_
gfx::Bitmap * PrepareRoomCompositeBitmap(int room_id)
zelda3::RoomLayerManager & GetRoomLayerManager(int room_id)
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
DungeonRoomStore * rooms_
util::LruCache< SpritePreviewKey, CachedSpritePreview > sprite_preview_cache_
bool HasRoomCanvasShortcutFocusForFrame(int frame_index) const
const project::YazeProject * project() const
gui::CanvasTouchHandler touch_handler_
int room_canvas_last_draw_frame_
void ConsumePendingCanvasScroll(const gui::CanvasRuntime &canvas_rt)
void DrawDungeonCanvas(int room_id)
void SyncViewerStateFromCanvasConfig()
std::vector< ObjectRenderCache > object_render_cache_
DungeonRenderingHelpers::TrackCollisionConfig track_collision_config_
void SetRooms(DungeonRoomStore *rooms)
std::vector< ChangePingRect > change_ping_rects_
void InvalidateExternalSpriteResources()
std::map< int, RoomLayerState > room_layer_managers_
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
zelda3::Room * GetIfMaterialized(int room_id)
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
RoomLayerManager - Manages layer visibility and compositing.
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
bool SetContext(std::string_view project_path, std::string_view assets_path, std::string_view hack_name)
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