GPencil: Primitive: Polyline Tool

T70927

Maniphest Tasks: T70927

Differential Revision: https://developer.blender.org/D6097
This commit is contained in:
Charlie Jolly 2019-10-18 22:02:45 +01:00 committed by Charlie Jolly
parent 3de4446959
commit c2a2cd13be
Notes: blender-bot 2023-02-14 10:37:50 +01:00
Referenced by issue #70962, Render image / render animation crash with OptiX enabled (works with CUDA)
10 changed files with 248 additions and 72 deletions

@ -1 +1 @@
Subproject commit 88497d7507e76281fbdd0cc1f8451f81ae7e3785
Subproject commit 6a6b84fd50538a65276c729b5d396be615bc79f2

@ -1 +1 @@
Subproject commit 0ec4a4fd2ac1a9a0aaf550ced7e4b445a340ca4e
Subproject commit 46b1ada7f5f2d396f712e9a1376922ca89475486

@ -1 +1 @@
Subproject commit 69bcc72f1ec4df73265ce35851658ef184b9d0f9
Subproject commit b5e801446c820e7f5725e2e09f8c2a12a4449f45

View File

@ -5793,6 +5793,19 @@ def km_3d_view_tool_paint_gpencil_line(params):
]},
)
def km_3d_view_tool_paint_gpencil_polyline(params):
return (
"3D View Tool: Paint Gpencil, Polyline",
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
{"items": [
("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'},
{"properties": [("type", 'POLYLINE'), ("wait_for_input", False)]}),
("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True},
{"properties": [("type", 'POLYLINE'), ("wait_for_input", False)]}),
# Lasso select
("gpencil.select_lasso", {"type": params.action_tweak, "value": 'ANY', "ctrl": True, "alt": True}, None),
]},
)
def km_3d_view_tool_paint_gpencil_box(params):
return (
@ -6214,6 +6227,7 @@ def generate_keymaps(params=None):
km_3d_view_tool_paint_weight_sample_vertex_group(params),
km_3d_view_tool_paint_weight_gradient(params),
km_3d_view_tool_paint_gpencil_line(params),
km_3d_view_tool_paint_gpencil_polyline(params),
km_3d_view_tool_paint_gpencil_box(params),
km_3d_view_tool_paint_gpencil_circle(params),
km_3d_view_tool_paint_gpencil_arc(params),

View File

@ -420,7 +420,7 @@ def brush_basic_gpencil_paint_settings(layout, _context, brush, tool, *, compact
row.prop(gp_settings, "pen_strength", slider=True)
row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.circle"}:
if tool.idname in {"builtin.arc", "builtin.curve", "builtin.line", "builtin.box", "builtin.circle", "builtin.polyline"}:
settings = _context.tool_settings.gpencil_sculpt
if is_toolbar:
row = layout.row(align=True)

View File

@ -1348,6 +1348,17 @@ class _defs_gpencil_paint:
keymap=(),
)
@ToolDef.from_fn
def polyline():
return dict(
idname="builtin.polyline",
label="Polyline",
icon="ops.gpencil.primitive_polyline",
cursor='CROSSHAIR',
widget=None,
keymap=(),
)
@ToolDef.from_fn
def box():
return dict(
@ -1390,7 +1401,7 @@ class _defs_gpencil_paint:
cursor='CROSSHAIR',
widget=None,
keymap=(),
)
)
@ToolDef.from_fn
def eyedropper():
@ -2058,6 +2069,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_gpencil_paint.eyedropper,
None,
_defs_gpencil_paint.line,
_defs_gpencil_paint.polyline,
_defs_gpencil_paint.arc,
_defs_gpencil_paint.curve,
_defs_gpencil_paint.box,

View File

@ -298,7 +298,7 @@ class _draw_tool_settings_context_mode:
# is_paint = True
# FIXME: tools must use their own UI drawing!
if tool.idname in {"builtin.line", "builtin.box", "builtin.circle", "builtin.arc", "builtin.curve"}:
if tool.idname in {"builtin.line", "builtin.box", "builtin.circle", "builtin.arc", "builtin.curve","builtin.polyline"}:
# is_paint = False
pass
elif tool.idname == "Cutter":

View File

@ -214,6 +214,8 @@ typedef struct tGPDprimitive {
int sel_cp;
/** flag to determine operations in progress */
int flag;
/** flag to determine operations previous mode */
int prev_flag;
/** recorded mouse-position */
float mval[2];
/** previous recorded mouse-position */
@ -465,6 +467,7 @@ enum {
GP_STROKE_CIRCLE = 2,
GP_STROKE_ARC = 3,
GP_STROKE_CURVE = 4,
GP_STROKE_POLYLINE = 5,
};
enum {

View File

@ -90,6 +90,7 @@
#define IN_MOVE 3
#define IN_BRUSH_SIZE 4
#define IN_BRUSH_STRENGTH 5
#define IN_POLYLINE 6
#define SELECT_NONE 0
#define SELECT_START 1
@ -184,6 +185,29 @@ static void gpencil_primitive_to_square(tGPDprimitive *tgpi, const float x, cons
}
}
/* Helper to constrain a primitive */
static void gpencil_primitive_constrain(tGPDprimitive *tgpi, bool line_mode)
{
float x = tgpi->end[0] - tgpi->origin[0];
float y = tgpi->end[1] - tgpi->origin[1];
if (line_mode) {
float angle = fabsf(atan2f(y, x));
if (angle < 0.4f || angle > (M_PI - 0.4f)) {
tgpi->end[1] = tgpi->origin[1];
}
else if (angle > (M_PI_2 - 0.4f) && angle < (M_PI_2 + 0.4f)) {
tgpi->end[0] = tgpi->origin[0];
}
else {
gpencil_primitive_to_square(tgpi, x, y);
}
}
else {
gpencil_primitive_to_square(tgpi, x, y);
}
}
/* Helper to rotate point around origin */
static void gp_rotate_v2_v2v2fl(float v[2],
const float p[2],
@ -404,6 +428,11 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi
"adjust subdivision number, Shift to align, Alt to center, E: extrude"),
UI_MAX_DRAW_STR);
}
else if (tgpi->type == GP_STROKE_POLYLINE) {
BLI_strncpy(msg_str,
TIP_("Line: ESC to cancel, LMB to set, Enter/MMB to confirm, Shift to align"),
UI_MAX_DRAW_STR);
}
else if (tgpi->type == GP_STROKE_BOX) {
BLI_strncpy(msg_str,
TIP_("Rectangle: ESC to cancel, LMB set origin, Enter/MMB to confirm, WHEEL/+- "
@ -429,7 +458,7 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi
UI_MAX_DRAW_STR);
}
if (ELEM(tgpi->type, GP_STROKE_CIRCLE, GP_STROKE_ARC, GP_STROKE_LINE, GP_STROKE_BOX)) {
if (ELEM(tgpi->type, GP_STROKE_CIRCLE, GP_STROKE_ARC, GP_STROKE_LINE, GP_STROKE_BOX, GP_STROKE_POLYLINE)) {
if (hasNumInput(&tgpi->num)) {
char str_offs[NUM_STR_REP_LEN];
@ -528,7 +557,7 @@ static void gp_primitive_rectangle(tGPDprimitive *tgpi, tGPspoint *points2D)
}
/* create a line */
static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D)
static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D, bool editable)
{
const int totpoints = (tgpi->tot_edges + tgpi->tot_stored_edges);
const float step = 1.0f / (float)(tgpi->tot_edges - 1);
@ -540,15 +569,22 @@ static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D)
a += step;
}
float color[4];
UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
if (tgpi->tot_stored_edges) {
UI_GetThemeColor4fv(TH_REDALERT, color);
gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
if (editable) {
float color[4];
UI_GetThemeColor4fv(TH_GIZMO_PRIMARY, color);
gp_primitive_set_cp(tgpi, tgpi->end, color, BIG_SIZE_CTL);
if (tgpi->tot_stored_edges) {
UI_GetThemeColor4fv(TH_REDALERT, color);
gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
}
else {
gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
}
}
else {
gp_primitive_set_cp(tgpi, tgpi->start, color, BIG_SIZE_CTL);
float color[4];
UI_GetThemeColor4fv(TH_REDALERT, color);
gp_primitive_set_cp(tgpi, tgpi->start, color, SMALL_SIZE_CTL);
}
}
@ -693,7 +729,10 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
gp_primitive_rectangle(tgpi, points2D);
break;
case GP_STROKE_LINE:
gp_primitive_line(tgpi, points2D);
gp_primitive_line(tgpi, points2D, true);
break;
case GP_STROKE_POLYLINE:
gp_primitive_line(tgpi, points2D, false);
break;
case GP_STROKE_CIRCLE:
gp_primitive_circle(tgpi, points2D);
@ -1041,6 +1080,7 @@ static void gpencil_primitive_update(bContext *C, wmOperator *op, tGPDprimitive
gp_primitive_update_strokes(C, tgpi);
}
/* Initialise mouse points */
static void gpencil_primitive_interaction_begin(tGPDprimitive *tgpi, const wmEvent *event)
{
copy_v2fl_v2i(tgpi->mval, event->mval);
@ -1164,6 +1204,10 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op)
/* set default edge count */
switch (tgpi->type) {
case GP_STROKE_POLYLINE: {
RNA_int_set(op->ptr, "edges", 8);
break;
}
case GP_STROKE_LINE: {
RNA_int_set(op->ptr, "edges", 8);
break;
@ -1334,6 +1378,42 @@ static void gpencil_primitive_edit_event_handling(
}
switch (event->type) {
case LEFTMOUSE: {
if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
/* set control points and enter edit mode */
if ((ELEM(tgpi->type, GP_STROKE_POLYLINE))) {
gpencil_primitive_add_segment(tgpi);
copy_v2_v2(tgpi->start, tgpi->end);
copy_v2_v2(tgpi->origin, tgpi->start);
gp_primitive_update_cps(tgpi);
tgpi->flag = IN_POLYLINE;
WM_cursor_modal_set(win, WM_CURSOR_CROSS);
}
else {
tgpi->flag = IN_CURVE_EDIT;
gp_primitive_update_cps(tgpi);
gpencil_primitive_update(C, op, tgpi);
}
}
else if ((event->val == KM_PRESS) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
/* find nearest cp based on stroke end points */
if (move == MOVE_ENDS) {
tgpi->sel_cp = (a < b) ? SELECT_START : SELECT_END;
}
else if (move == MOVE_CP) {
tgpi->sel_cp = (c < d) ? SELECT_CP1 : SELECT_CP2;
}
else {
tgpi->sel_cp = SELECT_NONE;
}
break;
}
else {
tgpi->sel_cp = SELECT_NONE;
}
break;
}
case MOUSEMOVE: {
if ((event->val == KM_PRESS) && tgpi->sel_cp != SELECT_NONE) {
if (tgpi->sel_cp == SELECT_START && tgpi->tot_stored_edges == 0) {
@ -1366,31 +1446,6 @@ static void gpencil_primitive_edit_event_handling(
}
break;
}
case LEFTMOUSE: {
if ((event->val == KM_PRESS)) {
/* find nearest cp based on stroke end points */
if (move == MOVE_ENDS) {
tgpi->sel_cp = (a < b) ? SELECT_START : SELECT_END;
}
else if (move == MOVE_CP) {
tgpi->sel_cp = (c < d) ? SELECT_CP1 : SELECT_CP2;
}
else {
tgpi->sel_cp = SELECT_NONE;
}
break;
}
else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
/* set control points and enter edit mode */
tgpi->flag = IN_CURVE_EDIT;
gp_primitive_update_cps(tgpi);
gpencil_primitive_update(C, op, tgpi);
}
else {
tgpi->sel_cp = SELECT_NONE;
}
break;
}
case MKEY: {
if ((event->val == KM_PRESS) && (tgpi->curve) && (ELEM(tgpi->orign_type, GP_STROKE_ARC))) {
tgpi->flip ^= 1;
@ -1524,6 +1579,96 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
copy_v2_v2(tgpi->mvalo, tgpi->mval);
return OPERATOR_RUNNING_MODAL;
}
else if (tgpi->flag == IN_POLYLINE) {
switch (event->type) {
case ESCKEY: {
/* return to normal cursor and header status */
ED_workspace_status_text(C, NULL);
WM_cursor_modal_restore(win);
/* clean up temp data */
gpencil_primitive_exit(C, op);
/* canceled! */
return OPERATOR_CANCELLED;
}
case LEFTMOUSE: {
if (event->val == KM_PRESS) {
WM_cursor_modal_set(win, WM_CURSOR_CROSS);
gpencil_primitive_add_segment(tgpi);
gpencil_primitive_update(C, op, tgpi);
copy_v2_v2(tgpi->start, tgpi->end);
copy_v2_v2(tgpi->origin, tgpi->end);
}
break;
}
case SPACEKEY: /* confirm */
case MIDDLEMOUSE:
case RETKEY:
case RIGHTMOUSE: {
if (event->val == KM_PRESS) {
tgpi->flag = IDLE;
tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0;
gp_primitive_update_strokes(C, tgpi);
gpencil_primitive_interaction_end(C, op, win, tgpi);
return OPERATOR_FINISHED;
}
break;
}
case MOUSEMOVE: {
WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL);
copy_v2_v2(tgpi->end, tgpi->mval);
if (event->shift) {
gpencil_primitive_constrain(tgpi, true);
}
gpencil_primitive_update(C, op, tgpi);
break;
}
case PADPLUSKEY:
case WHEELUPMOUSE: {
if ((event->val != KM_RELEASE)) {
tgpi->tot_edges = tgpi->tot_edges + 1;
CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
gpencil_primitive_update(C, op, tgpi);
}
break;
}
case PADMINUS:
case WHEELDOWNMOUSE: {
if ((event->val != KM_RELEASE)) {
tgpi->tot_edges = tgpi->tot_edges - 1;
CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES);
RNA_int_set(op->ptr, "edges", tgpi->tot_edges);
gpencil_primitive_update(C, op, tgpi);
}
break;
}
case FKEY: /* brush thickness/ brush strength */
{
if ((event->val == KM_PRESS)) {
if (event->shift) {
tgpi->prev_flag = tgpi->flag;
tgpi->flag = IN_BRUSH_STRENGTH;
}
else {
tgpi->prev_flag = tgpi->flag;
tgpi->flag = IN_BRUSH_SIZE;
}
WM_cursor_modal_set(win, WM_CURSOR_NS_SCROLL);
}
break;
}
}
copy_v2_v2(tgpi->mvalo, tgpi->mval);
return OPERATOR_RUNNING_MODAL;
}
else if (tgpi->flag == IN_BRUSH_SIZE) {
switch (event->type) {
case MOUSEMOVE:
@ -1534,11 +1679,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
case MIDDLEMOUSE:
case LEFTMOUSE:
tgpi->brush_size = 0;
tgpi->flag = IN_CURVE_EDIT;
tgpi->flag = tgpi->prev_flag;
break;
case RIGHTMOUSE:
if (event->val == KM_RELEASE) {
tgpi->flag = IN_CURVE_EDIT;
tgpi->flag = tgpi->prev_flag;
gpencil_primitive_size(tgpi, true);
gpencil_primitive_update(C, op, tgpi);
}
@ -1557,11 +1702,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
case MIDDLEMOUSE:
case LEFTMOUSE:
tgpi->brush_strength = 0.0f;
tgpi->flag = IN_CURVE_EDIT;
tgpi->flag = tgpi->prev_flag;
break;
case RIGHTMOUSE:
if (event->val == KM_RELEASE) {
tgpi->flag = IN_CURVE_EDIT;
tgpi->flag = tgpi->prev_flag;
gpencil_primitive_strength(tgpi, true);
gpencil_primitive_update(C, op, tgpi);
}
@ -1570,7 +1715,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
copy_v2_v2(tgpi->mvalo, tgpi->mval);
return OPERATOR_RUNNING_MODAL;
}
else if (tgpi->flag != IDLE) {
else if (!ELEM(tgpi->flag, IDLE) && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
gpencil_primitive_edit_event_handling(C, op, win, event, tgpi);
}
@ -1581,24 +1726,38 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
/* TODO: Ignore if not in main region yet */
tgpi->flag = IN_PROGRESS;
gpencil_primitive_interaction_begin(tgpi, event);
if (ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
tgpi->flag = IN_POLYLINE;
gpencil_primitive_update(C, op, tgpi);
return OPERATOR_RUNNING_MODAL;
}
}
else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_MOVE)) {
tgpi->flag = IN_CURVE_EDIT;
}
else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS)) {
else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) &&
(!ELEM(tgpi->type, GP_STROKE_POLYLINE))) {
/* set control points and enter edit mode */
tgpi->flag = IN_CURVE_EDIT;
gp_primitive_update_cps(tgpi);
gpencil_primitive_update(C, op, tgpi);
}
else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) &&
(tgpi->type != GP_STROKE_CURVE)) {
(!ELEM(tgpi->type, GP_STROKE_CURVE, GP_STROKE_POLYLINE))) {
/* stop drawing primitive */
tgpi->flag = IDLE;
gpencil_primitive_interaction_end(C, op, win, tgpi);
/* done! */
return OPERATOR_FINISHED;
}
else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_PROGRESS) &&
(ELEM(tgpi->type, GP_STROKE_POLYLINE))) {
/* set control points and enter edit mode */
tgpi->flag = IN_POLYLINE;
gpencil_primitive_update(C, op, tgpi);
copy_v2_v2(tgpi->mvalo, tgpi->mval);
return OPERATOR_RUNNING_MODAL;
}
else if ((event->val == KM_RELEASE) && (tgpi->flag == IN_MOVE)) {
tgpi->flag = IN_CURVE_EDIT;
}
else {
if (G.debug & G_DEBUG) {
printf("GP Add Primitive Modal: LEFTMOUSE %d, Status = %d\n", event->val, tgpi->flag);
@ -1618,7 +1777,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
/* exception to cancel current stroke when we have previous strokes in buffer */
if (tgpi->tot_stored_edges > 0) {
tgpi->flag = IDLE;
tgpi->tot_edges = 0;
tgpi->tot_edges = tgpi->tot_stored_edges ? 1 : 0;
gp_primitive_update_strokes(C, tgpi);
gpencil_primitive_interaction_end(C, op, win, tgpi);
/* done! */
@ -1673,9 +1832,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
{
if ((event->val == KM_PRESS)) {
if (event->shift) {
tgpi->prev_flag = tgpi->flag;
tgpi->flag = IN_BRUSH_STRENGTH;
}
else {
tgpi->prev_flag = tgpi->flag;
tgpi->flag = IN_BRUSH_SIZE;
}
WM_cursor_modal_set(win, WM_CURSOR_NS_SCROLL);
@ -1712,7 +1873,7 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
case MOUSEMOVE: /* calculate new position */
{
if (tgpi->flag == IN_CURVE_EDIT) {
if (ELEM(tgpi->flag, IN_CURVE_EDIT)) {
break;
}
/* only handle mousemove if not doing numinput */
@ -1725,26 +1886,11 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e
}
/* Keep square if shift key */
if (event->shift) {
float x = tgpi->end[0] - tgpi->origin[0];
float y = tgpi->end[1] - tgpi->origin[1];
if (tgpi->type == GP_STROKE_LINE || tgpi->curve) {
float angle = fabsf(atan2f(y, x));
if (angle < 0.4f || angle > (M_PI - 0.4f)) {
tgpi->end[1] = tgpi->origin[1];
}
else if (angle > (M_PI_2 - 0.4f) && angle < (M_PI_2 + 0.4f)) {
tgpi->end[0] = tgpi->origin[0];
}
else {
gpencil_primitive_to_square(tgpi, x, y);
}
}
else {
gpencil_primitive_to_square(tgpi, x, y);
}
gpencil_primitive_constrain(
tgpi, (ELEM(tgpi->type, GP_STROKE_LINE, GP_STROKE_POLYLINE) || tgpi->curve));
}
/* Center primitive if alt key */
if (event->alt) {
if (event->alt && !ELEM(tgpi->type, GP_STROKE_POLYLINE)) {
tgpi->start[0] = tgpi->origin[0] - (tgpi->end[0] - tgpi->origin[0]);
tgpi->start[1] = tgpi->origin[1] - (tgpi->end[1] - tgpi->origin[1]);
}
@ -1796,6 +1942,7 @@ void GPENCIL_OT_primitive(wmOperatorType *ot)
static EnumPropertyItem primitive_type[] = {
{GP_STROKE_BOX, "BOX", 0, "Box", ""},
{GP_STROKE_LINE, "LINE", 0, "Line", ""},
{GP_STROKE_POLYLINE, "POLYLINE", 0, "Polyline", ""},
{GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""},
{GP_STROKE_ARC, "ARC", 0, "Arc", ""},
{GP_STROKE_CURVE, "CURVE", 0, "Curve", ""},

@ -1 +1 @@
Subproject commit d8c4ae2c23a36d9609d47142dc72f243551258f1
Subproject commit 8598818108ddaf35e30d2a2dbd408ad371e41eb5