Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Vazquez <blendergit@gmail.com>2020-06-09 16:41:26 +0300
committerAntonio Vazquez <blendergit@gmail.com>2020-06-09 16:46:55 +0300
commit37d68871b7c5e6dea36ce4e08013eb645ef550c9 (patch)
treebc221a53f7683850526a3fb51d22561c9d1714cf /source/blender/editors/gpencil
parentc23b1de2cf8ad13f102d2d5484d09e280b36dda4 (diff)
GPencil: Keep original stroke when reproject
When reproject a stroke sometimes is good to keep the copy of the original stroke to create volume effects Related to T77639 {F8603513} Reviewed By: mendio, pepeland Maniphest Tasks: T77639 Differential Revision: https://developer.blender.org/D7963 50258
Diffstat (limited to 'source/blender/editors/gpencil')
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c138
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c131
2 files changed, 145 insertions, 124 deletions
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 8771fcb0c8d..76776b5c23c 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -3633,43 +3633,25 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot)
/** \name Stroke Re-project Operator
* \{ */
-typedef enum eGP_ReprojectModes {
- /* Axis */
- GP_REPROJECT_FRONT = 0,
- GP_REPROJECT_SIDE,
- GP_REPROJECT_TOP,
- /* On same plane, parallel to view-plane. */
- GP_REPROJECT_VIEW,
- /* Reprojected on to the scene geometry */
- GP_REPROJECT_SURFACE,
- /* Reprojected on 3D cursor orientation */
- GP_REPROJECT_CURSOR,
-} eGP_ReprojectModes;
-
static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Scene *scene = CTX_data_scene(C);
Main *bmain = CTX_data_main(C);
- ToolSettings *ts = CTX_data_tool_settings(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Object *ob = CTX_data_active_object(C);
ARegion *region = CTX_wm_region(C);
- RegionView3D *rv3d = region->regiondata;
- SnapObjectContext *sctx = NULL;
int oldframe = (int)DEG_get_ctime(depsgraph);
+ const eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
+ const bool keep_original = RNA_boolean_get(op->ptr, "keep_original");
+ /* Init space conversion stuff. */
GP_SpaceConversion gsc = {NULL};
- eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
-
- float origin[3];
-
- /* init space conversion stuff */
+ SnapObjectContext *sctx = NULL;
gp_point_conversion_init(C, &gsc);
+ /* Init snap context for geometry projection. */
+ sctx = ED_transform_snap_object_context_create_view3d(scene, 0, region, CTX_wm_view3d(C));
int cfra_prv = INT_MIN;
- /* init snap context for geometry projection */
- sctx = ED_transform_snap_object_context_create_view3d(scene, 0, region, CTX_wm_view3d(C));
/* Go through each editable + selected stroke, adjusting each of its points one by one... */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
@@ -3682,106 +3664,7 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
- bGPDspoint *pt;
- int i;
- /* Adjust each point */
- for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- float xy[2];
-
- /* 3D to Screen-space */
- /* Note: We can't use gp_point_to_xy() here because that uses ints for the screen-space
- * coordinates, resulting in lost precision, which in turn causes stair-stepping
- * artifacts in the final points. */
-
- bGPDspoint pt2;
- gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
- gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
-
- /* Project stroke in one axis */
- if (ELEM(mode,
- GP_REPROJECT_FRONT,
- GP_REPROJECT_SIDE,
- GP_REPROJECT_TOP,
- GP_REPROJECT_CURSOR)) {
- if (mode != GP_REPROJECT_CURSOR) {
- ED_gpencil_drawing_reference_get(scene, ob, ts->gpencil_v3d_align, origin);
- }
- else {
- copy_v3_v3(origin, scene->cursor.location);
- }
-
- int axis = 0;
- switch (mode) {
- case GP_REPROJECT_FRONT: {
- axis = 1;
- break;
- }
- case GP_REPROJECT_SIDE: {
- axis = 0;
- break;
- }
- case GP_REPROJECT_TOP: {
- axis = 2;
- break;
- }
- case GP_REPROJECT_CURSOR: {
- axis = 3;
- break;
- }
- default: {
- axis = 1;
- break;
- }
- }
-
- ED_gp_project_point_to_plane(scene, ob, rv3d, origin, axis, &pt2);
-
- copy_v3_v3(&pt->x, &pt2.x);
-
- /* apply parent again */
- gp_apply_parent_point(depsgraph, ob, gpl, pt);
- }
- /* Project screen-space back to 3D space (from current perspective)
- * so that all points have been treated the same way. */
- else if (mode == GP_REPROJECT_VIEW) {
- /* Planar - All on same plane parallel to the view-plane. */
- gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
- }
- else {
- /* Geometry - Snap to surfaces of visible geometry */
- float ray_start[3];
- float ray_normal[3];
- /* magic value for initial depth copied from the default
- * value of Python's Scene.ray_cast function
- */
- float depth = 1.70141e+38f;
- float location[3] = {0.0f, 0.0f, 0.0f};
- float normal[3] = {0.0f, 0.0f, 0.0f};
-
- ED_view3d_win_to_ray(region, xy, &ray_start[0], &ray_normal[0]);
- if (ED_transform_snap_object_project_ray(sctx,
- depsgraph,
- &(const struct SnapObjectParams){
- .snap_select = SNAP_ALL,
- },
- &ray_start[0],
- &ray_normal[0],
- &depth,
- &location[0],
- &normal[0])) {
- copy_v3_v3(&pt->x, location);
- }
- else {
- /* Default to planar */
- gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
- }
- }
-
- /* Unapply parent corrections */
- if (!ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP)) {
- mul_m4_v3(gpstroke_iter.inverse_diff_mat, &pt->x);
- }
- }
+ ED_gpencil_stroke_reproject(depsgraph, &gsc, sctx, gpl, gpf_, gps, mode, keep_original);
}
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
@@ -3844,6 +3727,13 @@ void GPENCIL_OT_reproject(wmOperatorType *ot)
/* properties */
ot->prop = RNA_def_enum(
ot->srna, "type", reproject_type, GP_REPROJECT_VIEW, "Projection Type", "");
+
+ RNA_def_boolean(
+ ot->srna,
+ "keep_original",
+ 0,
+ "Keep Original",
+ "Keep original strokes and create a copy before reprojecting instead of reproject them");
}
static int gp_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op))
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 876fa7c9874..467b7ee86bf 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1118,6 +1118,137 @@ void ED_gp_project_stroke_to_plane(const Scene *scene,
}
}
+/* Reproject selected strokes */
+void ED_gpencil_stroke_reproject(Depsgraph *depsgraph,
+ const GP_SpaceConversion *gsc,
+ SnapObjectContext *sctx,
+ bGPDlayer *gpl,
+ bGPDframe *gpf,
+ bGPDstroke *gps,
+ const eGP_ReprojectModes mode,
+ const bool keep_original)
+{
+ ToolSettings *ts = gsc->scene->toolsettings;
+ ARegion *region = gsc->region;
+ RegionView3D *rv3d = region->regiondata;
+
+ float diff_mat[4][4], inverse_diff_mat[4][4];
+ BKE_gpencil_parent_matrix_get(depsgraph, gsc->ob, gpl, diff_mat);
+ invert_m4_m4(inverse_diff_mat, diff_mat);
+
+ float origin[3];
+ if (mode != GP_REPROJECT_CURSOR) {
+ ED_gpencil_drawing_reference_get(gsc->scene, gsc->ob, ts->gpencil_v3d_align, origin);
+ }
+ else {
+ copy_v3_v3(origin, gsc->scene->cursor.location);
+ }
+
+ bGPDspoint *pt;
+ int i;
+
+ /* If keep original, do a copy. */
+ bGPDstroke *gps_active = gps;
+ /* if duplicate, deselect all points. */
+ if (keep_original) {
+ gps_active = BKE_gpencil_stroke_duplicate(gps, true);
+ gps_active->flag &= ~GP_STROKE_SELECT;
+ for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) {
+ pt->flag &= ~GP_SPOINT_SELECT;
+ }
+ /* Add to frame. */
+ BLI_addtail(&gpf->strokes, gps_active);
+ }
+
+ /* Adjust each point */
+ for (i = 0, pt = gps_active->points; i < gps_active->totpoints; i++, pt++) {
+ float xy[2];
+
+ /* 3D to Screen-space */
+ /* Note: We can't use gp_point_to_xy() here because that uses ints for the screen-space
+ * coordinates, resulting in lost precision, which in turn causes stair-stepping
+ * artifacts in the final points. */
+
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy_fl(gsc, gps_active, &pt2, &xy[0], &xy[1]);
+
+ /* Project stroke in one axis */
+ if (ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP, GP_REPROJECT_CURSOR)) {
+ int axis = 0;
+ switch (mode) {
+ case GP_REPROJECT_FRONT: {
+ axis = 1;
+ break;
+ }
+ case GP_REPROJECT_SIDE: {
+ axis = 0;
+ break;
+ }
+ case GP_REPROJECT_TOP: {
+ axis = 2;
+ break;
+ }
+ case GP_REPROJECT_CURSOR: {
+ axis = 3;
+ break;
+ }
+ default: {
+ axis = 1;
+ break;
+ }
+ }
+
+ ED_gp_project_point_to_plane(gsc->scene, gsc->ob, rv3d, origin, axis, &pt2);
+
+ copy_v3_v3(&pt->x, &pt2.x);
+
+ /* apply parent again */
+ gp_apply_parent_point(depsgraph, gsc->ob, gpl, pt);
+ }
+ /* Project screen-space back to 3D space (from current perspective)
+ * so that all points have been treated the same way. */
+ else if (mode == GP_REPROJECT_VIEW) {
+ /* Planar - All on same plane parallel to the view-plane. */
+ gp_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x);
+ }
+ else {
+ /* Geometry - Snap to surfaces of visible geometry */
+ float ray_start[3];
+ float ray_normal[3];
+ /* magic value for initial depth copied from the default
+ * value of Python's Scene.ray_cast function
+ */
+ float depth = 1.70141e+38f;
+ float location[3] = {0.0f, 0.0f, 0.0f};
+ float normal[3] = {0.0f, 0.0f, 0.0f};
+
+ ED_view3d_win_to_ray(region, xy, &ray_start[0], &ray_normal[0]);
+ if (ED_transform_snap_object_project_ray(sctx,
+ depsgraph,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ },
+ &ray_start[0],
+ &ray_normal[0],
+ &depth,
+ &location[0],
+ &normal[0])) {
+ copy_v3_v3(&pt->x, location);
+ }
+ else {
+ /* Default to planar */
+ gp_point_xy_to_3d(gsc, gsc->scene, xy, &pt->x);
+ }
+ }
+
+ /* Unapply parent corrections */
+ if (!ELEM(mode, GP_REPROJECT_FRONT, GP_REPROJECT_SIDE, GP_REPROJECT_TOP)) {
+ mul_m4_v3(inverse_diff_mat, &pt->x);
+ }
+ }
+}
+
/**
* Reproject given point to a plane locked to axis to avoid stroke offset
* \param[in,out] pt: Point to affect