Blender V4.3
MOD_subsurf.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
9#include <cstddef>
10#include <cstdio>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_string.h"
16#include "BLI_utildefines.h"
17
18#include "BLT_translation.hh"
19
20#include "DNA_defaults.h"
21#include "DNA_mesh_types.h"
22#include "DNA_object_types.h"
23#include "DNA_scene_types.h"
24#include "DNA_screen_types.h"
25
26#include "BKE_context.hh"
27#include "BKE_editmesh.hh"
28#include "BKE_mesh.hh"
29#include "BKE_mesh_types.hh"
30#include "BKE_scene.hh"
31#include "BKE_subdiv.hh"
32#include "BKE_subdiv_ccg.hh"
33#include "BKE_subdiv_deform.hh"
34#include "BKE_subdiv_mesh.hh"
36
37#include "UI_interface.hh"
38#include "UI_resources.hh"
39
40#include "RE_engine.h"
41
42#include "RNA_access.hh"
43#include "RNA_prototypes.hh"
44
45#include "DEG_depsgraph.hh"
47
48#include "MOD_modifiertypes.hh"
49#include "MOD_ui_common.hh"
50
51#include "intern/CCGSubSurf.h"
52
61
62static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
63{
66 r_cddata_masks->lmask |= CD_MASK_CUSTOMLOOPNORMAL;
67 }
68}
69
70static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
71{
72#if 0
73 const SubsurfModifierData *smd = (const SubsurfModifierData *)md;
74#endif
76
78
79 tsmd->emCache = tsmd->mCache = nullptr;
80}
81
82static void free_runtime_data(void *runtime_data_v)
83{
84 if (runtime_data_v == nullptr) {
85 return;
86 }
87 SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)runtime_data_v;
88 if (runtime_data->subdiv_cpu != nullptr) {
90 }
91 if (runtime_data->subdiv_gpu != nullptr) {
93 }
94 MEM_freeN(runtime_data);
95}
96
97static void free_data(ModifierData *md)
98{
100
101 if (smd->mCache) {
102 ccgSubSurf_free(static_cast<CCGSubSurf *>(smd->mCache));
103 smd->mCache = nullptr;
104 }
105 if (smd->emCache) {
106 ccgSubSurf_free(static_cast<CCGSubSurf *>(smd->emCache));
107 smd->emCache = nullptr;
108 }
110}
111
112static bool is_disabled(const Scene *scene, ModifierData *md, bool use_render_params)
113{
115 int levels = (use_render_params) ? smd->renderLevels : smd->levels;
116
117 return get_render_subsurf_level(&scene->r, levels, use_render_params != 0) == 0;
118}
119
121 const ModifierEvalContext *ctx)
122{
124 const bool use_render_params = (ctx->flag & MOD_APPLY_RENDER);
125 const int requested_levels = (use_render_params) ? smd->renderLevels : smd->levels;
126 return get_render_subsurf_level(&scene->r, requested_levels, use_render_params);
127}
128
129/* Subdivide into fully qualified mesh. */
130
132 const SubsurfModifierData *smd,
133 const ModifierEvalContext *ctx)
134{
135 const int level = subdiv_levels_for_modifier_get(smd, ctx);
136 settings->resolution = (1 << level) + 1;
137 settings->use_optimal_display = (smd->flags & eSubsurfModifierFlag_ControlEdges) &&
138 !(ctx->flag & MOD_APPLY_TO_ORIGINAL);
139}
140
142 const ModifierEvalContext *ctx,
143 Mesh *mesh,
145{
146 Mesh *result = mesh;
148 subdiv_mesh_settings_init(&mesh_settings, smd, ctx);
149 if (mesh_settings.resolution < 3) {
150 return result;
151 }
152 result = blender::bke::subdiv::subdiv_to_mesh(subdiv, &mesh_settings, mesh);
153 return result;
154}
155
156/* Subdivide into CCG. */
157
159 const SubsurfModifierData *smd,
160 const ModifierEvalContext *ctx)
161{
162 const int level = subdiv_levels_for_modifier_get(smd, ctx);
163 settings->resolution = (1 << level) + 1;
164 settings->need_normal = true;
165 settings->need_mask = false;
166}
167
169 const ModifierEvalContext *ctx,
170 Mesh *mesh,
172{
173 Mesh *result = mesh;
174 SubdivToCCGSettings ccg_settings;
175 subdiv_ccg_settings_init(&ccg_settings, smd, ctx);
176 if (ccg_settings.resolution < 3) {
177 return result;
178 }
179 result = BKE_subdiv_to_ccg_mesh(*subdiv, ccg_settings, *mesh);
180 return result;
181}
182
183/* Cache settings for lazy CPU evaluation. */
184
186 Mesh *mesh,
188 SubsurfRuntimeData *runtime_data)
189{
191 subdiv_mesh_settings_init(&mesh_settings, smd, ctx);
192
193 runtime_data->has_gpu_subdiv = true;
194 runtime_data->resolution = mesh_settings.resolution;
195 runtime_data->use_optimal_display = mesh_settings.use_optimal_display;
197
198 mesh->runtime->subsurf_runtime_data = runtime_data;
199}
200
201/* Modifier itself. */
202
203static Mesh *modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
204{
205 Mesh *result = mesh;
206#if !defined(WITH_OPENSUBDIV)
207 BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv");
208 return result;
209#endif
212 return result;
213 }
214
216
217 /* Decrement the recent usage counters. */
218 if (runtime_data->used_cpu) {
219 runtime_data->used_cpu--;
220 }
221
222 if (runtime_data->used_gpu) {
223 runtime_data->used_gpu--;
224 }
225
226 /* Delay evaluation to the draw code if possible, provided we do not have to apply the modifier.
227 */
228 if ((ctx->flag & MOD_APPLY_TO_ORIGINAL) == 0) {
230 const bool is_render_mode = (ctx->flag & MOD_APPLY_RENDER) != 0;
231 /* Same check as in `DRW_mesh_batch_cache_create_requested` to keep both code coherent. The
232 * difference is that here we do not check for the final edit mesh pointer as it is not yet
233 * assigned at this stage of modifier stack evaluation. */
234 const bool is_editmode = (mesh->runtime->edit_mesh != nullptr);
235 const int required_mode = BKE_subsurf_modifier_eval_required_mode(is_render_mode, is_editmode);
236 if (BKE_subsurf_modifier_can_do_gpu_subdiv(scene, ctx->object, mesh, smd, required_mode)) {
237 subdiv_cache_mesh_wrapper_settings(ctx, mesh, smd, runtime_data);
238 return result;
239 }
240 }
241
243 runtime_data, mesh, false);
244 if (subdiv == nullptr) {
245 /* Happens on bad topology, but also on empty input mesh. */
246 return result;
247 }
248 const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh);
249 if (use_clnors) {
250 void *data = CustomData_add_layer(
251 &mesh->corner_data, CD_NORMAL, CD_CONSTRUCT, mesh->corners_num);
252 memcpy(data, mesh->corner_normals().data(), mesh->corner_normals().size_in_bytes());
253 }
254 /* TODO(sergey): Decide whether we ever want to use CCG for subsurf,
255 * maybe when it is a last modifier in the stack? */
256 if (true) {
257 result = subdiv_as_mesh(smd, ctx, mesh, subdiv);
258 }
259 else {
260 result = subdiv_as_ccg(smd, ctx, mesh, subdiv);
261 }
262
263 if (use_clnors) {
265 result,
266 static_cast<float(*)[3]>(
267 CustomData_get_layer_for_write(&result->corner_data, CD_NORMAL, result->corners_num)));
268 CustomData_free_layers(&result->corner_data, CD_NORMAL, result->corners_num);
269 }
270 // blender::bke::subdiv::stats_print(&subdiv->stats);
271 if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) {
273 }
274 return result;
275}
276
278 const ModifierEvalContext *ctx,
279 Mesh *mesh,
282{
283#if !defined(WITH_OPENSUBDIV)
284 BKE_modifier_set_error(ctx->object, md, "Disabled, built without OpenSubdiv");
285 return;
286#endif
287
288 /* Subsurf does not require extra space mapping, keep matrices as is. */
289
292 return;
293 }
296 runtime_data, mesh, false);
297 if (subdiv == nullptr) {
298 /* Happens on bad topology, but also on empty input mesh. */
299 return;
300 }
301 blender::bke::subdiv::deform_coarse_vertices(subdiv, mesh, positions);
302 if (!ELEM(subdiv, runtime_data->subdiv_cpu, runtime_data->subdiv_gpu)) {
304 }
305}
306
307#ifdef WITH_CYCLES
308static bool get_show_adaptive_options(const bContext *C, Panel *panel)
309{
310 /* Don't show adaptive options if cycles isn't the active engine. */
311 const RenderEngineType *engine_type = CTX_data_engine_type(C);
312 if (!STREQ(engine_type->idname, "CYCLES")) {
313 return false;
314 }
315
316 /* Only show adaptive options if this is the last modifier. */
318 ModifierData *md = static_cast<ModifierData *>(ptr->data);
319 if (md->next != nullptr) {
320 return false;
321 }
322
323 /* Don't show adaptive options if regular subdivision used. */
324 if (!RNA_boolean_get(ptr, "use_limit_surface")) {
325 return false;
326 }
327
328 /* Don't show adaptive options if the cycles experimental feature set is disabled. */
329 Scene *scene = CTX_data_scene(C);
331 return false;
332 }
333
334 return true;
335}
336#endif
337
338static void panel_draw(const bContext *C, Panel *panel)
339{
340 uiLayout *layout = panel->layout;
341
342 PointerRNA ob_ptr;
344
345 /* Only test for adaptive subdivision if built with cycles. */
346 bool show_adaptive_options = false;
347 bool ob_use_adaptive_subdivision = false;
348 PointerRNA cycles_ptr = {nullptr};
349 PointerRNA ob_cycles_ptr = {nullptr};
350#ifdef WITH_CYCLES
351 Scene *scene = CTX_data_scene(C);
352 PointerRNA scene_ptr = RNA_id_pointer_create(&scene->id);
353 if (BKE_scene_uses_cycles(scene)) {
354 cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles");
355 ob_cycles_ptr = RNA_pointer_get(&ob_ptr, "cycles");
356 if (!RNA_pointer_is_null(&ob_cycles_ptr)) {
357 ob_use_adaptive_subdivision = RNA_boolean_get(&ob_cycles_ptr, "use_adaptive_subdivision");
358 show_adaptive_options = get_show_adaptive_options(C, panel);
359 }
360 }
361#else
362 UNUSED_VARS(C);
363#endif
364
365 uiItemR(layout, ptr, "subdivision_type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
366
367 uiLayoutSetPropSep(layout, true);
368
369 if (show_adaptive_options) {
370 uiItemR(layout,
371 &ob_cycles_ptr,
372 "use_adaptive_subdivision",
374 IFACE_("Adaptive Subdivision"),
375 ICON_NONE);
376 }
377 if (ob_use_adaptive_subdivision && show_adaptive_options) {
378 uiItemR(layout, &ob_cycles_ptr, "dicing_rate", UI_ITEM_NONE, nullptr, ICON_NONE);
379 float render = std::max(RNA_float_get(&cycles_ptr, "dicing_rate") *
380 RNA_float_get(&ob_cycles_ptr, "dicing_rate"),
381 0.1f);
382 float preview = std::max(RNA_float_get(&cycles_ptr, "preview_dicing_rate") *
383 RNA_float_get(&ob_cycles_ptr, "dicing_rate"),
384 0.1f);
385 char output[256];
386 SNPRINTF(output, RPT_("Final Scale: Render %.2f px, Viewport %.2f px"), render, preview);
387 uiItemL(layout, output, ICON_NONE);
388
389 uiItemS(layout);
390
391 uiItemR(layout, ptr, "levels", UI_ITEM_NONE, IFACE_("Levels Viewport"), ICON_NONE);
392 }
393 else {
394 uiLayout *col = uiLayoutColumn(layout, true);
395 uiItemR(col, ptr, "levels", UI_ITEM_NONE, IFACE_("Levels Viewport"), ICON_NONE);
396 uiItemR(col, ptr, "render_levels", UI_ITEM_NONE, IFACE_("Render"), ICON_NONE);
397 }
398
399 uiItemR(layout, ptr, "show_only_control_edges", UI_ITEM_NONE, nullptr, ICON_NONE);
400
402 SubsurfModifierData *smd = static_cast<SubsurfModifierData *>(ptr->data);
403 Object *ob = static_cast<Object *>(ob_ptr.data);
404 const Mesh *mesh = static_cast<const Mesh *>(ob->data);
406 uiItemL(layout,
407 RPT_("Sharp edges or custom normals detected, disabling GPU subdivision"),
408 ICON_INFO);
409 }
410 else if (Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob)) {
411 if (ModifierData *md_eval = BKE_modifiers_findby_name(ob_eval, smd->modifier.name)) {
412 if (md_eval->type == eModifierType_Subsurf) {
413 SubsurfRuntimeData *runtime_data = (SubsurfRuntimeData *)md_eval->runtime;
414
415 if (runtime_data && runtime_data->used_gpu) {
416 if (runtime_data->used_cpu) {
417 uiItemL(layout, RPT_("Using both CPU and GPU subdivision"), ICON_INFO);
418 }
419 }
420 }
421 }
422 }
423
424 modifier_panel_end(layout, ptr);
425}
426
427static void advanced_panel_draw(const bContext *C, Panel *panel)
428{
429 uiLayout *layout = panel->layout;
430
431 PointerRNA ob_ptr;
433
434 bool ob_use_adaptive_subdivision = false;
435 bool show_adaptive_options = false;
436#ifdef WITH_CYCLES
437 Scene *scene = CTX_data_scene(C);
438 if (BKE_scene_uses_cycles(scene)) {
439 PointerRNA ob_cycles_ptr = RNA_pointer_get(&ob_ptr, "cycles");
440 if (!RNA_pointer_is_null(&ob_cycles_ptr)) {
441 ob_use_adaptive_subdivision = RNA_boolean_get(&ob_cycles_ptr, "use_adaptive_subdivision");
442 show_adaptive_options = get_show_adaptive_options(C, panel);
443 }
444 }
445#else
446 UNUSED_VARS(C);
447#endif
448
449 uiLayoutSetPropSep(layout, true);
450
451 uiLayoutSetActive(layout, !(show_adaptive_options && ob_use_adaptive_subdivision));
452 uiItemR(layout, ptr, "use_limit_surface", UI_ITEM_NONE, nullptr, ICON_NONE);
453
454 uiLayout *col = uiLayoutColumn(layout, true);
455 uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_limit_surface"));
456 uiItemR(col, ptr, "quality", UI_ITEM_NONE, nullptr, ICON_NONE);
457
458 uiItemR(layout, ptr, "uv_smooth", UI_ITEM_NONE, nullptr, ICON_NONE);
459 uiItemR(layout, ptr, "boundary_smooth", UI_ITEM_NONE, nullptr, ICON_NONE);
460 uiItemR(layout, ptr, "use_creases", UI_ITEM_NONE, nullptr, ICON_NONE);
461 uiItemR(layout, ptr, "use_custom_normals", UI_ITEM_NONE, nullptr, ICON_NONE);
462}
463
464static void panel_register(ARegionType *region_type)
465{
468 region_type, "advanced", "Advanced", nullptr, advanced_panel_draw, panel_type);
469}
470
471static void blend_read(BlendDataReader * /*reader*/, ModifierData *md)
472{
474
475 smd->emCache = smd->mCache = nullptr;
476}
477
479 /*idname*/ "Subdivision",
480 /*name*/ N_("Subdivision"),
481 /*struct_name*/ "SubsurfModifierData",
482 /*struct_size*/ sizeof(SubsurfModifierData),
483 /*srna*/ &RNA_SubsurfModifier,
488 /*icon*/ ICON_MOD_SUBSURF,
489
490 /*copy_data*/ copy_data,
491
492 /*deform_verts*/ nullptr,
493 /*deform_matrices*/ deform_matrices,
494 /*deform_verts_EM*/ nullptr,
495 /*deform_matrices_EM*/ nullptr,
496 /*modify_mesh*/ modify_mesh,
497 /*modify_geometry_set*/ nullptr,
498
499 /*init_data*/ init_data,
500 /*required_data_mask*/ required_data_mask,
501 /*free_data*/ free_data,
502 /*is_disabled*/ is_disabled,
503 /*update_depsgraph*/ nullptr,
504 /*depends_on_time*/ nullptr,
505 /*depends_on_normals*/ nullptr,
506 /*foreach_ID_link*/ nullptr,
507 /*foreach_tex_link*/ nullptr,
508 /*free_runtime_data*/ free_runtime_data,
509 /*panel_register*/ panel_register,
510 /*blend_write*/ nullptr,
511 /*blend_read*/ blend_read,
512 /*foreach_cache*/ nullptr,
513};
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
RenderEngineType * CTX_data_engine_type(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
@ CD_CONSTRUCT
void CustomData_free_layers(CustomData *data, eCustomDataType type, int totelem)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
void BKE_mesh_set_custom_normals_normalized(Mesh *mesh, float(*r_custom_loop_normals)[3])
void BKE_modifier_copydata_generic(const ModifierData *md, ModifierData *md_dst, int flag)
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_SupportsMapping
@ eModifierTypeFlag_EnableInEditmode
@ eModifierTypeFlag_SupportsEditmode
@ eModifierTypeFlag_AcceptsMesh
ModifierData * BKE_modifiers_findby_name(const Object *ob, const char *name)
void BKE_modifier_set_error(const Object *ob, ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
@ MOD_APPLY_TO_ORIGINAL
@ MOD_APPLY_RENDER
bool BKE_scene_uses_cycles(const Scene *scene)
Definition scene.cc:2782
int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
Definition scene.cc:2700
bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
Definition scene.cc:2798
Mesh * BKE_subdiv_to_ccg_mesh(blender::bke::subdiv::Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh)
int BKE_subsurf_modifier_eval_required_mode(bool is_final_render, bool is_edit_mode)
bool BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(const SubsurfModifierData *smd, const Mesh *mesh)
bool BKE_subsurf_modifier_can_do_gpu_subdiv(const Scene *scene, const Object *ob, const Mesh *mesh, const SubsurfModifierData *smd, int required_mode)
bool BKE_subsurf_modifier_use_custom_loop_normals(const SubsurfModifierData *smd, const Mesh *mesh)
bool BKE_subsurf_modifier_runtime_init(SubsurfModifierData *smd, bool use_render_params)
blender::bke::subdiv::Subdiv * BKE_subsurf_modifier_subdiv_descriptor_ensure(SubsurfRuntimeData *runtime_data, const Mesh *mesh, bool for_draw_code)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
#define UNUSED_VARS(...)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
#define RPT_(msgid)
#define IFACE_(msgid)
void ccgSubSurf_free(CCGSubSurf *ss)
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
#define CD_MASK_CUSTOMLOOPNORMAL
#define DNA_struct_default_get(struct_name)
@ eModifierType_Subsurf
struct SubsurfModifierData SubsurfModifierData
@ eSubsurfModifierFlag_ControlEdges
@ eSubsurfModifierFlag_UseCustomNormals
Object is a sort of wrapper for general info.
static bool is_disabled
Read Guarded memory(de)allocation.
static void init_data(ModifierData *md)
static void panel_register(ARegionType *region_type)
static void free_runtime_data(void *runtime_data_v)
static Mesh * subdiv_as_ccg(SubsurfModifierData *smd, const ModifierEvalContext *ctx, Mesh *mesh, blender::bke::subdiv::Subdiv *subdiv)
static void blend_read(BlendDataReader *, ModifierData *md)
static Mesh * modify_mesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
static void free_data(ModifierData *md)
static void subdiv_mesh_settings_init(blender::bke::subdiv::ToMeshSettings *settings, const SubsurfModifierData *smd, const ModifierEvalContext *ctx)
static void subdiv_ccg_settings_init(SubdivToCCGSettings *settings, const SubsurfModifierData *smd, const ModifierEvalContext *ctx)
ModifierTypeInfo modifierType_Subsurf
static void advanced_panel_draw(const bContext *C, Panel *panel)
static Mesh * subdiv_as_mesh(SubsurfModifierData *smd, const ModifierEvalContext *ctx, Mesh *mesh, blender::bke::subdiv::Subdiv *subdiv)
static void required_data_mask(ModifierData *md, CustomData_MeshMasks *r_cddata_masks)
static void copy_data(const ModifierData *md, ModifierData *target, const int flag)
static void deform_matrices(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions, blender::MutableSpan< blender::float3x3 >)
static int subdiv_levels_for_modifier_get(const SubsurfModifierData *smd, const ModifierEvalContext *ctx)
static void panel_draw(const bContext *C, Panel *panel)
static void subdiv_cache_mesh_wrapper_settings(const ModifierEvalContext *ctx, Mesh *mesh, SubsurfModifierData *smd, SubsurfRuntimeData *runtime_data)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void uiLayoutSetActive(uiLayout *layout, bool active)
void uiItemL(uiLayout *layout, const char *name, int icon)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
#define UI_ITEM_NONE
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_EXPAND
const Depsgraph * depsgraph
uint col
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void free(Subdiv *subdiv)
Definition subdiv.cc:192
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)
PointerRNA RNA_pointer_get(PointerRNA *ptr, const char *name)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_pointer_is_null(const PointerRNA *ptr)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_id_pointer_create(ID *id)
struct ModifierData * next
ModifierApplyFlag flag
struct uiLayout * layout
void * data
Definition RNA_types.hh:42
char idname[64]
Definition RE_engine.h:78
blender::bke::subdiv::Subdiv * subdiv_cpu
blender::bke::subdiv::Subdiv * subdiv_gpu
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126
uint8_t flag
Definition wm_window.cc:138