Blender V4.3
spreadsheet_layout.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <iomanip>
6#include <sstream>
7
8#include <fmt/format.h>
9
10#include "BLI_math_matrix.hh"
13
14#include "BKE_geometry_set.hh"
15#include "BKE_instances.hh"
16
19#include "spreadsheet_layout.hh"
20
22#include "DNA_meshdata_types.h"
23#include "DNA_object_types.h"
24#include "DNA_userdef_types.h"
25
26#include "UI_interface.hh"
27#include "UI_resources.hh"
28
29#include "BLT_translation.hh"
30
32
34 private:
35 const SpreadsheetLayout &spreadsheet_layout_;
36
37 public:
38 SpreadsheetLayoutDrawer(const SpreadsheetLayout &spreadsheet_layout)
39 : spreadsheet_layout_(spreadsheet_layout)
40 {
41 tot_columns = spreadsheet_layout.columns.size();
42 tot_rows = spreadsheet_layout.row_indices.size();
43 left_column_width = spreadsheet_layout.index_column_width;
44 }
45
46 void draw_top_row_cell(int column_index, const CellDrawParams &params) const final
47 {
48 const StringRefNull name = spreadsheet_layout_.columns[column_index].values->name();
49 uiBut *but = uiDefIconTextBut(params.block,
51 0,
52 ICON_NONE,
53 name,
54 params.xmin,
55 params.ymin,
56 params.width,
57 params.height,
58 nullptr,
59 0,
60 0,
61 nullptr);
62 /* Center-align column headers. */
65 }
66
67 void draw_left_column_cell(int row_index, const CellDrawParams &params) const final
68 {
69 const int real_index = spreadsheet_layout_.row_indices[row_index];
70 std::string index_str = std::to_string(real_index);
71 uiBut *but = uiDefIconTextBut(params.block,
73 0,
74 ICON_NONE,
75 index_str,
76 params.xmin,
77 params.ymin,
78 params.width,
79 params.height,
80 nullptr,
81 0,
82 0,
83 nullptr);
84 /* Right-align indices. */
87 }
88
89 void draw_content_cell(int row_index, int column_index, const CellDrawParams &params) const final
90 {
91 const int real_index = spreadsheet_layout_.row_indices[row_index];
92 const ColumnValues &column = *spreadsheet_layout_.columns[column_index].values;
93 if (real_index > column.size()) {
94 return;
95 }
96
97 const GVArray &data = column.data();
98
99 if (data.type().is<int>()) {
100 const int value = data.get<int>(real_index);
101 const std::string value_str = std::to_string(value);
102 uiBut *but = uiDefIconTextBut(params.block,
104 0,
105 ICON_NONE,
106 value_str,
107 params.xmin,
108 params.ymin,
109 params.width,
110 params.height,
111 nullptr,
112 0,
113 0,
114 nullptr);
116 but,
117 [](bContext * /*C*/, void *argN, const char * /*tip*/) {
118 return fmt::format(TIP_("{}"), *((int *)argN));
119 },
120 MEM_cnew<int>(__func__, value),
121 MEM_freeN);
122 /* Right-align Integers. */
125 }
126 if (data.type().is<int8_t>()) {
127 const int8_t value = data.get<int8_t>(real_index);
128 const std::string value_str = std::to_string(value);
129 uiBut *but = uiDefIconTextBut(params.block,
131 0,
132 ICON_NONE,
133 value_str,
134 params.xmin,
135 params.ymin,
136 params.width,
137 params.height,
138 nullptr,
139 0,
140 0,
141 nullptr);
142 /* Right-align Integers. */
145 }
146 else if (data.type().is<int2>()) {
147 const int2 value = data.get<int2>(real_index);
148 this->draw_int_vector(params, Span(&value.x, 2));
149 }
150 else if (data.type().is<float>()) {
151 const float value = data.get<float>(real_index);
152 std::stringstream ss;
153 ss << std::fixed << std::setprecision(3) << value;
154 const std::string value_str = ss.str();
155 uiBut *but = uiDefIconTextBut(params.block,
157 0,
158 ICON_NONE,
159 value_str,
160 params.xmin,
161 params.ymin,
162 params.width,
163 params.height,
164 nullptr,
165 0,
166 0,
167 nullptr);
169 but,
170 [](bContext * /*C*/, void *argN, const char * /*tip*/) {
171 return fmt::format(TIP_("{:f}"), *((float *)argN));
172 },
173 MEM_cnew<float>(__func__, value),
174 MEM_freeN);
175 /* Right-align Floats. */
178 }
179 else if (data.type().is<bool>()) {
180 const bool value = data.get<bool>(real_index);
181 const int icon = value ? ICON_CHECKBOX_HLT : ICON_CHECKBOX_DEHLT;
182 uiBut *but = uiDefIconTextBut(params.block,
184 0,
185 icon,
186 "",
187 params.xmin,
188 params.ymin,
189 params.width,
190 params.height,
191 nullptr,
192 0,
193 0,
194 nullptr);
196 }
197 else if (data.type().is<float2>()) {
198 const float2 value = data.get<float2>(real_index);
199 this->draw_float_vector(params, Span(&value.x, 2));
200 }
201 else if (data.type().is<float3>()) {
202 const float3 value = data.get<float3>(real_index);
203 this->draw_float_vector(params, Span(&value.x, 3));
204 }
205 else if (data.type().is<ColorGeometry4f>()) {
206 const ColorGeometry4f value = data.get<ColorGeometry4f>(real_index);
207 this->draw_float_vector(params, Span(&value.r, 4));
208 }
209 else if (data.type().is<ColorGeometry4b>()) {
210 const ColorGeometry4b value = data.get<ColorGeometry4b>(real_index);
211 this->draw_byte_color(params, value);
212 }
213 else if (data.type().is<math::Quaternion>()) {
214 const float4 value = float4(data.get<math::Quaternion>(real_index));
215 this->draw_float_vector(params, Span(&value.x, 4));
216 }
217 else if (data.type().is<float4x4>()) {
218 this->draw_float4x4(params, data.get<float4x4>(real_index));
219 }
220 else if (data.type().is<bke::InstanceReference>()) {
221 const bke::InstanceReference value = data.get<bke::InstanceReference>(real_index);
222 const StringRefNull name = value.name().is_empty() ? IFACE_("(Geometry)") : value.name();
223 const int icon = get_instance_reference_icon(value);
226 0,
227 icon,
228 name.c_str(),
229 params.xmin,
230 params.ymin,
231 params.width,
232 params.height,
233 nullptr,
234 0,
235 0,
236 nullptr);
237 }
238 else if (data.type().is<std::string>()) {
241 0,
242 ICON_NONE,
243 data.get<std::string>(real_index),
244 params.xmin,
245 params.ymin,
246 params.width,
247 params.height,
248 nullptr,
249 0,
250 0,
251 nullptr);
252 }
253 else if (data.type().is<MStringProperty>()) {
254 MStringProperty *prop = MEM_cnew<MStringProperty>(__func__);
255 data.get_to_uninitialized(real_index, prop);
256 uiBut *but = uiDefIconTextBut(params.block,
258 0,
259 ICON_NONE,
260 StringRef(prop->s, prop->s_len),
261 params.xmin,
262 params.ymin,
263 params.width,
264 params.height,
265 nullptr,
266 0,
267 0,
268 nullptr);
269
271 but,
272 [](bContext * /*C*/, void *argN, const char * /*tip*/) {
273 const MStringProperty &prop = *static_cast<MStringProperty *>(argN);
274 return std::string(StringRef(prop.s, prop.s_len));
275 },
276 prop,
277 MEM_freeN);
278 }
279 }
280
281 void draw_float_vector(const CellDrawParams &params, const Span<float> values) const
282 {
283 BLI_assert(!values.is_empty());
284 const float segment_width = float(params.width) / values.size();
285 for (const int i : values.index_range()) {
286 std::stringstream ss;
287 const float value = values[i];
288 ss << " " << std::fixed << std::setprecision(3) << value;
289 const std::string value_str = ss.str();
290 uiBut *but = uiDefIconTextBut(params.block,
292 0,
293 ICON_NONE,
294 value_str,
295 params.xmin + i * segment_width,
296 params.ymin,
297 segment_width,
298 params.height,
299 nullptr,
300 0,
301 0,
302 nullptr);
303
305 but,
306 [](bContext * /*C*/, void *argN, const char * /*tip*/) {
307 return fmt::format(TIP_("{:f}"), *((float *)argN));
308 },
309 MEM_cnew<float>(__func__, value),
310 MEM_freeN);
311 /* Right-align Floats. */
314 }
315 }
316
317 void draw_int_vector(const CellDrawParams &params, const Span<int> values) const
318 {
319 BLI_assert(!values.is_empty());
320 const float segment_width = float(params.width) / values.size();
321 for (const int i : values.index_range()) {
322 std::stringstream ss;
323 const int value = values[i];
324 ss << " " << value;
325 const std::string value_str = ss.str();
326 uiBut *but = uiDefIconTextBut(params.block,
328 0,
329 ICON_NONE,
330 value_str,
331 params.xmin + i * segment_width,
332 params.ymin,
333 segment_width,
334 params.height,
335 nullptr,
336 0,
337 0,
338 nullptr);
340 but,
341 [](bContext * /*C*/, void *argN, const char * /*tip*/) {
342 return fmt::format(TIP_("{}"), *((int *)argN));
343 },
344 MEM_cnew<int>(__func__, value),
345 MEM_freeN);
346 /* Right-align Floats. */
349 }
350 }
351
352 void draw_byte_color(const CellDrawParams &params, const ColorGeometry4b color) const
353 {
354 const ColorGeometry4f float_color = color.decode();
355 Span<float> values(&float_color.r, 4);
356 const float segment_width = float(params.width) / values.size();
357 for (const int i : values.index_range()) {
358 std::stringstream ss;
359 const float value = values[i];
360 ss << " " << std::fixed << std::setprecision(3) << value;
361 const std::string value_str = ss.str();
362 uiBut *but = uiDefIconTextBut(params.block,
364 0,
365 ICON_NONE,
366 value_str,
367 params.xmin + i * segment_width,
368 params.ymin,
369 segment_width,
370 params.height,
371 nullptr,
372 0,
373 0,
374 nullptr);
375 /* Right-align Floats. */
378
379 /* Tooltip showing raw byte values. Encode values in pointer to avoid memory allocation. */
381 but,
382 [](bContext * /*C*/, void *argN, const char * /*tip*/) {
383 const uint32_t uint_color = POINTER_AS_UINT(argN);
384 ColorGeometry4b color = *(ColorGeometry4b *)&uint_color;
385 return fmt::format(TIP_("Byte Color (sRGB encoded):\n{} {} {} {}"),
386 color.r,
387 color.g,
388 color.b,
389 color.a);
390 },
391 POINTER_FROM_UINT(*(uint32_t *)&color),
392 nullptr);
393 }
394 }
395
396 void draw_float4x4(const CellDrawParams &params, const float4x4 &value) const
397 {
398 uiBut *but = uiDefIconTextBut(params.block,
400 0,
401 ICON_NONE,
402 "...",
403 params.xmin,
404 params.ymin,
405 params.width,
406 params.height,
407 nullptr,
408 0,
409 0,
410 nullptr);
411 /* Center alignment. */
414 but,
415 [](bContext * /*C*/, void *argN, const char * /*tip*/) {
416 /* Transpose to be able to print row by row. */
417 const float4x4 value = math::transpose(*static_cast<const float4x4 *>(argN));
418 std::stringstream ss;
419 ss << value[0] << ",\n";
420 ss << value[1] << ",\n";
421 ss << value[2] << ",\n";
422 ss << value[3];
423 return ss.str();
424 },
425 MEM_cnew<float4x4>(__func__, value),
426 MEM_freeN);
427 }
428
429 int column_width(int column_index) const final
430 {
431 return spreadsheet_layout_.columns[column_index].width;
432 }
433};
434
435std::unique_ptr<SpreadsheetDrawer> spreadsheet_drawer_from_layout(
436 const SpreadsheetLayout &spreadsheet_layout)
437{
438 return std::make_unique<SpreadsheetLayoutDrawer>(spreadsheet_layout);
439}
440
441} // namespace blender::ed::spreadsheet
#define BLI_assert(a)
Definition BLI_assert.h:50
#define POINTER_AS_UINT(i)
#define POINTER_FROM_UINT(i)
#define TIP_(msgid)
#define IFACE_(msgid)
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFreeArgFunc free_arg)
void UI_but_drawflag_enable(uiBut *but, int flag)
uiBut * uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, const char *tip)
void UI_but_drawflag_disable(uiBut *but, int flag)
@ UI_BTYPE_LABEL
@ UI_BUT_TEXT_RIGHT
@ UI_BUT_ICON_LEFT
@ UI_BUT_TEXT_LEFT
ChannelStorageType r
Definition BLI_color.hh:88
void get(int64_t index, void *r_value) const
constexpr bool is_empty() const
void draw_top_row_cell(int column_index, const CellDrawParams &params) const final
void draw_byte_color(const CellDrawParams &params, const ColorGeometry4b color) const
void draw_left_column_cell(int row_index, const CellDrawParams &params) const final
void draw_int_vector(const CellDrawParams &params, const Span< int > values) const
void draw_content_cell(int row_index, int column_index, const CellDrawParams &params) const final
void draw_float_vector(const CellDrawParams &params, const Span< float > values) const
void draw_float4x4(const CellDrawParams &params, const float4x4 &value) const
SpreadsheetLayoutDrawer(const SpreadsheetLayout &spreadsheet_layout)
draw_view in_light_buf[] float
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
int get_instance_reference_icon(const bke::InstanceReference &reference)
std::unique_ptr< SpreadsheetDrawer > spreadsheet_drawer_from_layout(const SpreadsheetLayout &spreadsheet_layout)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
VecBase< float, 4 > float4
unsigned int uint32_t
Definition stdint.h:80
signed char int8_t
Definition stdint.h:75