7#include "absl/status/status.h"
8#include "absl/strings/str_format.h"
18#include "imgui/imgui.h"
26 int canvas_x,
int canvas_y) {
28 std::string info_text;
29 if (
object.id_ >= 0x100) {
31 absl::StrFormat(
"0x%03X %s (X:%d Y:%d S:0x%02X)",
object.id_,
32 name.c_str(),
object.x_,
object.y_,
object.size_);
35 absl::StrFormat(
"0x%02X %s (X:%d Y:%d S:0x%02X)",
object.id_,
36 name.c_str(),
object.x_,
object.y_,
object.size_);
43 LOG_DEBUG(
"[LoadAndRender]",
"START room_id=%d", room_id);
46 LOG_DEBUG(
"[LoadAndRender]",
"ERROR: Invalid room ID");
47 return absl::InvalidArgumentError(
"Invalid room ID");
51 LOG_DEBUG(
"[LoadAndRender]",
"ERROR: ROM not loaded");
52 return absl::FailedPreconditionError(
"ROM not loaded");
56 LOG_DEBUG(
"[LoadAndRender]",
"ERROR: Room data not available");
57 return absl::FailedPreconditionError(
"Room data not available");
62 LOG_DEBUG(
"[LoadAndRender]",
"ERROR: Room data unavailable");
63 return absl::InvalidArgumentError(
"Invalid room ID");
65 auto& room = *room_ptr;
66 LOG_DEBUG(
"[LoadAndRender]",
"Got room reference");
69 LOG_ERROR(
"[LoadAndRender]",
"GameData not available");
70 return absl::FailedPreconditionError(
"GameData not available");
73 if (!dungeon_main.empty()) {
75 static_cast<uint64_t
>(room.ResolveDungeonPaletteId());
80 LOG_DEBUG(
"[LoadAndRender]",
"Palette loaded: group_id=%zu",
84 LOG_DEBUG(
"[LoadAndRender]",
"Calling room.RenderRoomGraphics()...");
87 "RenderRoomGraphics() complete - room buffers self-contained");
90 return absl::OkStatus();
96 ImGui::BeginDisabled();
99 constexpr ImGuiTableFlags kPropsTableFlags =
100 ImGuiTableFlags_NoPadOuterX | ImGuiTableFlags_NoBordersInBody;
102 if (ImGui::BeginTable(
"##RoomPropsTable", 2, kPropsTableFlags)) {
103 const float nav_col_width = (ImGui::GetFrameHeight() * 4.0f) +
104 (ImGui::GetStyle().ItemSpacing.x * 3.0f) +
105 (ImGui::GetStyle().FramePadding.x * 2.0f);
106 ImGui::TableSetupColumn(
"NavCol", ImGuiTableColumnFlags_WidthFixed,
108 ImGui::TableSetupColumn(
"PropsCol", ImGuiTableColumnFlags_WidthStretch);
110 ImGui::TableNextRow();
111 ImGui::TableNextColumn();
113 ImGui::TableNextColumn();
117 ImGui::TableNextRow();
118 ImGui::TableNextColumn();
120 ImGui::TableNextColumn();
128 ImGui::EndDisabled();
137 auto room_if_valid = [](
int candidate) -> std::optional<int> {
153 auto make_tooltip = [&](
const std::optional<int>& target,
154 const char* direction) -> std::string {
155 if (!target.has_value()) {
158 return absl::StrFormat(
159 "%s: [%03X] %s", direction, *target,
163 auto nav_button = [&](
const char* id, ImGuiDir dir,
164 const std::optional<int>& target,
165 const std::string& tooltip) {
166 const bool enabled = target.has_value();
168 ImGui::BeginDisabled();
170 const bool pressed = ImGui::ArrowButton(
id, dir);
172 ImGui::EndDisabled();
174 if (enabled && ImGui::IsItemHovered() && !tooltip.empty()) {
175 ImGui::SetTooltip(
"%s", tooltip.c_str());
177 if (pressed && enabled) {
186 ImGui::PushID(room_id);
188 nav_button(
"##RoomNavWest", ImGuiDir_Left, west, make_tooltip(west,
"West"));
190 nav_button(
"##RoomNavNorth", ImGuiDir_Up, north,
191 make_tooltip(north,
"North"));
193 nav_button(
"##RoomNavSouth", ImGuiDir_Down, south,
194 make_tooltip(south,
"South"));
196 nav_button(
"##RoomNavEast", ImGuiDir_Right, east, make_tooltip(east,
"East"));
203 ImGui::AlignTextToFramePadding();
206 ImGui::SameLine(0, 6);
210 if (ImGui::IsItemHovered()) {
211 ImGui::SetTooltip(tr(
212 "Room changes are pending in the editor. Apply Room writes them to "
213 "the loaded ROM buffer."));
235 auto hex_input = [&](
const char* label,
const char* icon, uint8_t* val,
236 uint8_t max,
const char* tooltip) {
237 ImGui::TextDisabled(
"%s", icon);
238 ImGui::SameLine(0, 2);
240 const std::string anim_id = std::string(label) +
"_Flash";
242 "##RoomProps", anim_id, ImVec4(0, 0, 0, 0), 8.0f);
244 if (flash_color.w > 0.01f) {
245 ImGui::PushStyleColor(ImGuiCol_FrameBg, flash_color);
249 const bool changed = res.ShouldApply();
251 if (flash_color.w > 0.01f) {
252 ImGui::PopStyleColor();
260 if (ImGui::IsItemHovered()) {
261 ImGui::SetTooltip(
"%s", tooltip);
269 if (room.
rom() && room.
rom()->is_loaded()) {
273 ImGui::SameLine(0, 2);
280 if (room.
rom() && room.
rom()->is_loaded()) {
290 if (room.
rom() && room.
rom()->is_loaded()) {
299 if (room.
rom() && room.
rom()->is_loaded()) {
305 ImGui::TextDisabled(tr(
"Floor: %d | Effect: %d | Tag1: %d | Tag2: %d"),
315 ImGui::PushID(
"RecentRooms");
317 if (ImGui::IsItemHovered()) {
318 ImGui::SetTooltip(tr(
"Recently visited rooms"));
323 if (recent_room == room_id) {
326 ImGui::SameLine(0, 3);
327 const std::string button_label =
328 absl::StrFormat(
"%03X##RecentRoom%d", recent_room, rendered);
329 if (ImGui::SmallButton(button_label.c_str())) {
333 if (ImGui::IsItemHovered()) {
335 "[%03X] %s", recent_room,
352 const float compact_gap =
354 const float compact_padding =
358 {ImGuiStyleVar_FramePadding,
359 ImVec2(compact_padding, compact_padding * 0.5f)},
360 {ImGuiStyleVar_ItemSpacing, ImVec2(compact_gap, 0.0f)},
363 auto as_button_color = [](ImVec4 color,
float alpha) {
368 const ImVec4 inactive_color =
370 const ImVec4 inactive_hover =
372 const ImVec4 inactive_active =
375 auto draw_toggle = [&](
const char* label,
bool enabled, ImVec4 active_color,
376 const char* tooltip,
auto&& on_toggle) {
377 const ImVec4 button = enabled ? active_color : inactive_color;
378 const ImVec4 hovered =
379 enabled ? as_button_color(
382 const ImVec4 pressed =
383 enabled ? as_button_color(
388 {ImGuiCol_Button, button},
389 {ImGuiCol_ButtonHovered, hovered},
390 {ImGuiCol_ButtonActive, pressed},
393 if (ImGui::SmallButton(label)) {
396 if (ImGui::IsItemHovered()) {
397 ImGui::SetTooltip(
"%s", tooltip);
402 draw_toggle(
"BG1##LayerToggleBG1", bg1_visible,
404 "Toggle BG1 (main layer) visibility",
405 [&]() { SetBG1Visible(room_id, !bg1_visible); });
409 draw_toggle(
"BG2##LayerToggleBG2", bg2_visible,
411 "Toggle BG2 (overlay layer) visibility",
412 [&]() { SetBG2Visible(room_id, !bg2_visible); });
418 "Toggle sprite visibility", [&]() {
419 entity_visibility_.show_sprites =
420 !entity_visibility_.show_sprites;
426 "Toggle grid overlay", [&]() { show_grid_ = !show_grid_; });
432 "Toggle object bounds overlay",
433 [&]() { show_object_bounds_ = !show_object_bounds_; });
439 "Toggle pot item markers", [&]() {
440 entity_visibility_.show_pot_items =
441 !entity_visibility_.show_pot_items;
448 "Toggle custom collision overlay", [&]() {
449 show_custom_collision_overlay_ =
450 !show_custom_collision_overlay_;
459 int current_filter = interaction.GetLayerFilter();
461 auto radio = [&](
const char* label,
int filter) {
462 if (ImGui::RadioButton(label, current_filter == filter)) {
463 interaction.SetLayerFilter(filter);
std::vector< int > recently_visited_rooms_
zelda3::GameData * game_data_
void DrawRecentRoomBreadcrumbs(int room_id)
absl::Status LoadAndRenderRoomGraphics(int room_id)
void DrawRoomNavigation(int room_id)
bool IsBG1Visible(int room_id) const
bool show_custom_collision_overlay_
bool compact_header_mode_
DungeonObjectInteraction object_interaction_
const project::YazeProject * project_
void DrawCompactLayerToggles(int room_id)
std::function< void(bool)> pin_callback_
void DrawLayerControls(zelda3::Room &room, int room_id)
zelda3::RoomLayerManager & GetRoomLayerManager(int room_id)
uint8_t current_entrance_blockset_
gfx::PaletteGroup current_palette_group_
bool CanNavigateRooms() const
uint64_t current_palette_group_id_
DungeonRoomStore * rooms_
EntityVisibility entity_visibility_
void NavigateToRoom(int target_room)
bool IsBG2Visible(int room_id) const
void DrawRoomHeader(zelda3::Room &room, int room_id)
std::function< void(int)> room_navigation_callback_
void DisplayObjectInfo(const gui::CanvasRuntime &rt, const zelda3::RoomObject &object, int canvas_x, int canvas_y)
std::function< void(int, int)> room_swap_callback_
void DrawRoomPropertyTable(zelda3::Room &room, int room_id)
void SetLayersMerged(bool merged)
static const char * GetBlocksetGroupName(uint8_t blockset)
zelda3::Room * TryEnsureRoom(int room_id)
static constexpr int kLayer3
static constexpr int kLayer1
static constexpr int kLayer2
static constexpr int kLayerAll
ImVec4 AnimateColor(const std::string &panel_id, const std::string &anim_id, ImVec4 target, float speed=5.0f)
static float GetButtonPadding()
static float GetStandardSpacing()
RAII guard for ImGui style colors.
RAII guard for ImGui style vars.
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
bool HasUnsavedChanges() const
void SetLayoutId(uint8_t id)
void RenderRoomGraphics()
uint8_t spriteset() const
void SetSpriteset(uint8_t ss)
void SetBlockset(uint8_t bs)
void SetPalette(uint8_t pal)
uint8_t layout_id() const
#define ICON_MD_GRID_VIEW
#define ICON_MD_VIEW_MODULE
#define ICON_MD_FILTER_CENTER_FOCUS
#define ICON_MD_EXPAND_LESS
#define ICON_MD_PEST_CONTROL
#define ICON_MD_SELECT_ALL
#define ICON_MD_INVENTORY_2
#define ICON_MD_CROP_FREE
#define ICON_MD_EXPAND_MORE
#define LOG_DEBUG(category, format,...)
#define LOG_ERROR(category, format,...)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
std::string GetRoomLabel(const project::YazeProject *project, int room_id)
Editors are the view controllers for the application.
int NeighborRoomId(int room_id, zelda3::DoorDirection dir)
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromLargePalette(SnesPalette &palette, int num_colors)
Create a PaletteGroup by dividing a large palette into sub-palettes.
bool ThemedIconButton(const char *icon, const char *tooltip, const ImVec2 &size, bool is_active, bool is_disabled, const char *panel_id, const char *anim_id)
Draw a standard icon button with theme-aware colors.
ImVec4 ConvertColorToImVec4(const Color &color)
void ValueChangeFlash(bool changed, const char *id)
Provide visual "flash" feedback when a value changes.
void DrawText(const CanvasRuntime &rt, const std::string &text, int x, int y)
InputHexResult InputHexByteEx(const char *label, uint8_t *data, float input_width, bool no_step)
std::string GetObjectName(int object_id)
constexpr int kNumberOfRooms
@ South
Bottom wall (horizontal door, 4x3 tiles)
@ North
Top wall (horizontal door, 4x3 tiles)
@ East
Right wall (vertical door, 3x4 tiles)
@ West
Left wall (vertical door, 3x4 tiles)
PaletteGroup dungeon_main
gfx::PaletteGroupMap palette_groups