Cleanup: Extract project gesture to separate file

This PR extracts the `SCULPT_OT_project_line_gesture` operator into its
own file and namespace out of the `paint_mask.cc` file and
`blender::ed::sculpt_paint::mask` namespace.

Pull Request: https://projects.blender.org/blender/blender/pulls/119394
This commit is contained in:
Sean Kim
2024-03-12 19:52:50 +01:00
committed by Hans Goudey
parent 40dbe99dd9
commit 08801e8930
5 changed files with 157 additions and 139 deletions
@@ -83,6 +83,7 @@ set(SRC
sculpt_paint_color.cc
sculpt_paint_image.cc
sculpt_pose.cc
sculpt_project.cc
sculpt_smooth.cc
sculpt_transform.cc
sculpt_trim.cc
@@ -664,100 +664,6 @@ static void paint_mask_gesture_operator_properties(wmOperatorType *ot)
1.0f);
}
/* Project Gesture Operation. */
struct SculptGestureProjectOperation {
gesture::Operation operation;
};
static void sculpt_gesture_project_begin(bContext &C, gesture::GestureData &gesture_data)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
}
static void project_line_gesture_apply_task(gesture::GestureData &gesture_data, PBVHNode *node)
{
PBVHVertexIter vd;
bool any_updated = false;
undo::push_node(gesture_data.vc.obact, node, undo::Type::Position);
BKE_pbvh_vertex_iter_begin (gesture_data.ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
float vertex_normal[3];
const float *co = SCULPT_vertex_co_get(gesture_data.ss, vd.vertex);
SCULPT_vertex_normal_get(gesture_data.ss, vd.vertex, vertex_normal);
if (!gesture::is_affected(gesture_data, co, vertex_normal)) {
continue;
}
float projected_pos[3];
closest_to_plane_v3(projected_pos, gesture_data.line.plane, vd.co);
float disp[3];
sub_v3_v3v3(disp, projected_pos, vd.co);
const float mask = vd.mask;
mul_v3_fl(disp, 1.0f - mask);
if (is_zero_v3(disp)) {
continue;
}
add_v3_v3(vd.co, disp);
any_updated = true;
}
BKE_pbvh_vertex_iter_end;
if (any_updated) {
BKE_pbvh_node_mark_update(node);
}
}
static void sculpt_gesture_project_apply_for_symmetry_pass(bContext & /*C*/,
gesture::GestureData &gesture_data)
{
switch (gesture_data.shape_type) {
case gesture::ShapeType::Line:
threading::parallel_for(gesture_data.nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
project_line_gesture_apply_task(gesture_data, gesture_data.nodes[i]);
}
});
break;
case gesture::ShapeType::Lasso:
case gesture::ShapeType::Box:
/* Gesture shape projection not implemented yet. */
BLI_assert(false);
break;
}
}
static void sculpt_gesture_project_end(bContext &C, gesture::GestureData &gesture_data)
{
SculptSession *ss = gesture_data.ss;
Sculpt *sd = CTX_data_tool_settings(&C)->sculpt;
if (ss->deform_modifiers_active || ss->shapekey_active) {
SCULPT_flush_stroke_deform(sd, gesture_data.vc.obact, true);
}
SCULPT_flush_update_step(&C, SCULPT_UPDATE_COORDS);
SCULPT_flush_update_done(&C, gesture_data.vc.obact, SCULPT_UPDATE_COORDS);
}
static void sculpt_gesture_init_project_properties(gesture::GestureData &gesture_data,
wmOperator & /*op*/)
{
gesture_data.operation = reinterpret_cast<gesture::Operation *>(
MEM_cnew<SculptGestureProjectOperation>(__func__));
SculptGestureProjectOperation *project_operation = (SculptGestureProjectOperation *)
gesture_data.operation;
project_operation->operation.begin = sculpt_gesture_project_begin;
project_operation->operation.apply_for_symmetry_pass =
sculpt_gesture_project_apply_for_symmetry_pass;
project_operation->operation.end = sculpt_gesture_project_end;
}
static int paint_mask_gesture_box_exec(bContext *C, wmOperator *op)
{
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_box(C, op);
@@ -791,28 +697,6 @@ static int paint_mask_gesture_line_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int project_line_gesture_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const View3D *v3d = CTX_wm_view3d(C);
const Base *base = CTX_data_active_base(C);
if (!BKE_base_is_visible(v3d, base)) {
return OPERATOR_CANCELLED;
}
return WM_gesture_straightline_active_side_invoke(C, op, event);
}
static int project_gesture_line_exec(bContext *C, wmOperator *op)
{
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_line(C, op);
if (!gesture_data) {
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_project_properties(*gesture_data, *op);
gesture::apply(*C, *gesture_data, *op);
return OPERATOR_FINISHED;
}
void PAINT_OT_mask_lasso_gesture(wmOperatorType *ot)
{
ot->name = "Mask Lasso Gesture";
@@ -876,23 +760,4 @@ void PAINT_OT_mask_line_gesture(wmOperatorType *ot)
paint_mask_gesture_operator_properties(ot);
}
void SCULPT_OT_project_line_gesture(wmOperatorType *ot)
{
ot->name = "Project Line Gesture";
ot->idname = "SCULPT_OT_project_line_gesture";
ot->description = "Project the geometry onto a plane defined by a line";
ot->invoke = project_line_gesture_invoke;
ot->modal = WM_gesture_straightline_oneshot_modal;
ot->exec = project_gesture_line_exec;
ot->poll = SCULPT_mode_poll_view3d;
ot->flag = OPTYPE_REGISTER;
/* Properties. */
WM_operator_properties_gesture_straightline(ot, WM_CURSOR_EDIT);
gesture::operator_properties(ot);
}
} // namespace blender::ed::sculpt_paint::mask
@@ -1781,10 +1781,8 @@ void apply(bContext &C, GestureData &gesture_data, wmOperator &op);
}
namespace blender::ed::sculpt_paint::mask {
namespace blender::ed::sculpt_paint::project {
void SCULPT_OT_project_line_gesture(wmOperatorType *ot);
}
namespace blender::ed::sculpt_paint::trim {
@@ -1319,7 +1319,7 @@ void ED_operatortypes_sculpt()
WM_operatortype_append(face_set::SCULPT_OT_face_set_box_gesture);
WM_operatortype_append(trim::SCULPT_OT_trim_box_gesture);
WM_operatortype_append(trim::SCULPT_OT_trim_lasso_gesture);
WM_operatortype_append(mask::SCULPT_OT_project_line_gesture);
WM_operatortype_append(project::SCULPT_OT_project_line_gesture);
WM_operatortype_append(SCULPT_OT_sample_color);
WM_operatortype_append(color::SCULPT_OT_color_filter);
@@ -0,0 +1,154 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "sculpt_intern.hh"
namespace blender::ed::sculpt_paint::project {
struct SculptGestureProjectOperation {
gesture::Operation operation;
};
static void sculpt_gesture_project_begin(bContext &C, gesture::GestureData &gesture_data)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(&C);
BKE_sculpt_update_object_for_edit(depsgraph, gesture_data.vc.obact, false);
}
static void project_line_gesture_apply_task(gesture::GestureData &gesture_data, PBVHNode *node)
{
PBVHVertexIter vd;
bool any_updated = false;
undo::push_node(gesture_data.vc.obact, node, undo::Type::Position);
BKE_pbvh_vertex_iter_begin (gesture_data.ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
float vertex_normal[3];
const float *co = SCULPT_vertex_co_get(gesture_data.ss, vd.vertex);
SCULPT_vertex_normal_get(gesture_data.ss, vd.vertex, vertex_normal);
if (!gesture::is_affected(gesture_data, co, vertex_normal)) {
continue;
}
float projected_pos[3];
closest_to_plane_v3(projected_pos, gesture_data.line.plane, vd.co);
float disp[3];
sub_v3_v3v3(disp, projected_pos, vd.co);
const float mask = vd.mask;
mul_v3_fl(disp, 1.0f - mask);
if (is_zero_v3(disp)) {
continue;
}
add_v3_v3(vd.co, disp);
any_updated = true;
}
BKE_pbvh_vertex_iter_end;
if (any_updated) {
BKE_pbvh_node_mark_update(node);
}
}
static void sculpt_gesture_project_apply_for_symmetry_pass(bContext & /*C*/,
gesture::GestureData &gesture_data)
{
switch (gesture_data.shape_type) {
case gesture::ShapeType::Line:
threading::parallel_for(gesture_data.nodes.index_range(), 1, [&](const IndexRange range) {
for (const int i : range) {
project_line_gesture_apply_task(gesture_data, gesture_data.nodes[i]);
}
});
break;
case gesture::ShapeType::Lasso:
case gesture::ShapeType::Box:
/* Gesture shape projection not implemented yet. */
BLI_assert(false);
break;
}
}
static void sculpt_gesture_project_end(bContext &C, gesture::GestureData &gesture_data)
{
SculptSession *ss = gesture_data.ss;
Sculpt *sd = CTX_data_tool_settings(&C)->sculpt;
if (ss->deform_modifiers_active || ss->shapekey_active) {
SCULPT_flush_stroke_deform(sd, gesture_data.vc.obact, true);
}
SCULPT_flush_update_step(&C, SCULPT_UPDATE_COORDS);
SCULPT_flush_update_done(&C, gesture_data.vc.obact, SCULPT_UPDATE_COORDS);
}
static void sculpt_gesture_init_project_properties(gesture::GestureData &gesture_data,
wmOperator & /*op*/)
{
gesture_data.operation = reinterpret_cast<gesture::Operation *>(
MEM_cnew<SculptGestureProjectOperation>(__func__));
SculptGestureProjectOperation *project_operation = (SculptGestureProjectOperation *)
gesture_data.operation;
project_operation->operation.begin = sculpt_gesture_project_begin;
project_operation->operation.apply_for_symmetry_pass =
sculpt_gesture_project_apply_for_symmetry_pass;
project_operation->operation.end = sculpt_gesture_project_end;
}
static int project_line_gesture_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const View3D *v3d = CTX_wm_view3d(C);
const Base *base = CTX_data_active_base(C);
if (!BKE_base_is_visible(v3d, base)) {
return OPERATOR_CANCELLED;
}
return WM_gesture_straightline_active_side_invoke(C, op, event);
}
static int project_gesture_line_exec(bContext *C, wmOperator *op)
{
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_line(C, op);
if (!gesture_data) {
return OPERATOR_CANCELLED;
}
sculpt_gesture_init_project_properties(*gesture_data, *op);
gesture::apply(*C, *gesture_data, *op);
return OPERATOR_FINISHED;
}
void SCULPT_OT_project_line_gesture(wmOperatorType *ot)
{
ot->name = "Project Line Gesture";
ot->idname = "SCULPT_OT_project_line_gesture";
ot->description = "Project the geometry onto a plane defined by a line";
ot->invoke = project_line_gesture_invoke;
ot->modal = WM_gesture_straightline_oneshot_modal;
ot->exec = project_gesture_line_exec;
ot->poll = SCULPT_mode_poll_view3d;
ot->flag = OPTYPE_REGISTER;
/* Properties. */
WM_operator_properties_gesture_straightline(ot, WM_CURSOR_EDIT);
gesture::operator_properties(ot);
}
} // namespace blender::ed::sculpt_paint::project