Blender  V3.3
sculpt_mask_expand.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_math.h"
12 #include "BLI_task.h"
13 
14 #include "BLT_translation.h"
15 
16 #include "DNA_brush_types.h"
17 #include "DNA_mesh_types.h"
18 #include "DNA_meshdata_types.h"
19 #include "DNA_object_types.h"
20 
21 #include "BKE_brush.h"
22 #include "BKE_ccg.h"
23 #include "BKE_colortools.h"
24 #include "BKE_context.h"
25 #include "BKE_mesh.h"
26 #include "BKE_multires.h"
27 #include "BKE_node.h"
28 #include "BKE_object.h"
29 #include "BKE_paint.h"
30 #include "BKE_pbvh.h"
31 #include "BKE_scene.h"
32 
33 #include "DEG_depsgraph.h"
34 
35 #include "WM_api.h"
36 #include "WM_message.h"
37 #include "WM_toolsystem.h"
38 #include "WM_types.h"
39 
40 #include "RNA_access.h"
41 #include "RNA_define.h"
42 
43 #include "ED_object.h"
44 #include "ED_screen.h"
45 #include "ED_sculpt.h"
46 #include "ED_view3d.h"
47 #include "paint_intern.h"
48 #include "sculpt_intern.h"
49 
50 #include "bmesh.h"
51 
52 #include <math.h>
53 #include <stdlib.h>
54 
56 {
58  SculptSession *ss = ob->sculpt;
59  const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
60 
61  MEM_freeN(op->customdata);
62 
63  for (int n = 0; n < ss->filter_cache->totnode; n++) {
64  PBVHNode *node = ss->filter_cache->nodes[n];
65  if (create_face_set) {
66  for (int i = 0; i < ss->totfaces; i++) {
67  ss->face_sets[i] = ss->filter_cache->prev_face_set[i];
68  }
69  }
70  else {
71  PBVHVertexIter vd;
73  *vd.mask = ss->filter_cache->prev_mask[vd.index];
74  }
76  }
77 
79  }
80 
81  if (!create_face_set) {
83  }
88 }
89 
90 static void sculpt_expand_task_cb(void *__restrict userdata,
91  const int i,
92  const TaskParallelTLS *__restrict UNUSED(tls))
93 {
94  SculptThreadedTaskData *data = userdata;
95  SculptSession *ss = data->ob->sculpt;
96  PBVHNode *node = data->nodes[i];
97  PBVHVertexIter vd;
98  int update_it = data->mask_expand_update_it;
99 
101  int vi = vd.index;
102  float final_mask = *vd.mask;
103  if (data->mask_expand_use_normals) {
105  ss->filter_cache->normal_factor[vd.index]) {
106  final_mask = 1.0f;
107  }
108  else {
109  final_mask = 0.0f;
110  }
111  }
112  else {
113  if (ss->filter_cache->mask_update_it[vi] <= update_it &&
114  ss->filter_cache->mask_update_it[vi] != 0) {
115  final_mask = 1.0f;
116  }
117  else {
118  final_mask = 0.0f;
119  }
120  }
121 
122  if (data->mask_expand_create_face_set) {
123  if (final_mask == 1.0f) {
125  }
127  }
128  else {
129 
130  if (data->mask_expand_keep_prev_mask) {
131  final_mask = MAX2(ss->filter_cache->prev_mask[vd.index], final_mask);
132  }
133 
134  if (data->mask_expand_invert_mask) {
135  final_mask = 1.0f - final_mask;
136  }
137 
138  if (*vd.mask != final_mask) {
139  *vd.mask = final_mask;
141  }
142  }
143  }
145 }
146 
147 static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
148 {
151  SculptSession *ss = ob->sculpt;
153  ARegion *region = CTX_wm_region(C);
154  float prev_click_f[2];
155  copy_v2_v2(prev_click_f, op->customdata);
156  const int prev_click[2] = {(int)prev_click_f[0], (int)prev_click_f[1]};
157  int len = (int)len_v2v2_int(prev_click, event->mval);
158  len = abs(len);
159  int mask_speed = RNA_int_get(op->ptr, "mask_speed");
160  int mask_expand_update_it = len / mask_speed;
161  mask_expand_update_it = mask_expand_update_it + 1;
162 
163  const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
164 
165  if (RNA_boolean_get(op->ptr, "use_cursor")) {
167  const float mval_fl[2] = {UNPACK2(event->mval)};
168  if (SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false)) {
169  /* The cursor is over the mesh, get the update iteration from the updated active vertex. */
170  mask_expand_update_it = ss->filter_cache->mask_update_it[(int)SCULPT_active_vertex_get(ss)];
171  }
172  else {
173  /* When the cursor is outside the mesh, affect the entire connected component. */
174  mask_expand_update_it = ss->filter_cache->mask_update_last_it - 1;
175  }
176  }
177 
178  if ((event->type == EVT_ESCKEY && event->val == KM_PRESS) ||
179  (event->type == RIGHTMOUSE && event->val == KM_PRESS)) {
180  /* Returning OPERATOR_CANCELLED will leak memory due to not finishing
181  * undo. Better solution could be to make paint_mesh_restore_co work
182  * for this case. */
184  return OPERATOR_FINISHED;
185  }
186 
187  if ((event->type == LEFTMOUSE && event->val == KM_RELEASE) ||
188  (event->type == EVT_RETKEY && event->val == KM_PRESS) ||
189  (event->type == EVT_PADENTER && event->val == KM_PRESS)) {
190 
191  /* Smooth iterations. */
192  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
193  const int smooth_iterations = RNA_int_get(op->ptr, "smooth_iterations");
195  sd, ob, ss->filter_cache->nodes, ss->filter_cache->totnode, smooth_iterations);
196 
197  /* Pivot position. */
198  if (RNA_boolean_get(op->ptr, "update_pivot")) {
199  const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
200  const float threshold = 0.2f;
201  float avg[3];
202  int total = 0;
203  zero_v3(avg);
204 
205  for (int n = 0; n < ss->filter_cache->totnode; n++) {
206  PBVHVertexIter vd;
208  const float mask = (vd.mask) ? *vd.mask : 0.0f;
209  if (mask < (0.5f + threshold) && mask > (0.5f - threshold)) {
211  vd.co, ss->filter_cache->mask_expand_initial_co, symm)) {
212  add_v3_v3(avg, vd.co);
213  total++;
214  }
215  }
216  }
218  }
219 
220  if (total > 0) {
221  mul_v3_fl(avg, 1.0f / total);
222  copy_v3_v3(ss->pivot_pos, avg);
223  }
225  }
226 
227  MEM_freeN(op->customdata);
228 
229  for (int i = 0; i < ss->filter_cache->totnode; i++) {
231  }
232 
234 
238  return OPERATOR_FINISHED;
239  }
240 
241  /* When pressing Ctrl, expand directly to the max number of iterations. This allows to flood fill
242  * mask and face sets by connectivity directly. */
243  if (event->modifier & KM_CTRL) {
244  mask_expand_update_it = ss->filter_cache->mask_update_last_it - 1;
245  }
246 
248  return OPERATOR_RUNNING_MODAL;
249  }
250 
251  if (mask_expand_update_it == ss->filter_cache->mask_update_current_it) {
252  ED_region_tag_redraw(region);
253  return OPERATOR_RUNNING_MODAL;
254  }
255 
256  if (mask_expand_update_it < ss->filter_cache->mask_update_last_it) {
257 
258  if (create_face_set) {
259  for (int i = 0; i < ss->totfaces; i++) {
260  ss->face_sets[i] = ss->filter_cache->prev_face_set[i];
261  }
262  }
264  .sd = sd,
265  .ob = ob,
266  .nodes = ss->filter_cache->nodes,
267  .mask_expand_update_it = mask_expand_update_it,
268  .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"),
269  .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
270  .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
271  .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"),
272  };
273  TaskParallelSettings settings;
276  ss->filter_cache->mask_update_current_it = mask_expand_update_it;
277  }
278 
280 
281  return OPERATOR_RUNNING_MODAL;
282 }
283 
284 typedef struct MaskExpandFloodFillData {
285  float original_normal[3];
289 
291  SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
292 {
293  MaskExpandFloodFillData *data = userdata;
294 
295  if (!is_duplicate) {
296  int to_it = ss->filter_cache->mask_update_it[from_v] + 1;
297  ss->filter_cache->mask_update_it[to_v] = to_it;
298  if (to_it > ss->filter_cache->mask_update_last_it) {
299  ss->filter_cache->mask_update_last_it = to_it;
300  }
301 
302  if (data->use_normals) {
303  float current_normal[3], prev_normal[3];
304  SCULPT_vertex_normal_get(ss, to_v, current_normal);
305  SCULPT_vertex_normal_get(ss, from_v, prev_normal);
306  const float from_edge_factor = ss->filter_cache->edge_factor[from_v];
307  ss->filter_cache->edge_factor[to_v] = dot_v3v3(current_normal, prev_normal) *
308  from_edge_factor;
309  ss->filter_cache->normal_factor[to_v] = dot_v3v3(data->original_normal, current_normal) *
310  powf(from_edge_factor, data->edge_sensitivity);
311  CLAMP(ss->filter_cache->normal_factor[to_v], 0.0f, 1.0f);
312  }
313  }
314  else {
315  /* PBVH_GRIDS duplicate handling. */
316  ss->filter_cache->mask_update_it[to_v] = ss->filter_cache->mask_update_it[from_v];
317  if (data->use_normals) {
318  ss->filter_cache->edge_factor[to_v] = ss->filter_cache->edge_factor[from_v];
319  ss->filter_cache->normal_factor[to_v] = ss->filter_cache->normal_factor[from_v];
320  }
321  }
322 
323  return true;
324 }
325 
326 static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
327 {
330  SculptSession *ss = ob->sculpt;
332  PBVH *pbvh = ob->sculpt->pbvh;
333 
334  const bool use_normals = RNA_boolean_get(op->ptr, "use_normals");
335  const bool create_face_set = RNA_boolean_get(op->ptr, "create_face_set");
336 
338  const float mval_fl[2] = {UNPACK2(event->mval)};
339 
341 
342  op->customdata = MEM_mallocN(sizeof(float[2]), "initial mouse position");
343  copy_v2_v2(op->customdata, mval_fl);
344 
345  SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
346 
347  BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);
348 
349  int vertex_count = SCULPT_vertex_count_get(ss);
350 
351  ss->filter_cache = MEM_callocN(sizeof(FilterCache), "filter cache");
352 
354 
355  SCULPT_undo_push_begin(ob, "Mask Expand");
356 
357  if (create_face_set) {
359  for (int i = 0; i < ss->filter_cache->totnode; i++) {
361  }
362  }
363  else {
364  for (int i = 0; i < ss->filter_cache->totnode; i++) {
367  }
368  }
369 
370  ss->filter_cache->mask_update_it = MEM_callocN(sizeof(int) * vertex_count,
371  "mask update iteration");
372  if (use_normals) {
373  ss->filter_cache->normal_factor = MEM_callocN(sizeof(float) * vertex_count,
374  "mask update normal factor");
375  ss->filter_cache->edge_factor = MEM_callocN(sizeof(float) * vertex_count,
376  "mask update normal factor");
377  for (int i = 0; i < vertex_count; i++) {
378  ss->filter_cache->edge_factor[i] = 1.0f;
379  }
380  }
381 
382  if (create_face_set) {
383  ss->filter_cache->prev_face_set = MEM_callocN(sizeof(float) * ss->totfaces, "prev face mask");
384  for (int i = 0; i < ss->totfaces; i++) {
385  ss->filter_cache->prev_face_set[i] = ss->face_sets[i];
386  }
388  }
389  else {
390  ss->filter_cache->prev_mask = MEM_callocN(sizeof(float) * vertex_count, "prev mask");
391  for (int i = 0; i < vertex_count; i++) {
393  }
394  }
395 
399 
401 
402  SculptFloodFill flood;
403  SCULPT_floodfill_init(ss, &flood);
404  SCULPT_floodfill_add_active(sd, ob, ss, &flood, FLT_MAX);
405 
406  MaskExpandFloodFillData fdata = {
407  .use_normals = use_normals,
408  .edge_sensitivity = RNA_int_get(op->ptr, "edge_sensitivity"),
409  };
412  SCULPT_floodfill_free(&flood);
413 
414  if (use_normals) {
415  for (int repeat = 0; repeat < 2; repeat++) {
416  for (int i = 0; i < vertex_count; i++) {
417  float avg = 0.0f;
420  avg += ss->filter_cache->normal_factor[ni.index];
421  }
423  ss->filter_cache->normal_factor[i] = avg / ni.size;
424  }
425  }
426 
428  }
429 
431  .sd = sd,
432  .ob = ob,
433  .nodes = ss->filter_cache->nodes,
434  .mask_expand_update_it = 0,
435  .mask_expand_use_normals = RNA_boolean_get(op->ptr, "use_normals"),
436  .mask_expand_invert_mask = RNA_boolean_get(op->ptr, "invert"),
437  .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"),
438  .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"),
439  };
440  TaskParallelSettings settings;
443 
444  const char *status_str = TIP_(
445  "Move the mouse to expand the mask from the active vertex. LMB: confirm mask, ESC/RMB: "
446  "cancel");
447  ED_workspace_status_text(C, status_str);
448 
451  return OPERATOR_RUNNING_MODAL;
452 }
453 
455 {
456  /* Identifiers. */
457  ot->name = "Mask Expand";
458  ot->idname = "SCULPT_OT_mask_expand";
459  ot->description = "Expands a mask from the initial active vertex under the cursor";
460 
461  /* API callbacks. */
466 
468  ot->prop = RNA_def_boolean(ot->srna, "invert", true, "Invert", "Invert the new mask");
470  ot->srna, "use_cursor", true, "Use Cursor", "Expand the mask to the cursor position");
472  "update_pivot",
473  true,
474  "Update Pivot Position",
475  "Set the pivot position to the mask border after creating the mask");
476  ot->prop = RNA_def_int(ot->srna, "smooth_iterations", 2, 0, 10, "Smooth Iterations", "", 0, 10);
477  ot->prop = RNA_def_int(ot->srna, "mask_speed", 5, 1, 10, "Mask Speed", "", 1, 10);
478 
480  "use_normals",
481  true,
482  "Use Normals",
483  "Generate the mask using the normals and curvature of the model");
485  "keep_previous_mask",
486  false,
487  "Keep Previous Mask",
488  "Generate the new mask on top of the current one");
489  ot->prop = RNA_def_int(ot->srna,
490  "edge_sensitivity",
491  300,
492  0,
493  2000,
494  "Edge Detection Sensitivity",
495  "Sensitivity for expanding the mask across sculpted sharp edges when "
496  "using normals to generate the mask",
497  0,
498  2000);
500  "create_face_set",
501  false,
502  "Expand Face Mask",
503  "Expand a new Face Mask instead of the sculpt mask");
504 }
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct ToolSettings * CTX_data_tool_settings(const bContext *C)
Definition: context.c:1282
General operations, lookup, etc. for blender objects.
void BKE_sculpt_update_object_for_edit(struct Depsgraph *depsgraph, struct Object *ob_orig, bool need_pmap, bool need_mask, bool is_paint_tool)
Definition: paint.c:1914
A BVH for high poly meshes.
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:439
#define PBVH_ITER_ALL
Definition: BKE_pbvh.h:390
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:509
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:391
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3211
void BKE_pbvh_node_mark_update_mask(PBVHNode *node)
Definition: pbvh.c:1875
void BKE_pbvh_node_mark_redraw(PBVHNode *node)
Definition: pbvh.c:1906
void BKE_pbvh_search_gather(PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot)
Definition: pbvh.c:838
MINLINE float len_v2v2_int(const int v1[2], const int v2[2])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
#define UNPACK2(a)
#define UNUSED(x)
#define MAX2(a, b)
#define ELEM(...)
#define TIP_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
Object is a sort of wrapper for general info.
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
void ED_workspace_status_text(struct bContext *C, const char *str)
Definition: area.c:816
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define C
Definition: RandGen.cpp:25
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_GEOM
Definition: WM_types.h:343
#define ND_SELECT
Definition: WM_types.h:455
@ KM_CTRL
Definition: WM_types.h:239
#define powf(x, y)
Definition: cuda/compat.h:103
OperationNode * node
const Depsgraph * depsgraph
int len
Definition: draw_manager.c:108
ccl_gpu_kernel_postfix ccl_global float int int int int float threshold
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
T abs(const T &a)
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
PropertyRNA * RNA_def_int(StructOrFunctionRNA *cont_, const char *identifier, int default_value, int hardmin, int hardmax, const char *ui_name, const char *ui_description, int softmin, int softmax)
Definition: rna_define.c:3597
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:111
int SCULPT_active_vertex_get(SculptSession *ss)
Definition: sculpt.c:271
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
Definition: sculpt.c:4835
void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
Definition: sculpt.c:1072
void SCULPT_vertex_face_set_set(SculptSession *ss, int index, int face_set)
Definition: sculpt.c:483
const float * SCULPT_active_vertex_co_get(SculptSession *ss)
Definition: sculpt.c:279
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:103
void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType update_flags)
Definition: sculpt.c:5212
void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
Definition: sculpt.c:5144
void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
Definition: sculpt.c:171
void SCULPT_floodfill_free(SculptFloodFill *flood)
Definition: sculpt.c:1174
bool SCULPT_mode_poll(bContext *C)
Definition: sculpt.c:3957
void SCULPT_active_vertex_normal_get(SculptSession *ss, float normal[3])
Definition: sculpt.c:284
float SCULPT_vertex_mask_get(SculptSession *ss, int index)
Definition: sculpt.c:248
int SCULPT_face_set_next_available_get(SculptSession *ss)
Definition: sculpt.c:693
char SCULPT_mesh_symmetry_xyz_get(Object *object)
Definition: sculpt.c:317
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
Definition: sculpt.c:923
void SCULPT_floodfill_add_active(Sculpt *sd, Object *ob, SculptSession *ss, SculptFloodFill *flood, float radius)
Definition: sculpt.c:1118
void SCULPT_floodfill_execute(SculptSession *ss, SculptFloodFill *flood, bool(*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata), void *userdata)
Definition: sculpt.c:1143
void SCULPT_mask_filter_smooth_apply(Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, const int smooth_iterations)
void SCULPT_filter_cache_free(SculptSession *ss)
void SCULPT_undo_push_begin(struct Object *ob, const char *name)
Definition: sculpt_undo.c:1545
void SCULPT_undo_push_end(struct Object *ob)
Definition: sculpt_undo.c:1575
#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
@ SCULPT_UPDATE_MASK
Definition: sculpt_intern.h:46
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
SculptUndoNode * SCULPT_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt_undo.c:1419
@ SCULPT_UNDO_FACE_SETS
@ SCULPT_UNDO_MASK
static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static bool mask_expand_floodfill_cb(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
struct MaskExpandFloodFillData MaskExpandFloodFillData
static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void sculpt_expand_task_cb(void *__restrict userdata, const int i, const TaskParallelTLS *__restrict UNUSED(tls))
static void sculpt_mask_expand_cancel(bContext *C, wmOperator *op)
void SCULPT_OT_mask_expand(wmOperatorType *ot)
float * edge_factor
float * prev_mask
int * mask_update_it
float * normal_factor
int * prev_face_set
int mask_update_last_it
PBVHNode ** nodes
float mask_expand_initial_co[3]
int mask_update_current_it
struct SculptSession * sculpt
void * data
float * co
Definition: BKE_pbvh.h:430
float * mask
Definition: BKE_pbvh.h:433
int * face_sets
Definition: BKE_paint.h:536
float pivot_pos[3]
Definition: BKE_paint.h:612
struct FilterCache * filter_cache
Definition: BKE_paint.h:564
struct PBVH * pbvh
Definition: BKE_paint.h:550
short val
Definition: WM_types.h:680
int mval[2]
Definition: WM_types.h:684
uint8_t modifier
Definition: WM_types.h:693
short type
Definition: WM_types.h:678
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
PropertyRNA * prop
Definition: WM_types.h:981
struct PointerRNA * ptr
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
@ RIGHTMOUSE
@ EVT_RIGHTCTRLKEY
@ EVT_LEFTCTRLKEY
@ EVT_PADENTER
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_ESCKEY
@ EVT_RETKEY
wmOperatorType * ot
Definition: wm_files.c:3479