yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
dungeon_workbench_inspector_helpers.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <filesystem>
5
6#include "absl/strings/str_format.h"
12#include "core/features.h"
14
16
17bool HasEditableRoomObjectSize(std::span<const zelda3::RoomObject> objects,
18 std::span<const size_t> selected_indices) {
19 return std::any_of(selected_indices.begin(), selected_indices.end(),
20 [&](size_t index) {
21 return index < objects.size() &&
22 zelda3::IsRoomObjectResizable(objects[index].id_);
23 });
24}
25
27 uint8_t* requested_size) {
28 if (!requested_size) {
29 return false;
30 }
31 uint8_t size = object.size_;
32 const int axis_step = zelda3::RoomObjectSizeAxisStep(object.id_);
33 if (axis_step > 0) {
34 for (const bool horizontal : {true, false}) {
35 gui::LayoutHelpers::PropertyRow(horizontal ? "Width" : "Height", [&]() {
36 const int shift = horizontal ? 2 : 0;
37 const int current = (size >> shift) & 3;
38 const auto preview = absl::StrFormat(
39 "%d tiles",
40 zelda3::RoomObjectSizeAxisTiles(object.id_, size, horizontal));
41 ImGui::SetNextItemWidth(-1);
42 const bool open = ImGui::BeginCombo(
43 horizontal ? "##SelObjWidth" : "##SelObjHeight", preview.c_str());
44 if (open) {
45 for (int value = 0; value < 4; ++value) {
46 const auto candidate =
47 static_cast<uint8_t>((size & ~(3 << shift)) | (value << shift));
48 const auto label = absl::StrFormat(
50 object.id_, candidate, horizontal));
51 if (ImGui::Selectable(label.c_str(), value == current)) {
52 size = candidate;
53 }
54 {
55 gui::AutoWidgetScope automation_scope("Dungeon/Workbench");
57 "selectable",
58 absl::StrFormat("object_%s_%d",
59 horizontal ? "width" : "height", value));
60 }
61 if (value == current) {
62 ImGui::SetItemDefaultFocus();
63 }
64 }
65 ImGui::EndCombo();
66 }
67 // EndCombo restores the control's item data after the popup window.
68 {
69 gui::AutoWidgetScope automation_scope("Dungeon/Workbench");
71 "combo",
72 horizontal ? "selected_object_width" : "selected_object_height",
73 horizontal ? "Selected object width in tiles"
74 : "Selected object height in tiles");
75 }
76 });
77 }
78 } else {
79 auto& manager = zelda3::CustomObjectManager::Get();
81 ? std::min(manager.GetSubtypeCount(object.id_), 16)
82 : 0;
83 if (variants > 0 && zelda3::IsRoomObjectSizeEditable(object.id_)) {
84 const auto variant_label = [&](int subtype) {
86 object.id_) > 0) {
87 return GetDungeonCustomObjectSlotName(object.id_, subtype);
88 }
89 const auto filename = manager.ResolveFilename(object.id_, subtype);
90 return filename.empty()
91 ? absl::StrFormat("Variant %d (unmapped)", subtype)
92 : std::filesystem::path(filename).stem().string();
93 };
94 gui::LayoutHelpers::PropertyRow("Variant", [&]() {
95 const auto preview = size < variants
96 ? variant_label(size)
97 : absl::StrFormat("Invalid variant %d", size);
98 ImGui::SetNextItemWidth(-1);
99 const bool open = ImGui::BeginCombo("##SelObjVariant", preview.c_str());
100 if (open) {
101 for (int subtype = 0; subtype < variants; ++subtype) {
102 const auto label =
103 absl::StrFormat("%02X %s", subtype, variant_label(subtype));
104 const bool mapped =
105 !manager.ResolveFilename(object.id_, subtype).empty();
106 ImGui::BeginDisabled(!mapped);
107 if (ImGui::Selectable(label.c_str(), size == subtype)) {
108 size = static_cast<uint8_t>(subtype);
109 }
110 {
111 gui::AutoWidgetScope automation_scope("Dungeon/Workbench");
113 "selectable", absl::StrFormat("object_variant_%d", subtype));
114 }
115 ImGui::EndDisabled();
116 }
117 ImGui::EndCombo();
118 }
119 {
120 gui::AutoWidgetScope automation_scope("Dungeon/Workbench");
121 gui::AutoRegisterLastItem("combo", "selected_object_variant",
122 "Selected custom object variant");
123 }
124 });
125 } else {
126 gui::LayoutHelpers::PropertyRow("Size", [&]() {
127 if (!zelda3::IsRoomObjectResizable(object.id_)) {
128 ImGui::TextDisabled("Fixed");
129 return;
130 }
131 if (auto result =
132 gui::InputHexByteEx("##SelObjSize", &size, 0x0F, -1.0f, true);
133 !result.ShouldApply()) {
134 size = object.size_;
135 }
136 });
137 }
138 }
139 *requested_size = size;
140 return size != object.size_;
141}
142
143void DrawInspectorSectionHeader(const char* label) {
144 ImGui::SeparatorText(label);
145}
146
147bool BeginInspectorSection(const char* label, bool default_open) {
148 gui::StyleVarGuard frame_padding_guard(
149 ImGuiStyleVar_FramePadding,
150 ImVec2(ImGui::GetStyle().FramePadding.x,
151 std::max(5.0f, ImGui::GetStyle().FramePadding.y + 1.0f)));
152 return ImGui::CollapsingHeader(
153 label, default_open ? ImGuiTreeNodeFlags_DefaultOpen : 0);
154}
155
156bool DrawActionButton(const char* label, const ImVec2& size) {
157 gui::StyleVarGuard align_guard(ImGuiStyleVar_ButtonTextAlign,
158 ImVec2(0.08f, 0.5f));
159 return ImGui::Button(label, size);
160}
161
162} // namespace yaze::editor::workbench
static Flags & get()
Definition features.h:119
RAII scope that enables automatic widget registration.
static void PropertyRow(const char *label, std::function< void()> widget_callback)
RAII guard for ImGui style vars.
Definition style_guard.h:68
static int RuntimeSubtypeCountForObject(int object_id)
static CustomObjectManager & Get()
bool BeginInspectorSection(const char *label, bool default_open)
bool DrawObjectSizeControls(const zelda3::RoomObject &object, uint8_t *requested_size)
bool DrawActionButton(const char *label, const ImVec2 &size)
bool HasEditableRoomObjectSize(std::span< const zelda3::RoomObject > objects, std::span< const size_t > selected_indices)
std::string GetDungeonCustomObjectSlotName(int object_id, int subtype)
void AutoRegisterLastItem(const std::string &widget_type, const std::string &explicit_label, const std::string &description)
Automatically register the last ImGui item.
InputHexResult InputHexByteEx(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:533
bool IsRoomObjectSizeEditable(int object_id)
int RoomObjectSizeAxisStep(int object_id)
bool IsRoomObjectResizable(int object_id)
int RoomObjectSizeAxisTiles(int object_id, uint8_t size, bool horizontal)
bool ShouldApply() const
Definition input.h:82
Automatic widget registration helpers for ImGui Test Engine integration.