yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
property_inspector.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <cstdio>
5#include <cstring>
6#include <string>
7
9#include "imgui/imgui.h"
10#include "imgui/imgui_internal.h"
11
12namespace yaze {
13namespace gui {
14namespace property_inspector_internal {
15
17 ImGuiContext* ctx = ImGui::GetCurrentContext();
18 return ctx != nullptr && ctx->CurrentTable != nullptr;
19}
20
21void BeginRow(const char* label, const char* tooltip) {
22 if (!IsInPropertyTable()) {
23 return;
24 }
25 ImGui::TableNextColumn();
26 ImGui::AlignTextToFramePadding();
27 ImGui::TextUnformatted(label);
28 if (tooltip && tooltip[0] != '\0' && ImGui::IsItemHovered()) {
29 ImGui::SetTooltip("%s", tooltip);
30 }
31 ImGui::TableNextColumn();
32 ImGui::SetNextItemWidth(-FLT_MIN);
33}
34
35std::string ResolveWidgetId(const char* label) {
36 std::string result;
37 if (IsInPropertyTable()) {
38 result.reserve(std::strlen(label) + 2);
39 result.append("##").append(label);
40 } else {
41 result.assign(label);
42 }
43 return result;
44}
45
46} // namespace property_inspector_internal
47
48namespace {
49
50namespace pi = property_inspector_internal;
51
52template <typename T>
53void ClampIfBounded(T* value, const PropertyOptions& opts) {
54 if (opts.max > opts.min) {
55 const T lo = static_cast<T>(opts.min);
56 const T hi = static_cast<T>(opts.max);
57 if (*value < lo)
58 *value = lo;
59 if (*value > hi)
60 *value = hi;
61 }
62}
63
64const char* IntFormat(const PropertyOptions& opts) {
65 return opts.format ? opts.format : "%d";
66}
67
68const char* FloatFormat(const PropertyOptions& opts, const char* fallback) {
69 return opts.format ? opts.format : fallback;
70}
71
72} // namespace
73
74bool DrawProperty(const char* label, bool* value, const PropertyOptions& opts) {
75 pi::BeginRow(label, opts.tooltip);
76 const std::string id = pi::ResolveWidgetId(label);
77 ImGui::BeginDisabled(opts.read_only);
78 const bool changed = ImGui::Checkbox(id.c_str(), value);
79 ImGui::EndDisabled();
80 return changed && !opts.read_only;
81}
82
83bool DrawProperty(const char* label, int* value, const PropertyOptions& opts) {
84 pi::BeginRow(label, opts.tooltip);
85 const std::string id = pi::ResolveWidgetId(label);
86 const int step = static_cast<int>(opts.step);
87 const int step_fast = static_cast<int>(opts.step_fast);
88 ImGui::BeginDisabled(opts.read_only);
89 const bool changed =
90 ImGui::InputInt(id.c_str(), value, step, step_fast, opts.text_flags);
91 ImGui::EndDisabled();
92 if (changed && !opts.read_only)
93 ClampIfBounded(value, opts);
94 return changed && !opts.read_only;
95}
96
97bool DrawProperty(const char* label, std::uint8_t* value,
98 const PropertyOptions& opts) {
99 pi::BeginRow(label, opts.tooltip);
100 const std::string id = pi::ResolveWidgetId(label);
101 const std::uint8_t step = static_cast<std::uint8_t>(opts.step);
102 const std::uint8_t step_fast = static_cast<std::uint8_t>(opts.step_fast);
103 ImGui::BeginDisabled(opts.read_only);
104 const bool changed = ImGui::InputScalar(
105 id.c_str(), ImGuiDataType_U8, value, step ? &step : nullptr,
106 step_fast ? &step_fast : nullptr, IntFormat(opts), opts.text_flags);
107 ImGui::EndDisabled();
108 if (changed && !opts.read_only)
109 ClampIfBounded(value, opts);
110 return changed && !opts.read_only;
111}
112
113bool DrawProperty(const char* label, std::uint16_t* value,
114 const PropertyOptions& opts) {
115 pi::BeginRow(label, opts.tooltip);
116 const std::string id = pi::ResolveWidgetId(label);
117 const std::uint16_t step = static_cast<std::uint16_t>(opts.step);
118 const std::uint16_t step_fast = static_cast<std::uint16_t>(opts.step_fast);
119 ImGui::BeginDisabled(opts.read_only);
120 const bool changed = ImGui::InputScalar(
121 id.c_str(), ImGuiDataType_U16, value, step ? &step : nullptr,
122 step_fast ? &step_fast : nullptr, IntFormat(opts), opts.text_flags);
123 ImGui::EndDisabled();
124 if (changed && !opts.read_only)
125 ClampIfBounded(value, opts);
126 return changed && !opts.read_only;
127}
128
129bool DrawProperty(const char* label, std::uint32_t* value,
130 const PropertyOptions& opts) {
131 pi::BeginRow(label, opts.tooltip);
132 const std::string id = pi::ResolveWidgetId(label);
133 const std::uint32_t step = static_cast<std::uint32_t>(opts.step);
134 const std::uint32_t step_fast = static_cast<std::uint32_t>(opts.step_fast);
135 ImGui::BeginDisabled(opts.read_only);
136 const bool changed = ImGui::InputScalar(
137 id.c_str(), ImGuiDataType_U32, value, step ? &step : nullptr,
138 step_fast ? &step_fast : nullptr, IntFormat(opts), opts.text_flags);
139 ImGui::EndDisabled();
140 if (changed && !opts.read_only)
141 ClampIfBounded(value, opts);
142 return changed && !opts.read_only;
143}
144
145bool DrawProperty(const char* label, float* value,
146 const PropertyOptions& opts) {
147 pi::BeginRow(label, opts.tooltip);
148 const std::string id = pi::ResolveWidgetId(label);
149 const float step = static_cast<float>(opts.step > 0 ? opts.step : 0.0);
150 const float step_fast =
151 static_cast<float>(opts.step_fast > 0 ? opts.step_fast : 0.0);
152 ImGui::BeginDisabled(opts.read_only);
153 const bool changed =
154 ImGui::InputFloat(id.c_str(), value, step, step_fast,
155 FloatFormat(opts, "%.3f"), opts.text_flags);
156 ImGui::EndDisabled();
157 if (changed && !opts.read_only)
158 ClampIfBounded(value, opts);
159 return changed && !opts.read_only;
160}
161
162bool DrawProperty(const char* label, double* value,
163 const PropertyOptions& opts) {
164 pi::BeginRow(label, opts.tooltip);
165 const std::string id = pi::ResolveWidgetId(label);
166 const double step = opts.step > 0 ? opts.step : 0.0;
167 const double step_fast = opts.step_fast > 0 ? opts.step_fast : 0.0;
168 ImGui::BeginDisabled(opts.read_only);
169 const bool changed =
170 ImGui::InputDouble(id.c_str(), value, step, step_fast,
171 FloatFormat(opts, "%.6f"), opts.text_flags);
172 ImGui::EndDisabled();
173 if (changed && !opts.read_only)
174 ClampIfBounded(value, opts);
175 return changed && !opts.read_only;
176}
177
178namespace {
179
180int StringInputCallback(ImGuiInputTextCallbackData* data) {
181 if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
182 auto* str = static_cast<std::string*>(data->UserData);
183 str->resize(static_cast<std::size_t>(data->BufTextLen));
184 data->Buf = str->data();
185 }
186 return 0;
187}
188
189} // namespace
190
191bool DrawProperty(const char* label, std::string* value,
192 const PropertyOptions& opts) {
193 pi::BeginRow(label, opts.tooltip);
194 const std::string id = pi::ResolveWidgetId(label);
195 ImGui::BeginDisabled(opts.read_only);
196 // Ensure capacity for in-place edits; callback grows the string as needed.
197 if (value->capacity() < value->size() + 1) {
198 value->reserve(value->size() + 32);
199 }
200 const bool changed =
201 ImGui::InputText(id.c_str(), value->data(), value->capacity() + 1,
202 opts.text_flags | ImGuiInputTextFlags_CallbackResize,
203 &StringInputCallback, value);
204 ImGui::EndDisabled();
205 return changed && !opts.read_only;
206}
207
208bool DrawProperty(const char* label, ImVec4* value,
209 const PropertyOptions& opts) {
210 pi::BeginRow(label, opts.tooltip);
211 const std::string id = pi::ResolveWidgetId(label);
212 ImGui::BeginDisabled(opts.read_only);
213 const bool changed = ImGui::ColorEdit4(id.c_str(), &value->x);
214 ImGui::EndDisabled();
215 return changed && !opts.read_only;
216}
217
218bool DrawProperty(const char* label, Color* value,
219 const PropertyOptions& opts) {
220 pi::BeginRow(label, opts.tooltip);
221 const std::string id = pi::ResolveWidgetId(label);
222 float rgba[4] = {value->red, value->green, value->blue, value->alpha};
223 ImGui::BeginDisabled(opts.read_only);
224 const bool changed = ImGui::ColorEdit4(id.c_str(), rgba);
225 ImGui::EndDisabled();
226 if (changed && !opts.read_only) {
227 value->red = rgba[0];
228 value->green = rgba[1];
229 value->blue = rgba[2];
230 value->alpha = rgba[3];
231 }
232 return changed && !opts.read_only;
233}
234
235namespace {
236
237template <typename T>
238bool DrawHexScalar(const char* label, T* value, ImGuiDataType type,
239 const char* default_fmt, const PropertyOptions& opts) {
240 pi::BeginRow(label, opts.tooltip);
241 const std::string id = pi::ResolveWidgetId(label);
242 const char* fmt = opts.format ? opts.format : default_fmt;
243 const T step = static_cast<T>(opts.step);
244 const T step_fast = static_cast<T>(opts.step_fast);
245 ImGui::BeginDisabled(opts.read_only);
246 const bool changed = ImGui::InputScalar(
247 id.c_str(), type, value, step ? &step : nullptr,
248 step_fast ? &step_fast : nullptr, fmt,
249 opts.text_flags | ImGuiInputTextFlags_CharsHexadecimal |
250 ImGuiInputTextFlags_CharsUppercase);
251 ImGui::EndDisabled();
252 if (changed && !opts.read_only)
253 ClampIfBounded(value, opts);
254 return changed && !opts.read_only;
255}
256
257} // namespace
258
259bool DrawPropertyHex(const char* label, std::uint8_t* value,
260 const PropertyOptions& opts) {
261 return DrawHexScalar(label, value, ImGuiDataType_U8, "%02X", opts);
262}
263
264bool DrawPropertyHex(const char* label, std::uint16_t* value,
265 const PropertyOptions& opts) {
266 return DrawHexScalar(label, value, ImGuiDataType_U16, "%04X", opts);
267}
268
269bool DrawPropertyHex(const char* label, std::uint32_t* value,
270 const PropertyOptions& opts) {
271 return DrawHexScalar(label, value, ImGuiDataType_U32, "%08X", opts);
272}
273
274} // namespace gui
275} // namespace yaze
const char * IntFormat(const PropertyOptions &opts)
const char * FloatFormat(const PropertyOptions &opts, const char *fallback)
int StringInputCallback(ImGuiInputTextCallbackData *data)
void ClampIfBounded(T *value, const PropertyOptions &opts)
bool DrawHexScalar(const char *label, T *value, ImGuiDataType type, const char *default_fmt, const PropertyOptions &opts)
void BeginRow(const char *label, const char *tooltip)
std::string ResolveWidgetId(const char *label)
bool DrawProperty(const char *label, bool *value, const PropertyOptions &opts)
bool DrawPropertyHex(const char *label, std::uint8_t *value, const PropertyOptions &opts)
float alpha
Definition color.h:20
float green
Definition color.h:18
ImGuiInputTextFlags text_flags