mirror of
https://projects.blender.org/blender/blender.git
synced 2025-01-22 15:32:15 -05:00
Curves: Curve Pen
This tool can be used to rapidly edit curves. The current set of functionalities for Bezier splines are as follows: The functionalities are divided into three versions of the operator: * Left-Click * Ctrl + Left-Click * Double Click All current functionalities and their defaults are as follows: * Extrude Point: Add a point connected to an existing point. Enabled for Left-Click. * Extrude Handle Type: Type of the handles of the extruded points. Can be either Vector or Auto. Defaults to Vector. * Delete Point: Delete existing point. Enabled for Ctrl + Left-Click. * Insert Point: Insert a point into a curve segment. Enabled for Ctrl + Left-Click. * Move Segment: Move curve segment. Enabled for Left-Click. * Select Point: Select a single point or handle at a time. Enabled for Left-Click. * Move point: Move existing points or handles. Enabled for Left-Click. * Close Spline: Close spline by clicking the endpoints consecutively. Defaults to True. * Close Spline Method: The condition for Close Spline to activate. Can be one of None, On Press or On Click. Defaults to On Click for Left-Click and None for the others. * None: Functionality is turned off. * On Press: Activate on mouse down. This makes it possible to move the handles by dragging immediately after closing the spline. * On Click: Activate on mouse release. This makes it possible to avoid triggering the Close Spline functionality by dragging afterward. * Toggle Vector: Toggle handle between Vector and Auto handle types. Enabled for Double Click on a handle. * Cycle Handle Type: Cycle between all four handle types. Enabled for Double Click on the middle point of a Bezier point. The keybindings for the following functionalities can be adjusted from the modal keymap * Free-Align Toggle: Toggle between Free and Align handle types. Defaults to Left Shift. Activated on hold. * Move Adjacent Handle: Move the closer handle of the adjacent vertex. Defaults to Left Ctrl. Activated on hold. * Move Entire: Move the entire point by moving by grabbing on the handle Defaults to Spacebar. Activated on hold. * Link Handles: Mirror the movement of one handle onto the other. Defaults to Right Ctrl. Activated on press. * Lock Handle Angle: Move the handle along its current angle. Defaults to Left Alt. Activated on hold. All the above functionalities, except for Move Segment and those that work with handles, work similarly in the case of Poly and NURBS splines. Reviewed By: HooglyBoogly, weasel, campbellbarton Differential Revision: http://developer.blender.org/D12155
This commit is contained in:
parent
1cdf8b19e5
commit
336082acba
17 changed files with 2078 additions and 74 deletions
|
@ -205,6 +205,7 @@ ForEachMacros:
|
|||
- FOREACH_SCENE_COLLECTION_BEGIN
|
||||
- FOREACH_SCENE_OBJECT_BEGIN
|
||||
- FOREACH_SELECTED_BASE_BEGIN
|
||||
- FOREACH_SELECTED_BEZT_BEGIN
|
||||
- FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN
|
||||
- FOREACH_SELECTED_OBJECT_BEGIN
|
||||
- FOREACH_TRANS_DATA_CONTAINER
|
||||
|
|
Binary file not shown.
BIN
release/datafiles/icons/ops.curve.pen.dat
Normal file
BIN
release/datafiles/icons/ops.curve.pen.dat
Normal file
Binary file not shown.
|
@ -1 +1 @@
|
|||
Subproject commit 2a5095eed3028e91624d27ca93e4c65f572b809d
|
||||
Subproject commit 716dc02ec30c0810513f7b4adc4ae865ae50c4e6
|
|
@ -1 +1 @@
|
|||
Subproject commit 67f1fbca1482d9d9362a4001332e785c3fd5d230
|
||||
Subproject commit 787ea78f7fa6f0373d80ba1247768402df93f8ad
|
|
@ -100,6 +100,7 @@ _km_hierarchy = [
|
|||
('Paint Stroke Modal', 'EMPTY', 'WINDOW', []),
|
||||
('Sculpt Expand Modal', 'EMPTY', 'WINDOW', []),
|
||||
('Paint Curve', 'EMPTY', 'WINDOW', []),
|
||||
('Curve Pen Modal Map', 'EMPTY', 'WINDOW', []),
|
||||
|
||||
('Object Non-modal', 'EMPTY', 'WINDOW', []), # mode change
|
||||
|
||||
|
|
|
@ -6158,6 +6158,25 @@ def km_sculpt_expand_modal(_params):
|
|||
return keymap
|
||||
|
||||
|
||||
def km_curve_pen_modal_map(_params):
|
||||
items = []
|
||||
keymap = (
|
||||
"Curve Pen Modal Map",
|
||||
{"space_type": 'EMPTY', "region_type": 'WINDOW', "modal": True},
|
||||
{"items": items},
|
||||
)
|
||||
|
||||
items.extend([
|
||||
("FREE_ALIGN_TOGGLE", {"type": 'LEFT_SHIFT', "value": 'ANY', "any": True}, None),
|
||||
("MOVE_ADJACENT", {"type": 'LEFT_CTRL', "value": 'ANY', "any": True}, None),
|
||||
("MOVE_ENTIRE", {"type": 'SPACE', "value": 'ANY', "any": True}, None),
|
||||
("LOCK_ANGLE", {"type": 'LEFT_ALT', "value": 'ANY', "any": True}, None),
|
||||
("LINK_HANDLES", {"type": 'RIGHT_CTRL', "value": 'PRESS', "any": True}, None),
|
||||
])
|
||||
|
||||
return keymap
|
||||
|
||||
|
||||
# Fallback for gizmos that don't have custom a custom key-map.
|
||||
def km_generic_gizmo(_params):
|
||||
keymap = (
|
||||
|
@ -7078,6 +7097,27 @@ def km_3d_view_tool_edit_curve_draw(params):
|
|||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_edit_curve_pen(params):
|
||||
return (
|
||||
"3D View Tool: Edit Curve, Curve Pen",
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
("curve.pen", {"type": params.tool_mouse, "value": 'PRESS'},
|
||||
{"properties": [
|
||||
("extrude_point", True),
|
||||
("move_segment", True),
|
||||
("select_point", True),
|
||||
("move_point", True),
|
||||
("close_spline_method", "ON_CLICK"),
|
||||
]}),
|
||||
("curve.pen", {"type": params.tool_mouse, "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("insert_point", True), ("delete_point", True)]}),
|
||||
("curve.pen", {"type": params.tool_mouse, "value": 'DOUBLE_CLICK'},
|
||||
{"properties": [("toggle_vector", True), ("cycle_handle_type", True),]}),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_3d_view_tool_edit_curve_tilt(params):
|
||||
return (
|
||||
"3D View Tool: Edit Curve, Tilt",
|
||||
|
@ -7882,6 +7922,7 @@ def generate_keymaps(params=None):
|
|||
km_view3d_dolly_modal(params),
|
||||
km_paint_stroke_modal(params),
|
||||
km_sculpt_expand_modal(params),
|
||||
km_curve_pen_modal_map(params),
|
||||
|
||||
# Gizmos.
|
||||
km_generic_gizmo(params),
|
||||
|
@ -7960,6 +8001,7 @@ def generate_keymaps(params=None):
|
|||
km_3d_view_tool_edit_mesh_rip_region(params),
|
||||
km_3d_view_tool_edit_mesh_rip_edge(params),
|
||||
km_3d_view_tool_edit_curve_draw(params),
|
||||
km_3d_view_tool_edit_curve_pen(params),
|
||||
km_3d_view_tool_edit_curve_radius(params),
|
||||
km_3d_view_tool_edit_curve_tilt(params),
|
||||
km_3d_view_tool_edit_curve_randomize(params),
|
||||
|
|
|
@ -1201,6 +1201,22 @@ class _defs_edit_curve:
|
|||
keymap=(),
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def pen():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("curve.pen")
|
||||
layout.prop(props, "close_spline")
|
||||
layout.prop(props, "extrude_handle")
|
||||
return dict(
|
||||
idname="builtin.pen",
|
||||
label="Curve Pen",
|
||||
cursor='CROSSHAIR',
|
||||
icon="ops.curve.pen",
|
||||
widget=None,
|
||||
keymap=(),
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def tilt():
|
||||
return dict(
|
||||
|
@ -2881,6 +2897,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
*_tools_default,
|
||||
None,
|
||||
_defs_edit_curve.draw,
|
||||
_defs_edit_curve.pen,
|
||||
(
|
||||
_defs_edit_curve.extrude,
|
||||
_defs_edit_curve.extrude_cursor,
|
||||
|
|
|
@ -25,6 +25,7 @@ set(SRC
|
|||
editcurve_paint.c
|
||||
editcurve_query.c
|
||||
editcurve_select.c
|
||||
editcurve_pen.c
|
||||
editcurve_undo.c
|
||||
editfont.c
|
||||
editfont_undo.c
|
||||
|
|
|
@ -131,6 +131,16 @@ void CURVE_OT_match_texture_space(struct wmOperatorType *ot);
|
|||
struct GHash *ED_curve_keyindex_hash_duplicate(struct GHash *keyindex);
|
||||
void ED_curve_keyindex_update_nurb(struct EditNurb *editnurb, struct Nurb *nu, struct Nurb *newnu);
|
||||
|
||||
/* exported for editcurve_pen.c */
|
||||
int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, View3D *v3d, const float location_init[3]);
|
||||
bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction);
|
||||
void ed_dissolve_bez_segment(BezTriple *bezt_prev,
|
||||
BezTriple *bezt_next,
|
||||
const Nurb *nu,
|
||||
const Curve *cu,
|
||||
const int span_len,
|
||||
const int span_step[2]);
|
||||
|
||||
/* helper functions */
|
||||
void ed_editnurb_translate_flag(struct ListBase *editnurb,
|
||||
uint8_t flag,
|
||||
|
@ -189,8 +199,23 @@ bool ED_curve_pick_vert(struct ViewContext *vc,
|
|||
struct BPoint **r_bp,
|
||||
short *r_handle,
|
||||
struct Base **r_base);
|
||||
/**
|
||||
* \param sel_dist_mul: A multiplier on the default select distance.
|
||||
*/
|
||||
bool ED_curve_pick_vert_ex(struct ViewContext *vc,
|
||||
short sel,
|
||||
float dist_px,
|
||||
struct Nurb **r_nurb,
|
||||
struct BezTriple **r_bezt,
|
||||
struct BPoint **r_bp,
|
||||
short *r_handle,
|
||||
struct Base **r_base);
|
||||
void ED_curve_nurb_vert_selected_find(
|
||||
Curve *cu, View3D *v3d, Nurb **r_nu, BezTriple **r_bezt, BPoint **r_bp);
|
||||
|
||||
/* editcurve_paint.c */
|
||||
void CURVE_OT_draw(struct wmOperatorType *ot);
|
||||
|
||||
/* editcurve_pen.c */
|
||||
void CURVE_OT_pen(struct wmOperatorType *ot);
|
||||
struct wmKeyMap *curve_pen_modal_keymap(struct wmKeyConfig *keyconf);
|
||||
|
|
|
@ -111,6 +111,7 @@ void ED_operatortypes_curve(void)
|
|||
WM_operatortype_append(CURVE_OT_spin);
|
||||
WM_operatortype_append(CURVE_OT_vertex_add);
|
||||
WM_operatortype_append(CURVE_OT_draw);
|
||||
WM_operatortype_append(CURVE_OT_pen);
|
||||
WM_operatortype_append(CURVE_OT_extrude);
|
||||
WM_operatortype_append(CURVE_OT_cyclic_toggle);
|
||||
|
||||
|
@ -150,4 +151,6 @@ void ED_keymap_curve(wmKeyConfig *keyconf)
|
|||
/* only set in editmode curve, by space_view3d listener */
|
||||
keymap = WM_keymap_ensure(keyconf, "Curve", 0, 0);
|
||||
keymap->poll = ED_operator_editsurfcurve;
|
||||
|
||||
curve_pen_modal_keymap(keyconf);
|
||||
}
|
||||
|
|
|
@ -4726,6 +4726,14 @@ void CURVE_OT_make_segment(wmOperatorType *ot)
|
|||
bool ED_curve_editnurb_select_pick(bContext *C,
|
||||
const int mval[2],
|
||||
const struct SelectPick_Params *params)
|
||||
{
|
||||
return ED_curve_editnurb_select_pick_ex(C, mval, 1.0f, params);
|
||||
}
|
||||
|
||||
bool ED_curve_editnurb_select_pick_ex(bContext *C,
|
||||
const int mval[2],
|
||||
const float sel_dist_mul,
|
||||
const struct SelectPick_Params *params)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
ViewContext vc;
|
||||
|
@ -4740,7 +4748,8 @@ bool ED_curve_editnurb_select_pick(bContext *C,
|
|||
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
||||
copy_v2_v2_int(vc.mval, mval);
|
||||
|
||||
bool found = ED_curve_pick_vert(&vc, 1, &nu, &bezt, &bp, &hand, &basact);
|
||||
bool found = ED_curve_pick_vert_ex(
|
||||
&vc, 1, sel_dist_mul * ED_view3d_select_dist_px(), &nu, &bezt, &bp, &hand, &basact);
|
||||
|
||||
if (params->sel_op == SEL_OP_SET) {
|
||||
if ((found && params->select_passthrough) &&
|
||||
|
@ -5344,10 +5353,7 @@ static bool ed_editcurve_extrude(Curve *cu, EditNurb *editnurb, View3D *v3d)
|
|||
/** \name Add Vertex Operator
|
||||
* \{ */
|
||||
|
||||
static int ed_editcurve_addvert(Curve *cu,
|
||||
EditNurb *editnurb,
|
||||
View3D *v3d,
|
||||
const float location_init[3])
|
||||
int ed_editcurve_addvert(Curve *cu, EditNurb *editnurb, View3D *v3d, const float location_init[3])
|
||||
{
|
||||
float center[3];
|
||||
float temp[3];
|
||||
|
@ -5719,7 +5725,7 @@ void CURVE_OT_extrude(wmOperatorType *ot)
|
|||
/** \name Make Cyclic Operator
|
||||
* \{ */
|
||||
|
||||
static bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction)
|
||||
bool curve_toggle_cyclic(View3D *v3d, ListBase *editnurb, int direction)
|
||||
{
|
||||
BezTriple *bezt;
|
||||
BPoint *bp;
|
||||
|
@ -6502,45 +6508,17 @@ static bool test_bezt_is_sel_any(const void *bezt_v, void *user_data)
|
|||
return BEZT_ISSEL_ANY_HIDDENHANDLES(v3d, bezt);
|
||||
}
|
||||
|
||||
static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
void ed_dissolve_bez_segment(BezTriple *bezt_prev,
|
||||
BezTriple *bezt_next,
|
||||
const Nurb *nu,
|
||||
const Curve *cu,
|
||||
const int span_len,
|
||||
const int span_step[2])
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
uint objects_len;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
view_layer, CTX_wm_view3d(C), &objects_len);
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
Curve *cu = (Curve *)obedit->data;
|
||||
|
||||
if (!ED_curve_select_check(v3d, cu->editnurb)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ListBase *editnurb = object_editcurve_get(obedit);
|
||||
|
||||
LISTBASE_FOREACH (Nurb *, nu, editnurb) {
|
||||
if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) {
|
||||
uint span_step[2] = {nu->pntsu, nu->pntsu};
|
||||
uint span_len;
|
||||
|
||||
while (BLI_array_iter_span(nu->bezt,
|
||||
nu->pntsu,
|
||||
(nu->flagu & CU_NURB_CYCLIC) != 0,
|
||||
false,
|
||||
test_bezt_is_sel_any,
|
||||
v3d,
|
||||
span_step,
|
||||
&span_len)) {
|
||||
BezTriple *bezt_prev = &nu->bezt[mod_i(span_step[0] - 1, nu->pntsu)];
|
||||
BezTriple *bezt_next = &nu->bezt[mod_i(span_step[1] + 1, nu->pntsu)];
|
||||
|
||||
int i_span_edge_len = span_len + 1;
|
||||
const uint dims = 3;
|
||||
const int dims = 3;
|
||||
|
||||
const uint points_len = ((cu->resolu - 1) * i_span_edge_len) + 1;
|
||||
const int points_len = ((cu->resolu - 1) * i_span_edge_len) + 1;
|
||||
float *points = MEM_mallocN(points_len * dims * sizeof(float), __func__);
|
||||
float *points_stride = points;
|
||||
const int points_stride_len = (cu->resolu - 1);
|
||||
|
@ -6593,6 +6571,44 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
|
|||
|
||||
MEM_freeN(points);
|
||||
}
|
||||
|
||||
static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
|
||||
uint objects_len;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
view_layer, CTX_wm_view3d(C), &objects_len);
|
||||
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||
Object *obedit = objects[ob_index];
|
||||
Curve *cu = (Curve *)obedit->data;
|
||||
|
||||
if (!ED_curve_select_check(v3d, cu->editnurb)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ListBase *editnurb = object_editcurve_get(obedit);
|
||||
|
||||
LISTBASE_FOREACH (Nurb *, nu, editnurb) {
|
||||
if ((nu->type == CU_BEZIER) && (nu->pntsu > 2)) {
|
||||
int span_step[2] = {nu->pntsu, nu->pntsu};
|
||||
int span_len;
|
||||
|
||||
while (BLI_array_iter_span(nu->bezt,
|
||||
nu->pntsu,
|
||||
(nu->flagu & CU_NURB_CYCLIC) != 0,
|
||||
false,
|
||||
test_bezt_is_sel_any,
|
||||
v3d,
|
||||
span_step,
|
||||
&span_len)) {
|
||||
BezTriple *bezt_prev = &nu->bezt[mod_i(span_step[0] - 1, nu->pntsu)];
|
||||
BezTriple *bezt_next = &nu->bezt[mod_i(span_step[1] + 1, nu->pntsu)];
|
||||
|
||||
ed_dissolve_bez_segment(bezt_prev, bezt_next, nu, cu, span_len, span_step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1877
source/blender/editors/curve/editcurve_pen.c
Normal file
1877
source/blender/editors/curve/editcurve_pen.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -88,8 +88,9 @@ static void ED_curve_pick_vert__do_closest(void *userData,
|
|||
UNUSED_VARS_NDEBUG(handles_visible);
|
||||
}
|
||||
|
||||
bool ED_curve_pick_vert(ViewContext *vc,
|
||||
bool ED_curve_pick_vert_ex(ViewContext *vc,
|
||||
short sel,
|
||||
float dist_px,
|
||||
Nurb **r_nurb,
|
||||
BezTriple **r_bezt,
|
||||
BPoint **r_bp,
|
||||
|
@ -109,7 +110,7 @@ bool ED_curve_pick_vert(ViewContext *vc,
|
|||
bool is_changed;
|
||||
} data = {NULL};
|
||||
|
||||
data.dist = ED_view3d_select_dist_px();
|
||||
data.dist = dist_px;
|
||||
data.hpoint = 0;
|
||||
data.select = sel;
|
||||
data.mval_fl[0] = vc->mval[0];
|
||||
|
@ -143,6 +144,18 @@ bool ED_curve_pick_vert(ViewContext *vc,
|
|||
return (data.bezt || data.bp);
|
||||
}
|
||||
|
||||
bool ED_curve_pick_vert(ViewContext *vc,
|
||||
short sel,
|
||||
Nurb **r_nurb,
|
||||
BezTriple **r_bezt,
|
||||
BPoint **r_bp,
|
||||
short *r_handle,
|
||||
Base **r_base)
|
||||
{
|
||||
return ED_curve_pick_vert_ex(
|
||||
vc, sel, ED_view3d_select_dist_px(), r_nurb, r_bezt, r_bp, r_handle, r_base);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -765,6 +765,7 @@ set_property(GLOBAL PROPERTY ICON_GEOM_NAMES
|
|||
ops.armature.extrude_cursor
|
||||
ops.armature.extrude_move
|
||||
ops.curve.draw
|
||||
ops.curve.pen
|
||||
ops.curve.extrude_cursor
|
||||
ops.curve.extrude_move
|
||||
ops.curve.radius
|
||||
|
|
|
@ -53,6 +53,13 @@ void ED_curve_editnurb_free(struct Object *obedit);
|
|||
bool ED_curve_editnurb_select_pick(struct bContext *C,
|
||||
const int mval[2],
|
||||
const struct SelectPick_Params *params);
|
||||
/**
|
||||
* \param sel_dist_mul: A multiplier on the default select distance.
|
||||
*/
|
||||
bool ED_curve_editnurb_select_pick_ex(struct bContext *C,
|
||||
const int mval[2],
|
||||
const float sel_dist_mul,
|
||||
const struct SelectPick_Params *params);
|
||||
|
||||
struct Nurb *ED_curve_add_nurbs_primitive(
|
||||
struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob);
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7fd2ed908b4f50140670caf6786e5ed245b79137
|
||||
Subproject commit 1e658ca996f11e5ff3398d89bd81f5b719304a57
|
Loading…
Reference in a new issue