Blender V5.0
MOD_multires.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstddef>
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_utildefines.h"
14
15#include "BLT_translation.hh"
16
17#include "DNA_defaults.h"
18#include "DNA_mesh_types.h"
19#include "DNA_object_types.h"
20#include "DNA_screen_types.h"
21
22#include "BKE_context.hh"
23#include "BKE_customdata.hh"
24#include "BKE_mesh.hh"
25#include "BKE_modifier.hh"
26#include "BKE_multires.hh"
27#include "BKE_paint.hh"
28#include "BKE_subdiv.hh"
29#include "BKE_subdiv_ccg.hh"
30#include "BKE_subdiv_deform.hh"
31#include "BKE_subdiv_mesh.hh"
32
33#include "UI_interface.hh"
35#include "UI_resources.hh"
36
37#include "RNA_access.hh"
38#include "RNA_prototypes.hh"
39
40#include "WM_types.hh" /* For subdivide operator UI. */
41
43
44#include "MOD_ui_common.hh"
45
47 /* Cached subdivision surface descriptor, with topology and settings. */
49};
50
51static void init_data(ModifierData *md)
52{
54
56
58
59 /* Open subdivision panels by default. */
61}
62
63static void copy_data(const ModifierData *md_src, ModifierData *md_dst, const int flag)
64{
65 BKE_modifier_copydata_generic(md_src, md_dst, flag);
66}
67
68static void free_runtime_data(void *runtime_data_v)
69{
70 if (runtime_data_v == nullptr) {
71 return;
72 }
73 MultiresRuntimeData *runtime_data = (MultiresRuntimeData *)runtime_data_v;
74 if (runtime_data->subdiv != nullptr) {
76 }
77 MEM_freeN(runtime_data);
78}
79
85
87{
89 if (runtime_data == nullptr) {
90 runtime_data = MEM_callocN<MultiresRuntimeData>(__func__);
91 mmd->modifier.runtime = runtime_data;
92 }
93 return runtime_data;
94}
95
96/* Main goal of this function is to give usable subdivision surface descriptor
97 * which matches settings and topology. */
100 const blender::bke::subdiv::Settings *subdiv_settings,
101 const Mesh *mesh)
102{
105 runtime_data->subdiv, subdiv_settings, mesh);
106 runtime_data->subdiv = subdiv;
107 return subdiv;
108}
109
110/* Subdivide into fully qualified mesh. */
111
113 const ModifierEvalContext *ctx,
114 Mesh *mesh,
116{
117 Mesh *result = mesh;
118 const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
119 const bool ignore_simplify = (ctx->flag & MOD_APPLY_IGNORE_SIMPLIFY);
120 const bool ignore_control_edges = (ctx->flag & MOD_APPLY_TO_ORIGINAL);
121 const Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
122 Object *object = ctx->object;
125 scene,
126 object,
127 mmd,
128 use_render_params,
129 ignore_simplify,
130 ignore_control_edges);
131 if (mesh_settings.resolution < 3) {
132 return result;
133 }
135 result = blender::bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, mesh);
136 return result;
137}
138
139/* Subdivide into CCG. */
140
142 const MultiresModifierData *mmd,
143 const ModifierEvalContext *ctx,
144 Mesh *mesh)
145{
146 const bool has_mask = CustomData_has_layer(&mesh->corner_data, CD_GRID_PAINT_MASK);
147 const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
148 const bool ignore_simplify = (ctx->flag & MOD_APPLY_IGNORE_SIMPLIFY);
149 const Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
150 Object *object = ctx->object;
151 const int level = multires_get_level(scene, object, mmd, use_render_params, ignore_simplify);
152 settings->resolution = (1 << level) + 1;
153 settings->need_normal = true;
154 settings->need_mask = has_mask;
155}
156
158 const ModifierEvalContext *ctx,
159 Mesh *mesh,
161{
162 Mesh *result = mesh;
163 SubdivToCCGSettings ccg_settings;
164 multires_ccg_settings_init(&ccg_settings, mmd, ctx, mesh);
165 if (ccg_settings.resolution < 3) {
166 return result;
167 }
169 result = BKE_subdiv_to_ccg_mesh(*subdiv, ccg_settings, *mesh);
170
171 /* NOTE: CCG becomes an owner of Subdiv descriptor, so can not share
172 * this pointer. Not sure if it's needed, but might have a second look
173 * on the ownership model here. */
174 MultiresRuntimeData *runtime_data = static_cast<MultiresRuntimeData *>(mmd->modifier.runtime);
175 runtime_data->subdiv = nullptr;
176
177 return result;
178}
179
180static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
181{
182 using namespace blender;
183 Mesh *result = mesh;
184#if !defined(WITH_OPENSUBDIV)
185 BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv");
186 return result;
187#endif
189 blender::bke::subdiv::Settings subdiv_settings;
190 BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
191 if (subdiv_settings.level == 0) {
192 return result;
193 }
194 MultiresRuntimeData *runtime_data = multires_ensure_runtime(mmd);
195 blender::bke::subdiv::Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh);
196 if (subdiv == nullptr) {
197 /* Happens on bad topology, also on empty input mesh. */
198 return result;
199 }
200 const bool use_clnors = mmd->flags & eMultiresModifierFlag_UseCustomNormals &&
201 mesh->normals_domain() == blender::bke::MeshNormalDomain::Corner;
202 /* NOTE: Orco needs final coordinates on CPU side, which are expected to be
203 * accessible via mesh vertices. For this reason we do not evaluate multires to
204 * grids when orco is requested. */
205 const bool for_orco = (ctx->flag & MOD_APPLY_ORCO) != 0;
206 /* Needed when rendering or baking will in sculpt mode. */
207 const bool for_render = (ctx->flag & MOD_APPLY_RENDER) != 0;
208
209 const bool sculpt_base_mesh = mmd->flags & eMultiresModifierFlag_UseSculptBaseMesh;
210
211 if ((ctx->object->mode & OB_MODE_SCULPT) && !for_orco && !for_render && !sculpt_base_mesh) {
212 /* NOTE: CCG takes ownership over Subdiv. */
213 result = multires_as_ccg(mmd, ctx, mesh, subdiv);
214 result->runtime->subdiv_ccg_tot_level = mmd->totlvl;
215 /* TODO(sergey): Usually it is sculpt stroke's update variants which
216 * takes care of this, but is possible that we need this before the
217 * stroke: i.e. when exiting blender right after stroke is done.
218 * Annoying and not so much black-boxed as far as sculpting goes, and
219 * surely there is a better way of solving this. */
220 if (ctx->object->sculpt != nullptr) {
221 SculptSession *sculpt_session = ctx->object->sculpt;
222 sculpt_session->subdiv_ccg = result->runtime->subdiv_ccg.get();
223 sculpt_session->multires.active = true;
224 sculpt_session->multires.modifier = mmd;
225 sculpt_session->multires.level = mmd->sculptlvl;
226 }
227 // blender::bke::subdiv::stats_print(&subdiv->stats);
228 }
229 else {
230 if (use_clnors) {
233 memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes());
234 }
235
236 result = multires_as_mesh(mmd, ctx, mesh, subdiv);
237
238 if (use_clnors) {
240 *result,
242 &result->corner_data, CD_NORMAL, result->corners_num)),
243 result->corners_num});
245 }
246 // blender::bke::subdiv::stats_print(&subdiv->stats);
247 if (subdiv != runtime_data->subdiv) {
249 }
250 }
251 return result;
252}
253
255 const ModifierEvalContext *ctx,
256 Mesh *mesh,
259
260{
261#if !defined(WITH_OPENSUBDIV)
262 BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv");
263 return;
264#endif
265
267
268 blender::bke::subdiv::Settings subdiv_settings;
269 BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
270 if (subdiv_settings.level == 0) {
271 return;
272 }
273
274 SubdivToCCGSettings ccg_settings;
275 multires_ccg_settings_init(&ccg_settings, mmd, ctx, mesh);
276 if (ccg_settings.resolution < 3) {
277 return;
278 }
279
280 MultiresRuntimeData *runtime_data = multires_ensure_runtime(mmd);
281 blender::bke::subdiv::Subdiv *subdiv = subdiv_descriptor_ensure(mmd, &subdiv_settings, mesh);
282 if (subdiv == nullptr) {
283 /* Happens on bad topology, also on empty input mesh. */
284 return;
285 }
287 blender::bke::subdiv::deform_coarse_vertices(subdiv, mesh, positions);
288 if (subdiv != runtime_data->subdiv) {
290 }
291}
292
293static void panel_draw(const bContext *C, Panel *panel)
294{
295 uiLayout *col;
296 uiLayout *layout = panel->layout;
297
299
300 layout->use_property_split_set(true);
301
302 col = &layout->column(true);
303 col->prop(ptr, "levels", UI_ITEM_NONE, IFACE_("Levels Viewport"), ICON_NONE);
304 col->prop(ptr, "sculpt_levels", UI_ITEM_NONE, IFACE_("Sculpt"), ICON_NONE);
305 col->prop(ptr, "render_levels", UI_ITEM_NONE, IFACE_("Render"), ICON_NONE);
306
307 const bool is_sculpt_mode = CTX_data_active_object(C)->mode & OB_MODE_SCULPT;
308 uiBlock *block = panel->layout->block();
309 UI_block_lock_set(block, !is_sculpt_mode, N_("Sculpt Base Mesh"));
310 col->prop(ptr, "use_sculpt_base_mesh", UI_ITEM_NONE, IFACE_("Sculpt Base Mesh"), ICON_NONE);
311 UI_block_lock_clear(block);
312
313 layout->prop(ptr, "show_only_control_edges", UI_ITEM_NONE, std::nullopt, ICON_NONE);
314
316}
317
318static void subdivisions_panel_draw(const bContext * /*C*/, Panel *panel)
319{
320 uiLayout *row;
321 uiLayout *layout = panel->layout;
322
323 PointerRNA ob_ptr;
325
326 layout->enabled_set(RNA_enum_get(&ob_ptr, "mode") != OB_MODE_EDIT);
327
329
340
341 PointerRNA op_ptr;
342 op_ptr = layout->op("OBJECT_OT_multires_subdivide",
343 IFACE_("Subdivide"),
344 ICON_NONE,
348 RNA_string_set(&op_ptr, "modifier", ((ModifierData *)mmd)->name);
349
350 row = &layout->row(false);
351 op_ptr = row->op("OBJECT_OT_multires_subdivide",
352 IFACE_("Simple"),
353 ICON_NONE,
356 RNA_enum_set(&op_ptr, "mode", int8_t(MultiresSubdivideModeType::Simple));
357 RNA_string_set(&op_ptr, "modifier", ((ModifierData *)mmd)->name);
358 op_ptr = row->op("OBJECT_OT_multires_subdivide",
359 IFACE_("Linear"),
360 ICON_NONE,
363 RNA_enum_set(&op_ptr, "mode", int8_t(MultiresSubdivideModeType::Linear));
364 RNA_string_set(&op_ptr, "modifier", ((ModifierData *)mmd)->name);
365
366 layout->separator();
367
368 layout->op("OBJECT_OT_multires_unsubdivide", IFACE_("Unsubdivide"), ICON_NONE);
369 layout->op("OBJECT_OT_multires_higher_levels_delete", IFACE_("Delete Higher"), ICON_NONE);
370}
371
372static void shape_panel_draw(const bContext * /*C*/, Panel *panel)
373{
374 uiLayout *row;
375 uiLayout *layout = panel->layout;
376
377 PointerRNA ob_ptr;
379
380 layout->enabled_set(RNA_enum_get(&ob_ptr, "mode") != OB_MODE_EDIT);
381
382 PointerRNA op_ptr;
383 row = &layout->row(false);
384 row->op("OBJECT_OT_multires_reshape", IFACE_("Reshape"), ICON_NONE);
385
386 row = &layout->row(false);
387 op_ptr = row->op("OBJECT_OT_multires_base_apply", IFACE_("Apply Base"), ICON_NONE);
388 RNA_boolean_set(&op_ptr, "apply_heuristic", true);
389 op_ptr = row->op("OBJECT_OT_multires_base_apply", IFACE_("Conform Base"), ICON_NONE);
390 RNA_boolean_set(&op_ptr, "apply_heuristic", false);
391}
392
393static void generate_panel_draw(const bContext * /*C*/, Panel *panel)
394{
395 uiLayout *col, *row;
396 uiLayout *layout = panel->layout;
397
400
401 bool is_external = RNA_boolean_get(ptr, "is_external");
402
403 if (mmd->totlvl == 0) {
404 layout->op("OBJECT_OT_multires_rebuild_subdiv", IFACE_("Rebuild Subdivisions"), ICON_NONE);
405 }
406
407 col = &layout->column(false);
408 row = &col->row(false);
409 if (is_external) {
410 row->op("OBJECT_OT_multires_external_pack", IFACE_("Pack External"), ICON_NONE);
411 col->use_property_split_set(true);
412 row = &col->row(false);
413 row->prop(ptr, "filepath", UI_ITEM_NONE, std::nullopt, ICON_NONE);
414 }
415 else {
416 col->op("OBJECT_OT_multires_external_save", IFACE_("Save External..."), ICON_NONE);
417 }
418}
419
420static void advanced_panel_draw(const bContext * /*C*/, Panel *panel)
421{
422 uiLayout *col;
423 uiLayout *layout = panel->layout;
424
426
427 bool has_displacement = RNA_int_get(ptr, "total_levels") != 0;
428
429 layout->use_property_split_set(true);
430
431 layout->active_set(!has_displacement);
432
433 layout->prop(ptr, "quality", UI_ITEM_NONE, std::nullopt, ICON_NONE);
434
435 col = &layout->column(false);
436 col->active_set(true);
437 col->prop(ptr, "uv_smooth", UI_ITEM_NONE, std::nullopt, ICON_NONE);
438 col->prop(ptr, "boundary_smooth", UI_ITEM_NONE, std::nullopt, ICON_NONE);
439
440 layout->prop(ptr, "use_creases", UI_ITEM_NONE, std::nullopt, ICON_NONE);
441 layout->prop(ptr, "use_custom_normals", UI_ITEM_NONE, std::nullopt, ICON_NONE);
442}
443
444static void panel_register(ARegionType *region_type)
445{
448 region_type, "subdivide", "Subdivision", nullptr, subdivisions_panel_draw, panel_type);
449 modifier_subpanel_register(region_type, "shape", "Shape", nullptr, shape_panel_draw, panel_type);
451 region_type, "generate", "Generate", nullptr, generate_panel_draw, panel_type);
453 region_type, "advanced", "Advanced", nullptr, advanced_panel_draw, panel_type);
454}
455
457 /*idname*/ "Multires",
458 /*name*/ N_("Multires"),
459 /*struct_name*/ "MultiresModifierData",
460 /*struct_size*/ sizeof(MultiresModifierData),
461 /*srna*/ &RNA_MultiresModifier,
465 /*icon*/ ICON_MOD_MULTIRES,
466
467 /*copy_data*/ copy_data,
468
469 /*deform_verts*/ nullptr,
470 /*deform_matrices*/ deform_matrices,
471 /*deform_verts_EM*/ nullptr,
472 /*deform_matrices_EM*/ nullptr,
473 /*modify_mesh*/ modify_mesh,
474 /*modify_geometry_set*/ nullptr,
475
476 /*init_data*/ init_data,
477 /*required_data_mask*/ nullptr,
478 /*free_data*/ free_data,
479 /*is_disabled*/ nullptr,
480 /*update_depsgraph*/ nullptr,
481 /*depends_on_time*/ nullptr,
482 /*depends_on_normals*/ nullptr,
483 /*foreach_ID_link*/ nullptr,
484 /*foreach_tex_link*/ nullptr,
485 /*free_runtime_data*/ free_runtime_data,
486 /*panel_register*/ panel_register,
487 /*blend_write*/ nullptr,
488 /*blend_read*/ nullptr,
489 /*foreach_cache*/ nullptr,
490 /*foreach_working_space_color*/ nullptr,
491};
Object * CTX_data_active_object(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
@ CD_CONSTRUCT
void CustomData_free_layers(CustomData *data, eCustomDataType type)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_RequiresOriginalData
@ eModifierTypeFlag_AcceptsMesh
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
@ MOD_APPLY_TO_ORIGINAL
@ MOD_APPLY_RENDER
@ MOD_APPLY_IGNORE_SIMPLIFY
@ MOD_APPLY_ORCO
void BKE_multires_subdiv_settings_init(blender::bke::subdiv::Settings *settings, const MultiresModifierData *mmd)
void BKE_multires_subdiv_mesh_settings_init(blender::bke::subdiv::ToMeshSettings *mesh_settings, const Scene *scene, const Object *object, const MultiresModifierData *mmd, bool use_render_params, bool ignore_simplify, bool ignore_control_edges)
int multires_get_level(const Scene *scene, const Object *ob, const MultiresModifierData *mmd, bool render, bool ignore_simplify)
Definition multires.cc:205
Mesh * BKE_subdiv_to_ccg_mesh(blender::bke::subdiv::Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(msgid)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
@ CD_GRID_PAINT_MASK
#define DNA_struct_default_get(struct_name)
@ eMultiresModifierFlag_UseSculptBaseMesh
@ eMultiresModifierFlag_UseCustomNormals
@ eModifierType_Multires
@ OB_MODE_EDIT
@ OB_MODE_SCULPT
Object is a sort of wrapper for general info.
@ UI_PANEL_DATA_EXPAND_ROOT
@ UI_SUBPANEL_DATA_EXPAND_1
Read Guarded memory(de)allocation.
static void deform_matrices(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions, blender::MutableSpan< blender::float3x3 > matrices)
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void panel_draw(const bContext *, Panel *panel)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
Definition MOD_array.cc:862
static void free_data(ModifierData *md)
Definition MOD_bevel.cc:272
static void advanced_panel_draw(const bContext *, Panel *panel)
static void free_runtime_data(void *runtime_data_v)
static void init_data(ModifierData *md)
static void generate_panel_draw(const bContext *, Panel *panel)
static blender::bke::subdiv::Subdiv * subdiv_descriptor_ensure(MultiresModifierData *mmd, const blender::bke::subdiv::Settings *subdiv_settings, const Mesh *mesh)
static void panel_register(ARegionType *region_type)
static void free_runtime_data(void *runtime_data_v)
static Mesh * multires_as_ccg(MultiresModifierData *mmd, const ModifierEvalContext *ctx, Mesh *mesh, blender::bke::subdiv::Subdiv *subdiv)
static void copy_data(const ModifierData *md_src, ModifierData *md_dst, const int flag)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
ModifierTypeInfo modifierType_Multires
static void free_data(ModifierData *md)
static Mesh * multires_as_mesh(MultiresModifierData *mmd, const ModifierEvalContext *ctx, Mesh *mesh, blender::bke::subdiv::Subdiv *subdiv)
static void shape_panel_draw(const bContext *, Panel *panel)
static void advanced_panel_draw(const bContext *, Panel *panel)
static void subdivisions_panel_draw(const bContext *, Panel *panel)
static void multires_ccg_settings_init(SubdivToCCGSettings *settings, const MultiresModifierData *mmd, const ModifierEvalContext *ctx, Mesh *mesh)
static MultiresRuntimeData * multires_ensure_runtime(MultiresModifierData *mmd)
static void deform_matrices(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions, blender::MutableSpan< blender::float3x3 >)
static void panel_draw(const bContext *C, Panel *panel)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
#define C
Definition RandGen.cpp:29
void UI_block_lock_clear(uiBlock *block)
void UI_block_lock_set(uiBlock *block, bool val, const char *lockstr)
#define UI_ITEM_NONE
BMesh const char void * data
uint col
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void free(Subdiv *subdiv)
Definition subdiv.cc:190
void displacement_attach_from_multires(Subdiv *subdiv, const Mesh *mesh, const MultiresModifierData *mmd)
void deform_coarse_vertices(Subdiv *subdiv, const Mesh *coarse_mesh, MutableSpan< float3 > vert_positions)
Mesh * subdiv_to_mesh(Subdiv *subdiv, const ToMeshSettings *settings, const Mesh *coarse_mesh)
Subdiv * update_from_mesh(Subdiv *subdiv, const Settings *settings, const Mesh *mesh)
Definition subdiv.cc:179
void mesh_set_custom_normals_normalized(Mesh &mesh, MutableSpan< float3 > corner_normals)
const char * name
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
int RNA_int_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
int corners_num
CustomData corner_data
ModifierApplyFlag flag
blender::bke::subdiv::Subdiv * subdiv
struct SculptSession * sculpt
struct uiLayout * layout
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
struct SculptSession::@300305335361021334214041350300054316061376210174 multires
MultiresModifierData * modifier
Definition BKE_paint.hh:373
uiBlock * block() const
uiLayout & column(bool align)
void active_set(bool active)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void enabled_set(bool enabled)
uiLayout & row(bool align)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238
uint8_t flag
Definition wm_window.cc:145