Commit: d56f4f55b11f01d98f00cb867c0e6b53678ed14e
Author: Antonioya
Date:   Sun Mar 3 16:25:48 2019 +0100
Branches: greasepencil-object
https://developer.blender.org/rBd56f4f55b11f01d98f00cb867c0e6b53678ed14e

GPencil: New extrude operator

If the extrude points are the first or last of the stroke, the stroke is 
extended.

If the extrude points are in the middle of the stroke, a new stroke is created 
because the grease pencil strokes can be only with 2 extremes.

Still pending define a new icon and set by default XYZ axis in gizmo.

===================================================================

M       release/scripts/presets/keyconfig/keymap_data/blender_default.py
M       release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
M       source/blender/editors/gpencil/gpencil_edit.c
M       source/blender/editors/gpencil/gpencil_intern.h
M       source/blender/editors/gpencil/gpencil_ops.c
M       source/blender/editors/transform/transform_gizmo_extrude_3d.c

===================================================================

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py 
b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index e29b4a36af4..8e8c08b2e05 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -2951,6 +2951,8 @@ def km_grease_pencil_stroke_edit_mode(params):
         *_grease_pencil_selection(params),
         # Duplicate and move selected points
         ("gpencil.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": 
True}, None),
+        # Extrude and move selected points
+        ("gpencil.extrude_move", {"type": 'E', "value": 'PRESS'}, None),
         # Delete
         op_menu("VIEW3D_MT_edit_gpencil_delete", {"type": 'X', "value": 
'PRESS'}),
         op_menu("VIEW3D_MT_edit_gpencil_delete", {"type": 'DEL', "value": 
'PRESS'}),
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py 
b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 92c599ef071..3a0f5ce01cb 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1231,6 +1231,16 @@ class _defs_gpencil_edit:
             keymap=(),
         )
 
+    @ToolDef.from_fn
+    def extrude():
+        return dict(
+            text="Extrude",
+            icon="ops.gpencil.extrude_move",
+            widget="VIEW3D_GGT_xform_extrude",
+            keymap=(),
+            
draw_settings=_template_widget.VIEW3D_GGT_xform_extrude.draw_settings,
+        )
+
 
 class _defs_gpencil_sculpt:
 
@@ -1676,10 +1686,12 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, 
Panel):
             _defs_view3d_generic.cursor,
             None,
             *_tools_transform,
+            _defs_gpencil_edit.extrude,
             None,
             _defs_gpencil_edit.bend,
             _defs_gpencil_edit.shear,
             _defs_gpencil_edit.tosphere,
+
         ],
         'SCULPT_GPENCIL': [
             *_tools_gpencil_select,
diff --git a/source/blender/editors/gpencil/gpencil_edit.c 
b/source/blender/editors/gpencil/gpencil_edit.c
index 4ba74582774..bb96ba29503 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -754,6 +754,213 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
+/* ************** Extrude Selected Strokes **************** */
+
+/* helper to copy a point to temp area */
+static void copy_point(bGPDstroke *gps,
+                                       bGPDspoint *temp_points,
+                                       MDeformVert *temp_dverts,
+                                       int from_idx, int to_idx)
+{
+       bGPDspoint *pt = &temp_points[from_idx];
+       bGPDspoint *pt_final = &gps->points[to_idx];
+
+       copy_v3_v3(&pt_final->x, &pt->x);
+       pt_final->pressure = pt->pressure;
+       pt_final->strength = pt->strength;
+       pt_final->time = pt->time;
+       pt_final->flag = pt->flag;
+       pt_final->uv_fac = pt->uv_fac;
+       pt_final->uv_rot = pt->uv_rot;
+
+       if (gps->dvert != NULL) {
+               MDeformVert *dvert = &temp_dverts[from_idx];
+               MDeformVert *dvert_final = &gps->dvert[to_idx];
+
+               dvert_final->totweight = dvert->totweight;
+               dvert_final->dw = dvert->dw;
+       }
+}
+
+static void gpencil_add_move_points(bGPDframe *gpf, bGPDstroke *gps)
+{
+       bGPDspoint *temp_points = NULL;
+       MDeformVert *temp_dverts = NULL;
+       bGPDspoint *pt = NULL;
+       const bGPDspoint *pt_start = &gps->points[0];
+       const bGPDspoint *pt_last = &gps->points[gps->totpoints - 1];
+       const bool do_first = (pt_start->flag & GP_SPOINT_SELECT);
+       const bool do_last = ((pt_last->flag & GP_SPOINT_SELECT) && (pt_start 
!= pt_last));
+       const bool do_stroke = (do_first || do_last);
+
+       /* review points in the midle of stroke to create new strokes */
+       for (int i = 0; i < gps->totpoints; i++) {
+               /* skip first and last point */
+               if ((i == 0) || (i == gps->totpoints - 1)) {
+                       continue;
+               }
+
+               pt = &gps->points[i];
+               if (pt->flag == GP_SPOINT_SELECT) {
+                       /* duplicate original stroke data */
+                       bGPDstroke *gps_new = MEM_dupallocN(gps);
+                       gps_new->prev = gps_new->next = NULL;
+
+                       /* add new points array */
+                       gps_new->totpoints = 1;
+                       gps_new->points = MEM_callocN(sizeof(bGPDspoint), 
__func__);
+                       gps_new->dvert = NULL;
+
+                       if (gps->dvert != NULL) {
+                               gps_new->dvert = 
MEM_callocN(sizeof(MDeformVert), __func__);
+                       }
+
+                       gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+                       gps_new->triangles = NULL;
+                       gps_new->tot_triangles = 0;
+                       BLI_insertlinkafter(&gpf->strokes, gps, gps_new);
+
+                       /* copy selected point data to new stroke */
+                       copy_point(gps_new, gps->points, gps->dvert, i, 0);
+
+                       /* deselect orinal point */
+                       pt->flag &= ~GP_SPOINT_SELECT;
+               }
+       }
+
+       /* review first and last point to reuse same stroke */
+       int i2 = 0;
+       int totnewpoints, oldtotpoints;
+       /* if first or last, reuse stroke and resize */
+       if ((do_first) || (do_last)) {
+               totnewpoints = gps->totpoints;
+               if (do_first) {
+                       totnewpoints++;
+               }
+               if (do_last) {
+                       totnewpoints++;
+               }
+
+               /* duplicate points in a temp area */
+               temp_points = MEM_dupallocN(gps->points);
+               oldtotpoints = gps->totpoints;
+               if (gps->dvert != NULL) {
+                       temp_dverts = MEM_dupallocN(gps->dvert);
+               }
+
+               /* if first point, need move all one position */
+               if (do_first) {
+                       i2 = 1;
+               }
+
+               /* resize the points arrays */
+               gps->totpoints = totnewpoints;
+               gps->points = MEM_recallocN(gps->points, sizeof(*gps->points) * 
gps->totpoints);
+               if (gps->dvert != NULL) {
+                       gps->dvert = MEM_recallocN(gps->dvert, 
sizeof(*gps->dvert) * gps->totpoints);
+               }
+
+               /* move points to new position */
+               for (int i = 0; i < oldtotpoints; i++) {
+                       copy_point(gps, temp_points, temp_dverts, i, i2);
+                       i2++;
+               }
+               gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+
+               /* if first point, add new point at the begining */
+               if (do_first) {
+                       copy_point(gps, temp_points, temp_dverts, 0, 0);
+                       /* deselect old */
+                       pt = &gps->points[1];
+                       pt->flag &= ~GP_SPOINT_SELECT;
+                       /* select new */
+                       pt = &gps->points[0];
+                       pt->flag |= GP_SPOINT_SELECT;
+               }
+
+               /* if last point, add new point at the end */
+               if (do_last) {
+                       copy_point(gps, temp_points, temp_dverts,
+                               oldtotpoints - 1, gps->totpoints - 1);
+
+                       /* deselect old */
+                       pt = &gps->points[gps->totpoints - 2];
+                       pt->flag &= ~GP_SPOINT_SELECT;
+                       /* select new */
+                       pt = &gps->points[gps->totpoints - 1];
+                       pt->flag |= GP_SPOINT_SELECT;
+               }
+
+               MEM_SAFE_FREE(temp_points);
+               MEM_SAFE_FREE(temp_dverts);
+       }
+
+       /* if the stroke is not reused, deselect */
+       if (!do_stroke) {
+               gps->flag &= ~GP_STROKE_SELECT;
+       }
+}
+
+static int gp_extrude_exec(bContext *C, wmOperator *op)
+{
+       Object *obact = CTX_data_active_object(C);
+       bGPdata *gpd = (bGPdata *)obact->data;
+       bGPDstroke *gps;
+
+       if (gpd == NULL) {
+               BKE_report(op->reports, RPT_ERROR, "No Grease Pencil data");
+               return OPERATOR_CANCELLED;
+       }
+
+       if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
+               BKE_report(op->reports, RPT_ERROR, "Operator not supported in 
multiframe edition");
+               return OPERATOR_CANCELLED;
+       }
+
+       CTX_DATA_BEGIN(C, bGPDlayer *, gpl, editable_gpencil_layers)
+       {
+               bGPDframe *gpf = gpl->actframe;
+
+               if (gpf == NULL)
+                       continue;
+
+               for (gps = gpf->strokes.first; gps; gps = gps->next) {
+                       /* skip strokes that are invalid for current view */
+                       if (ED_gpencil_stroke_can_use(C, gps) == false) {
+                               continue;
+                       }
+
+                       if (gps->flag & GP_STROKE_SELECT) {
+                               gpencil_add_move_points(gpf, gps);
+                       }
+               }
+       }
+       CTX_DATA_END;
+
+       /* updates */
+       DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | 
ID_RECALC_COPY_ON_WRITE);
+       DEG_id_tag_update(&obact->id, ID_RECALC_COPY_ON_WRITE);
+       WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+
+       return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_extrude(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Extrude Stroke Points";
+       ot->idname = "GPENCIL_OT_extrude";
+       ot->description = "Extrude the selected Grease Pencil points";
+
+       /* callbacks */
+       ot->exec = gp_extrude_exec;
+       ot->poll = gp_stroke_edit_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
 /* ******************* Copy/Paste Strokes ************************* */
 /* Grease Pencil stroke data copy/paste buffer:
  * - The copy operation collects all segments of selected strokes,
diff --git a/source/blender/editors/gpencil/gpencil_intern.h 
b/source/blender/editors/gpencil/gpencil_intern.h
index 416f3093886..aa47319e3d9 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -390,6 +390,7 @@ void GPENCIL_OT_delete(struct wmOperatorType *ot);
 void GPENCIL_OT_dissolve(struct wmOperatorType *ot);
 void GPENCIL_OT_copy(struct wmOperatorType *ot);
 void GPENCIL_OT_paste(struct wmOperatorType *ot);
+void GPENCIL_OT_extrude(struct wmOperatorType *ot);
 
 void GPENCIL_OT_move_to_layer(struct wmOperatorType *ot);
 void GPENCIL_OT_layer_change(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c 
b/source/blender/editors/gpencil/gpencil_ops.c
index 60b2fb5d64e..e3b13b26672 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -254,6 +254,7 @@ void ED_operatortypes_gpencil(void)
        WM_operatortype_append(GPENCIL_OT_dissolve);
        WM_operatortype_append(GPENCIL_OT_copy);
        WM_operatortype_append(GPENCIL_OT_paste);
+       WM_operatortype_append(GPENCIL_OT_extrude);
 
        WM_operatortype_append(GPENCIL_OT_move_to_layer);
        WM_operatortype_append(GPENCIL_OT_layer_change);
@@ -361,6 +362,13 @@ void ED_operatormacros_gpencil(void)
        otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
        RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
 
+       /* Extrude + Move = Interactively add new points */
+       ot = WM_operatortype_append_macro("GPENCIL_OT_extrude_move", "Extrude 
Stroke Points",
+                                                                         
"Extrude selected points and move them",
+                                                                         
OPTYPE_UNDO | OPTYPE_REGISTER);
+       WM_operatortype_macro_define(ot, "GPENCIL_OT_extrude");
+       otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+       RNA_boolean_set(otmacro->ptr, "gpencil_strokes", true);
 }
 
 /* ****************************************** */
dif

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to