Sculpt: Add Line Trim tool #120845
|
@ -8009,6 +8009,16 @@ def km_3d_view_tool_sculpt_lasso_trim(params):
|
|||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_sculpt_line_trim(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt, Line Trim",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("sculpt.trim_line_gesture", params.tool_maybe_tweak_event, None),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_sculpt_line_mask(params):
|
||||
return (
|
||||
"3D View Tool: Sculpt, Line Mask",
|
||||
|
@ -8798,6 +8808,7 @@ def generate_keymaps(params=None):
|
|||
km_3d_view_tool_sculpt_lasso_face_set(params),
|
||||
km_3d_view_tool_sculpt_box_trim(params),
|
||||
km_3d_view_tool_sculpt_lasso_trim(params),
|
||||
km_3d_view_tool_sculpt_line_trim(params),
|
||||
km_3d_view_tool_sculpt_line_mask(params),
|
||||
km_3d_view_tool_sculpt_line_project(params),
|
||||
km_3d_view_tool_sculpt_mesh_filter(params),
|
||||
|
|
|
@ -1543,6 +1543,23 @@ class _defs_sculpt:
|
|||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def trim_line():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("sculpt.trim_line_gesture")
|
||||
layout.prop(props, "trim_solver", expand=False)
|
||||
layout.prop(props, "trim_orientation", expand=False)
|
||||
layout.prop(props, "use_cursor_depth", expand=False)
|
||||
layout.prop(props, "use_limit_to_segment", expand=False)
|
||||
return dict(
|
||||
idname="builtin.line_trim",
|
||||
label="Line Trim",
|
||||
icon="ops.sculpt.line_trim",
|
||||
widget=None,
|
||||
keymap=(),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def project_line():
|
||||
def draw_settings(_context, layout, tool):
|
||||
|
@ -3173,6 +3190,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
(
|
||||
_defs_sculpt.trim_box,
|
||||
_defs_sculpt.trim_lasso,
|
||||
_defs_sculpt.trim_line,
|
||||
),
|
||||
_defs_sculpt.project_line,
|
||||
None,
|
||||
|
|
|
@ -3690,6 +3690,9 @@ class VIEW3D_MT_sculpt(Menu):
|
|||
props = layout.operator("sculpt.trim_lasso_gesture", text="Lasso Trim")
|
||||
props.trim_mode = 'DIFFERENCE'
|
||||
|
||||
props = layout.operator("sculpt.trim_line_gesture", text="Line Trim")
|
||||
props.trim_mode = 'DIFFERENCE'
|
||||
|
||||
props = layout.operator("sculpt.trim_box_gesture", text="Box Add")
|
||||
props.trim_mode = 'JOIN'
|
||||
|
||||
|
|
|
@ -230,6 +230,12 @@ std::unique_ptr<GestureData> init_from_line(bContext *C, wmOperator *op)
|
|||
line_points[1][0] = RNA_int_get(op->ptr, "xend");
|
||||
line_points[1][1] = RNA_int_get(op->ptr, "yend");
|
||||
|
||||
gesture_data->gesture_points.reinitialize(2);
|
||||
gesture_data->gesture_points[0][0] = line_points[0][0];
|
||||
gesture_data->gesture_points[0][1] = line_points[0][1];
|
||||
gesture_data->gesture_points[1][0] = line_points[1][0];
|
||||
gesture_data->gesture_points[1][1] = line_points[1][1];
|
||||
|
||||
gesture_data->line.flip = RNA_boolean_get(op->ptr, "flip");
|
||||
|
||||
float plane_points[4][3];
|
||||
|
|
|
@ -1784,6 +1784,7 @@ void SCULPT_OT_project_line_gesture(wmOperatorType *ot);
|
|||
namespace blender::ed::sculpt_paint::trim {
|
||||
void SCULPT_OT_trim_lasso_gesture(wmOperatorType *ot);
|
||||
void SCULPT_OT_trim_box_gesture(wmOperatorType *ot);
|
||||
void SCULPT_OT_trim_line_gesture(wmOperatorType *ot);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -1323,6 +1323,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(trim::SCULPT_OT_trim_line_gesture);
|
||||
WM_operatortype_append(project::SCULPT_OT_project_line_gesture);
|
||||
|
||||
WM_operatortype_append(SCULPT_OT_sample_color);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "BLI_math_geom.h"
|
||||
#include "BLI_math_matrix.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_math_vector.hh"
|
||||
#include "BLI_polyfill_2d.h"
|
||||
|
||||
#include "BKE_brush.hh"
|
||||
|
@ -17,6 +18,7 @@
|
|||
#include "BKE_layer.hh"
|
||||
#include "BKE_lib_id.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_object.hh"
|
||||
|
||||
#include "DNA_modifier_types.h"
|
||||
|
||||
|
@ -274,13 +276,65 @@ static void calculate_depth(gesture::GestureData &gesture_data,
|
|||
r_depth_back = depth_back;
|
||||
}
|
||||
|
||||
/* Calculates a scalar factor to use to ensure a drawn line gesture
|
||||
* encompasses the entire object to be acted on. */
|
||||
static float calc_expand_factor(const gesture::GestureData &gesture_data)
|
||||
{
|
||||
Object *object = gesture_data.vc.obact;
|
||||
|
||||
rcti rect;
|
||||
const Bounds<float3> bounds = *BKE_object_boundbox_get(object);
|
||||
paint_convert_bb_to_rect(
|
||||
&rect, bounds.min, bounds.max, gesture_data.vc.region, gesture_data.vc.rv3d, object);
|
||||
|
||||
const float2 min_corner(rect.xmin, rect.ymin);
|
||||
const float2 max_corner(rect.xmax, rect.ymax);
|
||||
|
||||
/* Mutiply the screen space bounds by an arbitrary factor to ensure the created points are
|
||||
* sufficiently far and enclose the mesh to be operated on. */
|
||||
return math::distance(min_corner, max_corner) * 2.0f;
|
||||
}
|
||||
|
||||
/* Converts a gesture's points into usable screen points. */
|
||||
static Span<float2> gesture_to_screen_points(gesture::GestureData &gesture_data)
|
||||
{
|
||||
if (gesture_data.shape_type != gesture::ShapeType::Line) {
|
||||
return gesture_data.gesture_points;
|
||||
}
|
||||
|
||||
const float expand_factor = calc_expand_factor(gesture_data);
|
||||
|
||||
float2 start(gesture_data.gesture_points[0]);
|
||||
float2 end(gesture_data.gesture_points[1]);
|
||||
|
||||
const float2 dir = math::normalize(end - start);
|
||||
|
||||
if (!gesture_data.line.use_side_planes) {
|
||||
end = end + dir * expand_factor;
|
||||
start = start - dir * expand_factor;
|
||||
}
|
||||
|
||||
float2 perp(dir.y, -dir.x);
|
||||
|
||||
if (gesture_data.line.flip) {
|
||||
perp *= -1;
|
||||
}
|
||||
|
||||
const float2 parallel_start = start + perp * expand_factor;
|
||||
const float2 parallel_end = end + perp * expand_factor;
|
||||
|
||||
const Array<float2> result = {{start, end, parallel_end, parallel_start}};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void generate_geometry(gesture::GestureData &gesture_data)
|
||||
{
|
||||
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
|
||||
Sean-Kim marked this conversation as resolved
Outdated
|
||||
ViewContext *vc = &gesture_data.vc;
|
||||
ARegion *region = vc->region;
|
||||
|
||||
const Span<float2> screen_points = gesture_data.gesture_points;
|
||||
const Span<float2> screen_points = gesture_to_screen_points(gesture_data);
|
||||
BLI_assert(screen_points.size() > 1);
|
||||
|
||||
const int trim_totverts = screen_points.size() * 2;
|
||||
|
@ -614,6 +668,11 @@ static void init_operation(gesture::GestureData &gesture_data, wmOperator &op)
|
|||
if (!trim_operation->initial_hit) {
|
||||
trim_operation->orientation = OrientationType::View;
|
||||
}
|
||||
|
||||
if (gesture_data.shape_type == gesture::ShapeType::Line) {
|
||||
/* Line gestures only support Difference, no extrusion. */
|
||||
trim_operation->mode = OperationType::Difference;
|
||||
}
|
||||
}
|
||||
|
||||
static void operator_properties(wmOperatorType *ot)
|
||||
|
@ -773,6 +832,37 @@ static int gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *even
|
|||
return WM_gesture_lasso_invoke(C, op, event);
|
||||
}
|
||||
|
||||
static int gesture_line_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
if (!can_exec(*C)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
std::unique_ptr<gesture::GestureData> gesture_data = gesture::init_from_line(C, op);
|
||||
if (!gesture_data) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
gesture_data->operation = reinterpret_cast<gesture::Operation *>(
|
||||
MEM_cnew<TrimOperation>(__func__));
|
||||
|
||||
initialize_cursor_info(*C, *op, *gesture_data);
|
||||
init_operation(*gesture_data, *op);
|
||||
gesture::apply(*C, *gesture_data, *op);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int gesture_line_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
if (!can_invoke(*C)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
RNA_int_set_array(op->ptr, "location", event->mval);
|
||||
|
||||
return WM_gesture_straightline_active_side_invoke(C, op, event);
|
||||
}
|
||||
|
||||
void SCULPT_OT_trim_lasso_gesture(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Trim Lasso Gesture";
|
||||
|
@ -814,4 +904,25 @@ void SCULPT_OT_trim_box_gesture(wmOperatorType *ot)
|
|||
|
||||
operator_properties(ot);
|
||||
}
|
||||
|
||||
void SCULPT_OT_trim_line_gesture(wmOperatorType *ot)
|
||||
{
|
||||
ot->name = "Trim Line Gesture";
|
||||
ot->idname = "SCULPT_OT_trim_line_gesture";
|
||||
ot->description = "Trims the mesh divided by the line as you move the brush";
|
||||
|
||||
ot->invoke = gesture_line_invoke;
|
||||
ot->modal = WM_gesture_straightline_oneshot_modal;
|
||||
ot->exec = 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, gesture::ShapeType::Line);
|
||||
|
||||
operator_properties(ot);
|
||||
}
|
||||
} // namespace blender::ed::sculpt_paint::trim
|
||||
|
|
|
@ -4135,6 +4135,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf)
|
|||
WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient");
|
||||
WM_modalkeymap_assign(keymap, "MESH_OT_bisect");
|
||||
WM_modalkeymap_assign(keymap, "PAINT_OT_mask_line_gesture");
|
||||
WM_modalkeymap_assign(keymap, "SCULPT_OT_trim_line_gesture");
|
||||
WM_modalkeymap_assign(keymap, "SCULPT_OT_project_line_gesture");
|
||||
WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show_line_gesture");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
This handling of the
line_points
as looks rather awkward to me as it currently is, but I wasn't able to think of a good way of handling this. Another alternative here could be to modify the internalGestureData
blender::Array
in the aboveline_gesture_to_screen_points
but that also had a code smell. Any thoughts on a good approach here?I think this is fine. But another potentially simpler solution would be changing
const Span<float2> screen_points
toArray<float2>
. The copying shouldn't really matter here.