Cleanup: Use function pointers in sculpt gestures
This replaces the switch case and operation types with a SculptGestureOperation struct with callbacks. Reviewed By: sergey Differential Revision: https://developer.blender.org/D8798
This commit is contained in:
parent
985cc48fca
commit
587f75f009
|
@ -230,11 +230,6 @@ typedef enum eSculptGestureShapeType {
|
|||
SCULPT_GESTURE_SHAPE_LASSO,
|
||||
} eMaskGesturesShapeType;
|
||||
|
||||
typedef enum eSculptGestureOperationType {
|
||||
SCULPT_GESTURE_MASK,
|
||||
SCULPT_GESTURE_FACE_SET,
|
||||
} eSculptGestureOperationType;
|
||||
|
||||
typedef struct LassoGestureData {
|
||||
float projviewobjmat[4][4];
|
||||
|
||||
|
@ -245,6 +240,8 @@ typedef struct LassoGestureData {
|
|||
BLI_bitmap *mask_px;
|
||||
} LassoGestureData;
|
||||
|
||||
struct SculptGestureOperation;
|
||||
|
||||
typedef struct SculptGestureContext {
|
||||
SculptSession *ss;
|
||||
ViewContext vc;
|
||||
|
@ -255,15 +252,9 @@ typedef struct SculptGestureContext {
|
|||
|
||||
/* Operation parameters. */
|
||||
eMaskGesturesShapeType shape_type;
|
||||
eSculptGestureOperationType operation;
|
||||
bool front_faces_only;
|
||||
|
||||
/* Mask operation parameters. */
|
||||
PaintMaskFloodMode mask_mode;
|
||||
float mask_value;
|
||||
|
||||
/* Face Set operation parameters. */
|
||||
int new_face_set_id;
|
||||
struct SculptGestureOperation *operation;
|
||||
|
||||
/* View parameters. */
|
||||
float true_view_normal[3];
|
||||
|
@ -280,6 +271,18 @@ typedef struct SculptGestureContext {
|
|||
int totnode;
|
||||
} SculptGestureContext;
|
||||
|
||||
typedef struct SculptGestureOperation {
|
||||
/* Initial setup (data updates, special undo push...). */
|
||||
void (*sculpt_gesture_begin)(struct bContext *, SculptGestureContext *);
|
||||
|
||||
/* Apply the gesture action for each symmetry pass. */
|
||||
void (*sculpt_gesture_apply_for_symmetry_pass)(struct bContext *, SculptGestureContext *);
|
||||
|
||||
/* Remaining actions after finishing the symmetry passes iterations (updating datalayers, tagging
|
||||
* PBVH updates...) */
|
||||
void (*sculpt_gesture_end)(struct bContext *, SculptGestureContext *);
|
||||
} SculptGestureOperation;
|
||||
|
||||
static void sculpt_gesture_operator_properties(wmOperatorType *ot)
|
||||
{
|
||||
RNA_def_boolean(ot->srna,
|
||||
|
@ -393,6 +396,7 @@ static SculptGestureContext *sculpt_gesture_init_from_box(bContext *C, wmOperato
|
|||
static void sculpt_gesture_context_free(SculptGestureContext *sgcontext)
|
||||
{
|
||||
MEM_SAFE_FREE(sgcontext->lasso.mask_px);
|
||||
MEM_SAFE_FREE(sgcontext->operation);
|
||||
MEM_SAFE_FREE(sgcontext->nodes);
|
||||
MEM_SAFE_FREE(sgcontext);
|
||||
}
|
||||
|
@ -493,11 +497,126 @@ static bool sculpt_gesture_is_vertex_effected(SculptGestureContext *sgcontext, P
|
|||
return false;
|
||||
}
|
||||
|
||||
static void sculpt_gesture_apply(bContext *C, SculptGestureContext *sgcontext)
|
||||
{
|
||||
SculptGestureOperation *operation = sgcontext->operation;
|
||||
SCULPT_undo_push_begin("Sculpt Gesture Apply");
|
||||
|
||||
operation->sculpt_gesture_begin(C, sgcontext);
|
||||
|
||||
for (ePaintSymmetryFlags symmpass = 0; symmpass <= sgcontext->symm; symmpass++) {
|
||||
if (SCULPT_is_symmetry_iteration_valid(symmpass, sgcontext->symm)) {
|
||||
sculpt_gesture_flip_for_symmetry_pass(sgcontext, symmpass);
|
||||
sculpt_gesture_update_effected_nodes(sgcontext);
|
||||
|
||||
operation->sculpt_gesture_apply_for_symmetry_pass(C, sgcontext);
|
||||
|
||||
MEM_SAFE_FREE(sgcontext->nodes);
|
||||
}
|
||||
}
|
||||
|
||||
operation->sculpt_gesture_end(C, sgcontext);
|
||||
|
||||
SCULPT_undo_push_end();
|
||||
|
||||
ED_region_tag_redraw(sgcontext->vc.region);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, sgcontext->vc.obact);
|
||||
}
|
||||
|
||||
/* Face Set Gesture Operation. */
|
||||
|
||||
typedef struct SculptGestureFaceSetOperation {
|
||||
SculptGestureOperation op;
|
||||
|
||||
int new_face_set_id;
|
||||
} SculptGestureFaceSetOperation;
|
||||
|
||||
static void sculpt_gesture_face_set_begin(bContext *C, SculptGestureContext *sgcontext)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, sgcontext->vc.obact, true, false, false);
|
||||
|
||||
/* Face Sets modifications do a single undo push. */
|
||||
SCULPT_undo_push_node(sgcontext->vc.obact, NULL, SCULPT_UNDO_FACE_SETS);
|
||||
}
|
||||
|
||||
static void face_set_gesture_apply_task_cb(void *__restrict userdata,
|
||||
const int i,
|
||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
||||
{
|
||||
SculptGestureContext *sgcontext = userdata;
|
||||
SculptGestureFaceSetOperation *face_set_operation = (SculptGestureFaceSetOperation *)
|
||||
sgcontext->operation;
|
||||
PBVHNode *node = sgcontext->nodes[i];
|
||||
PBVHVertexIter vd;
|
||||
bool any_updated = false;
|
||||
|
||||
BKE_pbvh_vertex_iter_begin(sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
|
||||
{
|
||||
if (sculpt_gesture_is_vertex_effected(sgcontext, &vd)) {
|
||||
SCULPT_vertex_face_set_set(sgcontext->ss, vd.index, face_set_operation->new_face_set_id);
|
||||
any_updated = true;
|
||||
}
|
||||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
|
||||
if (any_updated) {
|
||||
BKE_pbvh_node_mark_update_visibility(node);
|
||||
}
|
||||
}
|
||||
|
||||
static void sculpt_gesture_face_set_apply_for_symmetry_pass(bContext *UNUSED(C),
|
||||
SculptGestureContext *sgcontext)
|
||||
{
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->totnode);
|
||||
BLI_task_parallel_range(
|
||||
0, sgcontext->totnode, sgcontext, face_set_gesture_apply_task_cb, &settings);
|
||||
}
|
||||
|
||||
static void sculpt_gesture_face_set_end(bContext *UNUSED(C), SculptGestureContext *sgcontext)
|
||||
{
|
||||
BKE_pbvh_update_vertex_data(sgcontext->ss->pbvh, PBVH_UpdateVisibility);
|
||||
}
|
||||
|
||||
static void sculpt_gesture_init_face_set_properties(SculptGestureContext *sgcontext,
|
||||
wmOperator *UNUSED(op))
|
||||
{
|
||||
struct Mesh *mesh = BKE_mesh_from_object(sgcontext->vc.obact);
|
||||
sgcontext->operation = MEM_callocN(sizeof(SculptGestureFaceSetOperation), "Face Set Operation");
|
||||
|
||||
SculptGestureFaceSetOperation *face_set_operation = (SculptGestureFaceSetOperation *)
|
||||
sgcontext->operation;
|
||||
|
||||
face_set_operation->op.sculpt_gesture_begin = sculpt_gesture_face_set_begin;
|
||||
face_set_operation->op.sculpt_gesture_apply_for_symmetry_pass =
|
||||
sculpt_gesture_face_set_apply_for_symmetry_pass;
|
||||
face_set_operation->op.sculpt_gesture_end = sculpt_gesture_face_set_end;
|
||||
|
||||
face_set_operation->new_face_set_id = ED_sculpt_face_sets_find_next_available_id(mesh);
|
||||
}
|
||||
|
||||
/* Mask Gesture Operation. */
|
||||
|
||||
typedef struct SculptGestureMaskOperation {
|
||||
SculptGestureOperation op;
|
||||
|
||||
PaintMaskFloodMode mode;
|
||||
float value;
|
||||
} SculptGestureMaskOperation;
|
||||
|
||||
static void sculpt_gesture_mask_begin(bContext *C, SculptGestureContext *sgcontext)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, sgcontext->vc.obact, false, true, false);
|
||||
}
|
||||
|
||||
static void mask_gesture_apply_task_cb(void *__restrict userdata,
|
||||
const int i,
|
||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
||||
{
|
||||
SculptGestureContext *sgcontext = userdata;
|
||||
SculptGestureMaskOperation *mask_operation = (SculptGestureMaskOperation *)sgcontext->operation;
|
||||
Object *ob = sgcontext->vc.obact;
|
||||
PBVHNode *node = sgcontext->nodes[i];
|
||||
|
||||
|
@ -520,7 +639,7 @@ static void mask_gesture_apply_task_cb(void *__restrict userdata,
|
|||
BKE_pbvh_node_mark_normals_update(node);
|
||||
}
|
||||
}
|
||||
mask_flood_fill_set_elem(vd.mask, sgcontext->mask_mode, sgcontext->mask_value);
|
||||
mask_flood_fill_set_elem(vd.mask, mask_operation->mode, mask_operation->value);
|
||||
if (prevmask != *vd.mask) {
|
||||
redraw = true;
|
||||
}
|
||||
|
@ -533,100 +652,36 @@ static void mask_gesture_apply_task_cb(void *__restrict userdata,
|
|||
}
|
||||
}
|
||||
|
||||
static void face_set_gesture_apply_task_cb(void *__restrict userdata,
|
||||
const int i,
|
||||
const TaskParallelTLS *__restrict UNUSED(tls))
|
||||
static void sculpt_gesture_mask_apply_for_symmetry_pass(bContext *UNUSED(C),
|
||||
SculptGestureContext *sgcontext)
|
||||
{
|
||||
SculptGestureContext *sgcontext = userdata;
|
||||
PBVHNode *node = sgcontext->nodes[i];
|
||||
PBVHVertexIter vd;
|
||||
bool any_updated = false;
|
||||
|
||||
BKE_pbvh_vertex_iter_begin(sgcontext->ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
|
||||
{
|
||||
if (sculpt_gesture_is_vertex_effected(sgcontext, &vd)) {
|
||||
SCULPT_vertex_face_set_set(sgcontext->ss, vd.index, sgcontext->new_face_set_id);
|
||||
any_updated = true;
|
||||
}
|
||||
}
|
||||
BKE_pbvh_vertex_iter_end;
|
||||
|
||||
if (any_updated) {
|
||||
BKE_pbvh_node_mark_update_visibility(node);
|
||||
}
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, sgcontext->totnode);
|
||||
BLI_task_parallel_range(0, sgcontext->totnode, sgcontext, mask_gesture_apply_task_cb, &settings);
|
||||
}
|
||||
|
||||
static void sculpt_gesture_apply(bContext *C, SculptGestureContext *mcontext)
|
||||
static void sculpt_gesture_mask_end(bContext *C, SculptGestureContext *sgcontext)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
|
||||
const bool needs_mask = mcontext->operation == SCULPT_GESTURE_MASK;
|
||||
const bool needs_connectivity = mcontext->operation == SCULPT_GESTURE_FACE_SET;
|
||||
|
||||
BKE_sculpt_update_object_for_edit(
|
||||
depsgraph, mcontext->vc.obact, needs_connectivity, needs_mask, false);
|
||||
|
||||
SCULPT_undo_push_begin("Sculpt Gesture Apply");
|
||||
|
||||
if (mcontext->operation == SCULPT_GESTURE_FACE_SET) {
|
||||
/* Face Sets modifications do a single undo push. */
|
||||
SCULPT_undo_push_node(mcontext->vc.obact, NULL, SCULPT_UNDO_FACE_SETS);
|
||||
if (BKE_pbvh_type(sgcontext->ss->pbvh) == PBVH_GRIDS) {
|
||||
multires_mark_as_modified(depsgraph, sgcontext->vc.obact, MULTIRES_COORDS_MODIFIED);
|
||||
}
|
||||
|
||||
for (ePaintSymmetryFlags symmpass = 0; symmpass <= mcontext->symm; symmpass++) {
|
||||
if (SCULPT_is_symmetry_iteration_valid(symmpass, mcontext->symm)) {
|
||||
sculpt_gesture_flip_for_symmetry_pass(mcontext, symmpass);
|
||||
sculpt_gesture_update_effected_nodes(mcontext);
|
||||
|
||||
TaskParallelSettings settings;
|
||||
BKE_pbvh_parallel_range_settings(&settings, true, mcontext->totnode);
|
||||
switch (mcontext->operation) {
|
||||
case SCULPT_GESTURE_MASK:
|
||||
BLI_task_parallel_range(
|
||||
0, mcontext->totnode, mcontext, mask_gesture_apply_task_cb, &settings);
|
||||
break;
|
||||
case SCULPT_GESTURE_FACE_SET:
|
||||
BLI_task_parallel_range(
|
||||
0, mcontext->totnode, mcontext, face_set_gesture_apply_task_cb, &settings);
|
||||
break;
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(mcontext->nodes);
|
||||
}
|
||||
}
|
||||
|
||||
switch (mcontext->operation) {
|
||||
case SCULPT_GESTURE_MASK:
|
||||
if (BKE_pbvh_type(mcontext->ss->pbvh) == PBVH_GRIDS) {
|
||||
multires_mark_as_modified(depsgraph, mcontext->vc.obact, MULTIRES_COORDS_MODIFIED);
|
||||
}
|
||||
BKE_pbvh_update_vertex_data(mcontext->ss->pbvh, PBVH_UpdateMask);
|
||||
break;
|
||||
|
||||
case SCULPT_GESTURE_FACE_SET:
|
||||
BKE_pbvh_update_vertex_data(mcontext->ss->pbvh, PBVH_UpdateVisibility);
|
||||
break;
|
||||
}
|
||||
|
||||
SCULPT_undo_push_end();
|
||||
|
||||
ED_region_tag_redraw(mcontext->vc.region);
|
||||
WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, mcontext->vc.obact);
|
||||
}
|
||||
|
||||
static void sculpt_gesture_init_face_set_properties(SculptGestureContext *sgcontext,
|
||||
wmOperator *UNUSED(op))
|
||||
{
|
||||
sgcontext->operation = SCULPT_GESTURE_FACE_SET;
|
||||
struct Mesh *mesh = BKE_mesh_from_object(sgcontext->vc.obact);
|
||||
sgcontext->new_face_set_id = ED_sculpt_face_sets_find_next_available_id(mesh);
|
||||
BKE_pbvh_update_vertex_data(sgcontext->ss->pbvh, PBVH_UpdateMask);
|
||||
}
|
||||
|
||||
static void sculpt_gesture_init_mask_properties(SculptGestureContext *sgcontext, wmOperator *op)
|
||||
{
|
||||
sgcontext->operation = SCULPT_GESTURE_MASK;
|
||||
sgcontext->mask_mode = RNA_enum_get(op->ptr, "mode");
|
||||
sgcontext->mask_value = RNA_float_get(op->ptr, "value");
|
||||
sgcontext->operation = MEM_callocN(sizeof(SculptGestureFaceSetOperation), "Mask Operation");
|
||||
|
||||
SculptGestureMaskOperation *mask_operation = (SculptGestureMaskOperation *)sgcontext->operation;
|
||||
|
||||
mask_operation->op.sculpt_gesture_begin = sculpt_gesture_mask_begin;
|
||||
mask_operation->op.sculpt_gesture_apply_for_symmetry_pass =
|
||||
sculpt_gesture_mask_apply_for_symmetry_pass;
|
||||
mask_operation->op.sculpt_gesture_end = sculpt_gesture_mask_end;
|
||||
|
||||
mask_operation->mode = RNA_enum_get(op->ptr, "mode");
|
||||
mask_operation->value = RNA_float_get(op->ptr, "value");
|
||||
}
|
||||
|
||||
static void paint_mask_gesture_operator_properties(wmOperatorType *ot)
|
||||
|
|
Loading…
Reference in New Issue