diff options
6 files changed, 119 insertions, 13 deletions
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index ddcd4242c4a..09fdd202932 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -5646,6 +5646,10 @@ def km_3d_view_tool_gpencil_paint_line(params): {"items": [ ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, {"properties": [("type", 'LINE'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("type", 'LINE'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("type", 'LINE'), ("wait_for_input", False)]}), ]}, ) @@ -5657,6 +5661,10 @@ def km_3d_view_tool_gpencil_paint_box(params): {"items": [ ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, {"properties": [("type", 'BOX'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("type", 'BOX'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("type", 'BOX'), ("wait_for_input", False)]}), ]}, ) @@ -5668,6 +5676,25 @@ def km_3d_view_tool_gpencil_paint_circle(params): {"items": [ ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, {"properties": [("type", 'CIRCLE'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("type", 'CIRCLE'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("type", 'CIRCLE'), ("wait_for_input", False)]}), + ]}, + ) + + +def km_3d_view_tool_gpencil_paint_arc(params): + return ( + "3D View Tool: Gpencil Paint, Arc", + {"space_type": 'VIEW_3D', "region_type": 'WINDOW'}, + {"items": [ + ("gpencil.primitive", {"type": params.tool_tweak, "value": 'ANY'}, + {"properties": [("type", 'ARC'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, + {"properties": [("type", 'ARC'), ("wait_for_input", False)]}), + ("gpencil.primitive", {"type": 'LEFTMOUSE', "value": 'PRESS', "alt": True}, + {"properties": [("type", 'ARC'), ("wait_for_input", False)]}), ]}, ) @@ -5944,6 +5971,7 @@ def generate_keymaps(params=None): km_3d_view_tool_gpencil_paint_line(params), km_3d_view_tool_gpencil_paint_box(params), km_3d_view_tool_gpencil_paint_circle(params), + km_3d_view_tool_gpencil_paint_arc(params), km_3d_view_tool_gpencil_edit_select(params), km_3d_view_tool_gpencil_edit_select_box(params), km_3d_view_tool_gpencil_edit_select_circle(params), diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index eed78ff26ad..5a0c2bd1e43 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -644,6 +644,7 @@ class GPENCIL_MT_gpencil_draw_specials(Menu): layout.operator("gpencil.primitive", text="Line", icon='IPO_CONSTANT').type = 'LINE' layout.operator("gpencil.primitive", text="Rectangle", icon='UV_FACESEL').type = 'BOX' layout.operator("gpencil.primitive", text="Circle", icon='ANTIALIASED').type = 'CIRCLE' + layout.operator("gpencil.primitive", text="Arc", icon='SPHERECURVE').type = 'ARC' class GPENCIL_MT_gpencil_draw_delete(Menu): diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 591a17db4a5..5c930b68dd9 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -1067,6 +1067,15 @@ class _defs_gpencil_paint: keymap=(), ) + @ToolDef.from_fn + def arc(): + return dict( + text="Arc", + icon="ops.gpencil.primitive_arc", + cursor='CROSSHAIR', + widget=None, + keymap=(), + ) class _defs_gpencil_edit: @ToolDef.from_fn @@ -1573,6 +1582,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_gpencil_paint.line, _defs_gpencil_paint.box, _defs_gpencil_paint.circle, + _defs_gpencil_paint.arc, ], 'GPENCIL_EDIT': [ *_tools_gpencil_select, diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index f1a91d08040..af1f72fa72c 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -301,7 +301,7 @@ class _draw_left_context_mode: return is_paint = True - if (tool.name in {"Line", "Box", "Circle"}): + if (tool.name in {"Line", "Box", "Circle", "Arc"}): is_paint = False elif (not tool.has_datablock): return diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index 93d75063bff..5db5c0f2571 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -154,6 +154,8 @@ typedef struct tGPDprimitive { struct bGPDlayer *gpl; /* layer */ struct bGPDframe *gpf; /* frame */ int type; /* type of primitive */ + short cyclic; /* cyclic option */ + short flip; /* flip option */ int tot_edges; /* number of polygon edges */ int top[2]; /* first box corner */ int bottom[2]; /* last box corner */ @@ -369,7 +371,8 @@ enum { enum { GP_STROKE_BOX = -1, GP_STROKE_LINE = 1, - GP_STROKE_CIRCLE = 2 + GP_STROKE_CIRCLE = 2, + GP_STROKE_ARC = 3 }; diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 336ed305a93..140a7527dc9 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -84,7 +84,7 @@ #include "gpencil_intern.h" #define MIN_EDGES 2 -#define MAX_EDGES 100 +#define MAX_EDGES 128 #define IDLE 0 #define IN_PROGRESS 1 @@ -168,7 +168,7 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi) /* enable recalculation flag by default */ gps->flag |= GP_STROKE_RECALC_CACHES; /* the polygon must be closed, so enabled cyclic */ - if (tgpi->type != GP_STROKE_LINE) { + if (tgpi->type != GP_STROKE_LINE && tgpi->type != GP_STROKE_ARC) { gps->flag |= GP_STROKE_CYCLIC; } else { @@ -215,11 +215,14 @@ static void gpencil_primitive_status_indicators(bContext *C, tGPDprimitive *tgpi else if (tgpi->type == GP_STROKE_LINE) { BLI_strncpy(msg_str, IFACE_("Line: ESC/RMB to cancel, LMB set origin, Enter/LMB to confirm, Alt to center"), UI_MAX_DRAW_STR); } + else if (tgpi->type == GP_STROKE_ARC) { + BLI_strncpy(msg_str, IFACE_("Arc: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/+- to adjust edge number, Shift to square, Alt to center, F to flip, C to Close"), UI_MAX_DRAW_STR); + } else { - BLI_strncpy(msg_str, IFACE_("Circle: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL to adjust edge number, Shift to square, Alt to center"), UI_MAX_DRAW_STR); + BLI_strncpy(msg_str, IFACE_("Circle: ESC/RMB to cancel, Enter/LMB to confirm, WHEEL/+- to adjust edge number, Shift to square, Alt to center"), UI_MAX_DRAW_STR); } - if (tgpi->type == GP_STROKE_CIRCLE) { + if (tgpi->type == GP_STROKE_CIRCLE || tgpi->type == GP_STROKE_ARC) { if (hasNumInput(&tgpi->num)) { char str_offs[NUM_STR_REP_LEN]; @@ -286,6 +289,37 @@ static void gp_primitive_line(tGPDprimitive *tgpi, tGPspoint *points2D) points2D[1].y = tgpi->bottom[1]; } +/* create an arc */ +static void gp_primitive_arc(tGPDprimitive *tgpi, tGPspoint *points2D) +{ + const int totpoints = tgpi->tot_edges; + const float step = M_PI_2 / (float)(totpoints - 1); + float length[2]; + int start[2]; + int end[2]; + float a = 0.0f; + + start[0] = tgpi->top[0]; + start[1] = tgpi->top[1]; + end[0] = tgpi->bottom[0]; + end[1] = tgpi->bottom[1]; + + if (tgpi->flip) { + SWAP(int, end[0], start[0]); + SWAP(int, end[1], start[1]); + } + + length[0] = end[0] - start[0]; + length[1] = end[1] - start[1]; + + for (int i = 0; i < totpoints; i++) { + tGPspoint *p2d = &points2D[i]; + p2d->x = (int)(start[0] + sinf(a) * length[0]); + p2d->y = (int)(end[1] - cosf(a) * length[1]); + a += step; + } +} + /* create a circle */ static void gp_primitive_circle(tGPDprimitive *tgpi, tGPspoint *points2D) { @@ -337,6 +371,13 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) case GP_STROKE_CIRCLE: gp_primitive_circle(tgpi, points2D); break; + case GP_STROKE_ARC: + gp_primitive_arc(tgpi, points2D); + if (tgpi->cyclic) + gps->flag |= GP_STROKE_CYCLIC; + else + gps->flag &= ~GP_STROKE_CYCLIC; + break; default: break; } @@ -346,7 +387,6 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) bGPDspoint *pt = &gps->points[i]; tGPspoint *p2d = &points2D[i]; - /* convert screen-coordinates to 3D coordinates */ gp_stroke_convertcoords_tpoint(tgpi->scene, tgpi->ar, tgpi->ob, tgpi->gpl, p2d, NULL, &pt->x); @@ -447,7 +487,7 @@ static void gpencil_primitive_exit(bContext *C, wmOperator *op) } /* Init new temporary primitive data */ -static void gpencil_primitive_init(bContext *C, wmOperator *op) +static void gpencil_primitive_init(bContext *C, wmOperator *op, const wmEvent *event) { ToolSettings *ts = CTX_data_tool_settings(C); bGPdata *gpd = CTX_data_gpencil_data(C); @@ -482,8 +522,11 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) /* set parameters */ tgpi->type = RNA_enum_get(op->ptr, "type"); - /* if circle set default to 32 */ + /* set default edge count */ if (tgpi->type == GP_STROKE_CIRCLE) { + RNA_int_set(op->ptr, "edges", 64); + } + else if (tgpi->type == GP_STROKE_ARC) { RNA_int_set(op->ptr, "edges", 32); } else if (tgpi->type == GP_STROKE_BOX) { @@ -512,7 +555,7 @@ static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent * tGPDprimitive *tgpi = NULL; /* initialize operator runtime data */ - gpencil_primitive_init(C, op); + gpencil_primitive_init(C, op, event); tgpi = op->customdata; const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); @@ -647,7 +690,6 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e /* done! */ return OPERATOR_FINISHED; } - case ESCKEY: /* cancel */ case RIGHTMOUSE: { @@ -661,10 +703,30 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e /* canceled! */ return OPERATOR_CANCELLED; } + case CKEY: + { + if ((event->val == KM_RELEASE) && tgpi->type == GP_STROKE_ARC) { + tgpi->cyclic ^= 1; + + /* update screen */ + gpencil_primitive_update(C, op, tgpi); + } + break; + } + case FKEY: + { + if ((event->val == KM_RELEASE) && tgpi->type == GP_STROKE_ARC) { + tgpi->flip ^= 1; + /* update screen */ + gpencil_primitive_update(C, op, tgpi); + } + break; + } + case PADPLUSKEY: case WHEELUPMOUSE: { - if (tgpi->type == GP_STROKE_CIRCLE) { + if ((event->val != KM_RELEASE) && (tgpi->type == GP_STROKE_CIRCLE || tgpi->type == GP_STROKE_ARC)) { tgpi->tot_edges = tgpi->tot_edges + 1; CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES); RNA_int_set(op->ptr, "edges", tgpi->tot_edges); @@ -674,9 +736,10 @@ static int gpencil_primitive_modal(bContext *C, wmOperator *op, const wmEvent *e } break; } + case PADMINUS: case WHEELDOWNMOUSE: { - if (tgpi->type == GP_STROKE_CIRCLE) { + if ((event->val != KM_RELEASE) && (tgpi->type == GP_STROKE_CIRCLE || tgpi->type == GP_STROKE_ARC)) { tgpi->tot_edges = tgpi->tot_edges - 1; CLAMP(tgpi->tot_edges, MIN_EDGES, MAX_EDGES); RNA_int_set(op->ptr, "edges", tgpi->tot_edges); @@ -771,6 +834,7 @@ void GPENCIL_OT_primitive(wmOperatorType *ot) {GP_STROKE_BOX, "BOX", 0, "Box", ""}, {GP_STROKE_LINE, "LINE", 0, "Line", ""}, {GP_STROKE_CIRCLE, "CIRCLE", 0, "Circle", ""}, + {GP_STROKE_ARC, "ARC", 0, "Arc", ""}, {0, NULL, 0, NULL, NULL} }; |