[Bf-blender-cvs] [163e434] GPencil_Editing_Stage3: GP Editing: Snapping Tools (Shift S)

Joshua Leung noreply at git.blender.org
Sun Nov 15 07:41:55 CET 2015


Commit: 163e434b32d7965015c4cf4c5d9f3ae30bf73976
Author: Joshua Leung
Date:   Sun Nov 15 19:41:27 2015 +1300
Branches: GPencil_Editing_Stage3
https://developer.blender.org/rB163e434b32d7965015c4cf4c5d9f3ae30bf73976

GP Editing: Snapping Tools (Shift S)

This commit introduces the ability to snap GP points to the cursor/grid,
as well as snapping the cursor to GP points. Currently this functionality
is only available in the 3D view (since the cursor/grid settings are only
available in that view), where they are most needed.

Later, some of these operators can be extended to other editors on an
"as-needed" basis, based on finding some way of dealing with the lack
of 2D cursor in those views.

Coded during my recent travels :)

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

M	release/scripts/startup/bl_ui/properties_grease_pencil_common.py
M	release/scripts/startup/bl_ui/space_view3d.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

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

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 3c2f2c6..ee1ff62 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -390,6 +390,26 @@ class GPENCIL_PIE_sculpt(Menu):
 ###############################
 
 
+class GPENCIL_MT_snap(Menu):
+    bl_label = "Snap"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.operator("gpencil.snap_to_grid", text="Selection to Grid")
+        layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor").use_offset = False
+        layout.operator("gpencil.snap_to_cursor", text="Selection to Cursor (Offset)").use_offset = True
+
+        layout.separator()
+
+        layout.operator("gpencil.snap_cursor_to_selected", text="Cursor to Selected")
+        layout.operator("view3d.snap_cursor_to_center", text="Cursor to Center")
+        layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid")
+
+
+###############################
+
+
 class GPENCIL_UL_layer(UIList):
     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
         # assert(isinstance(item, bpy.types.GPencilLayer)
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index da1bcfc..590128f 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2882,13 +2882,17 @@ class VIEW3D_MT_edit_gpencil(Menu):
         layout.separator()
 
         layout.menu("VIEW3D_MT_edit_gpencil_transform")
+        layout.operator("transform.mirror", text="Mirror")
+        layout.menu("GPENCIL_MT_snap")
+
+        layout.separator()
+
         layout.menu("VIEW3D_MT_object_animation")   # NOTE: provides keyingset access...
 
         layout.separator()
 
         layout.menu("VIEW3D_MT_edit_gpencil_delete")
         layout.operator("gpencil.duplicate_move", text="Duplicate")
-        layout.operator("transform.mirror", text="Mirror")
 
         layout.separator()
 
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 5a980a3..c4e2db6 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -960,4 +960,189 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot)
 	ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
 }
 
+/* ****************** Snapping - Strokes <-> Cursor ************************ */
+
+/* Poll callback for snap operators */
+/* NOTE: For now, we only allow these in the 3D view, as other editors do not
+ *       define a cursor or gridstep which can be used
+ */
+static int gp_snap_poll(bContext *C)
+{
+	bGPdata *gpd = CTX_data_gpencil_data(C);
+	ScrArea *sa = CTX_wm_area(C);
+	
+	return (gpd != NULL) && ((sa != NULL) && (sa->spacetype == SPACE_VIEW3D));
+}
+
+/* --------------------------------- */
+
+static int gp_snap_to_grid(bContext *C, wmOperator *op)
+{
+	RegionView3D *rv3d = CTX_wm_region_data(C);
+	float gridf = rv3d->gridview;
+	
+	CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+	{
+		bGPDspoint *pt;
+		int i;
+		
+		// TOOD: if entire stroke is selected, offset entire stroke by same amount?
+		
+		for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+			/* only if point is selected.. */
+			if (pt->flag & GP_SPOINT_SELECT) {
+				pt->x = gridf * floorf(0.5f + pt->x / gridf);
+				pt->y = gridf * floorf(0.5f + pt->y / gridf);
+				pt->z = gridf * floorf(0.5f + pt->z / gridf);
+			}
+		}
+	}
+	CTX_DATA_END;
+	
+	WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+	return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_snap_to_grid(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Snap Selection to Grid";
+	ot->idname = "GPENCIL_OT_snap_to_grid";
+	ot->description = "Snap selected points to the nearest grid points";
+	
+	/* callbacks */
+	ot->exec = gp_snap_to_grid;
+	ot->poll = gp_snap_poll;
+	
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ------------------------------- */
+
+static int gp_snap_to_cursor(bContext *C, wmOperator *op)
+{
+	Scene *scene = CTX_data_scene(C);
+	View3D *v3d = CTX_wm_view3d(C);
+	
+	const bool use_offset = RNA_boolean_get(op->ptr, "use_offset");
+	const float *cursor_global = ED_view3d_cursor3d_get(scene, v3d);
+	
+	CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+	{
+		bGPDspoint *pt;
+		int i;
+		
+		/* only continue if this stroke is selected (editable doesn't guarantee this)... */
+		if ((gps->flag & GP_STROKE_SELECT) == 0)
+			continue;
+		
+		if (use_offset) {
+			float offset[3];
+			
+			/* compute offset from first point of stroke to cursor */
+			/* TODO: Allow using midpoint instead? */
+			sub_v3_v3v3(offset, cursor_global, &gps->points->x);
+			
+			/* apply offset to all points in the stroke */
+			for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+				add_v3_v3(&pt->x, offset);
+			}
+		}
+		else {
+			/* affect each selected point */
+			for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+				if (pt->flag & GP_SPOINT_SELECT) {
+					copy_v3_v3(&pt->x, cursor_global);
+				}
+			}
+		}
+	}
+	CTX_DATA_END;
+	
+	WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+	return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Snap Selection to Cursor";
+	ot->idname = "GPENCIL_OT_snap_to_cursor";
+	ot->description = "Snap selected points/strokes to the cursor";
+	
+	/* callbacks */
+	ot->exec = gp_snap_to_cursor;
+	ot->poll = gp_snap_poll;
+	
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+	
+	/* props */
+	ot->prop = RNA_def_boolean(ot->srna, "use_offset", true, "With Offset",
+	                           "Offset the entire stroke instead of selected points only");
+}
+
+/* ------------------------------- */
+
+static int gp_snap_cursor_to_sel(bContext *C, wmOperator *op)
+{
+	Scene *scene = CTX_data_scene(C);
+	View3D *v3d = CTX_wm_view3d(C);
+	
+	float *cursor = ED_view3d_cursor3d_get(scene, v3d);
+	float centroid[3] = {0.0f};
+	float min[3] = {0.0f};
+	float max[3] = {0.0f};
+	size_t count = 0;
+	
+	/* calculate midpoints from selected points */
+	CTX_DATA_BEGIN(C, bGPDstroke *, gps, editable_gpencil_strokes)
+	{
+		bGPDspoint *pt;
+		int i;
+		
+		/* only continue if this stroke is selected (editable doesn't guarantee this)... */
+		if ((gps->flag & GP_STROKE_SELECT) == 0)
+			continue;
+		
+		for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+			if (pt->flag & GP_SPOINT_SELECT) {
+				add_v3_v3(centroid, &pt->x);
+				minmax_v3v3_v3(min, max, &pt->x);
+				count++;
+			}
+		}
+	}
+	CTX_DATA_END;
+	
+	if (v3d->around == V3D_CENTROID) {
+		mul_v3_fl(centroid, 1.0f / (float)count);
+		copy_v3_v3(cursor, centroid);
+	}
+	else {
+		mid_v3_v3v3(cursor, min, max);
+	}
+
+	
+	WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+	return OPERATOR_FINISHED;
+}
+
+void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot)
+{
+	/* identifiers */
+	ot->name = "Snap Cursor to Selected Points";
+	ot->idname = "GPENCIL_OT_snap_cursor_to_selected";
+	ot->description = "Snap cursor to center of selected points";
+	
+	/* callbacks */
+	ot->exec = gp_snap_cursor_to_sel;
+	ot->poll = gp_snap_poll;
+	
+	/* flags */
+	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
 /* ************************************************ */
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 2480d92..9e7b88c 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -165,6 +165,12 @@ void GPENCIL_OT_paste(struct wmOperatorType *ot);
 void GPENCIL_OT_move_to_layer(struct wmOperatorType *ot);
 void GPENCIL_OT_layer_change(struct wmOperatorType *ot);
 
+void GPENCIL_OT_snap_to_grid(struct wmOperatorType *ot);
+void GPENCIL_OT_snap_to_cursor(struct wmOperatorType *ot);
+void GPENCIL_OT_snap_cursor_to_selected(struct wmOperatorType *ot);
+void GPENCIL_OT_snap_cursor_to_center(struct wmOperatorType *ot);
+
+
 /* stroke sculpting -- */
 
 void GPENCIL_OT_brush_paint(struct wmOperatorType *ot);
diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c
index bcb233c..3ed6b35 100644
--- a/source/blender/editors/gpencil/gpencil_ops.c
+++ b/source/blender/editors/gpencil/gpencil_ops.c
@@ -201,6 +201,9 @@ static void ed_keymap_gpencil_editing(wmKeyConfig *keyconf)
 	WM_keymap_add_item(keymap, "GPENCIL_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
 	WM_keymap_add_item(keymap, "GPENCIL_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
 #endif
+
+	/* snap */
+	WM_keymap_add_menu(keymap, "GPENCIL_MT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
 	
 	/* Show/Hide */
 	/* NOTE: These are available only in EditMode now, since they clash with general-purpose hotkeys */
@@ -309,6 +312,10 @@ void ED_operatortypes_gpencil(void)
 	WM_operatortype_append(GPENCIL_OT_move_to_layer);
 	WM_operatortype_append(GPENCIL_OT_layer_change);
 	
+	WM_operatortype_append(GPENCIL_OT_snap_to_grid);
+	WM_operatortype_append(GPENCIL_OT_snap_to_cursor);
+	WM_operatortype_append(GPENCIL_OT_snap_cursor_to_selected);
+	
 	WM_operatortype_append(GPENCIL_OT_brush_paint);
 	
 	/* Editing (Buttons) ------------ */




More information about the Bf-blender-cvs mailing list