From 0bfec04cd5541551fea45d0f021e2df0aca80d2f Mon Sep 17 00:00:00 2001 From: Sebastian Parborg Date: Tue, 21 Jul 2020 12:11:56 +0200 Subject: Fix T72621: Transform object origin support for grease-pencil Added support for transforming only origins with greasepencil objects. The new functions is based on BKE_gpencil_transform. That is why there is FIXME statements in there. Reviewed By: Campbell, Antonio Differential Revision: http://developer.blender.org/D8303 --- source/blender/blenkernel/BKE_gpencil_geom.h | 14 +++ source/blender/blenkernel/intern/gpencil_geom.c | 129 +++++++++++++++++++++ .../blender/editors/object/object_data_transform.c | 34 ++++++ 3 files changed, 177 insertions(+) diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 6b0f9428f82..1b22931483c 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -78,6 +78,20 @@ void BKE_gpencil_stroke_uv_update(struct bGPDstroke *gps); void BKE_gpencil_transform(struct bGPdata *gpd, float mat[4][4]); +typedef struct GPencilPointCoordinates { + /* This is used when doing "move only origin" in object_data_transform.c. + * pressure is needs to be stored here as it is tied to object scale. */ + float co[3]; + float pressure; +} GPencilPointCoordinates; + +int BKE_gpencil_stroke_point_count(struct bGPdata *gpd); +void BKE_gpencil_point_coords_get(struct bGPdata *gpd, GPencilPointCoordinates *elem_data); +void BKE_gpencil_point_coords_apply(struct bGPdata *gpd, const GPencilPointCoordinates *elem_data); +void BKE_gpencil_point_coords_apply_with_mat4(struct bGPdata *gpd, + const GPencilPointCoordinates *elem_data, + const float mat[4][4]); + bool BKE_gpencil_stroke_sample(struct bGPDstroke *gps, const float dist, const bool select); bool BKE_gpencil_stroke_smooth(struct bGPDstroke *gps, int i, float inf); bool BKE_gpencil_stroke_smooth_strength(struct bGPDstroke *gps, int point_index, float influence); diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 5e55d3b2bef..0b965899689 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -2458,4 +2458,133 @@ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4]) } } } + +/* Used for "move only origins" in object_data_transform.c */ +int BKE_gpencil_stroke_point_count(bGPdata *gpd) +{ + int total_points = 0; + + if (gpd == NULL) { + return 0; + } + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + total_points += gps->totpoints; + } + } + } + return total_points; +} + +/* Used for "move only origins" in object_data_transform.c */ +void BKE_gpencil_point_coords_get(bGPdata *gpd, GPencilPointCoordinates *elem_data) +{ + if (gpd == NULL) { + return; + } + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + + for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) { + copy_v3_v3(elem_data->co, &pt->x); + elem_data->pressure = pt->pressure; + elem_data++; + } + } + } + } +} + +/* Used for "move only origins" in object_data_transform.c */ +void BKE_gpencil_point_coords_apply(bGPdata *gpd, const GPencilPointCoordinates *elem_data) +{ + if (gpd == NULL) { + return; + } + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + + for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) { + copy_v3_v3(&pt->x, elem_data->co); + pt->pressure = elem_data->pressure; + elem_data++; + } + + /* Distortion may mean we need to re-triangulate. */ + BKE_gpencil_stroke_geometry_update(gps); + } + } + } +} + +/* Used for "move only origins" in object_data_transform.c */ +void BKE_gpencil_point_coords_apply_with_mat4(bGPdata *gpd, + const GPencilPointCoordinates *elem_data, + const float mat[4][4]) +{ + if (gpd == NULL) { + return; + } + + const float scalef = mat4_to_scale(mat); + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + /* FIXME: For now, we just skip parented layers. + * Otherwise, we have to update each frame to find + * the current parent position/effects. + */ + if (gpl->parent) { + continue; + } + + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + bGPDspoint *pt; + int i; + + for (pt = gps->points, i = 0; i < gps->totpoints; pt++, i++) { + mul_v3_m4v3(&pt->x, mat, elem_data->co); + pt->pressure = elem_data->pressure * scalef; + elem_data++; + } + + /* Distortion may mean we need to re-triangulate. */ + BKE_gpencil_stroke_geometry_update(gps); + } + } + } +} /** \} */ diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c index 54fd1fe6671..1e030a50f38 100644 --- a/source/blender/editors/object/object_data_transform.c +++ b/source/blender/editors/object/object_data_transform.c @@ -33,6 +33,7 @@ #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_collection_types.h" +#include "DNA_gpencil_types.h" #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" @@ -46,6 +47,7 @@ #include "BKE_armature.h" #include "BKE_curve.h" #include "BKE_editmesh.h" +#include "BKE_gpencil_geom.h" #include "BKE_lattice.h" #include "BKE_mball.h" #include "BKE_mesh.h" @@ -303,6 +305,11 @@ struct XFormObjectData_MetaBall { struct ElemData_MetaBall elem_array[0]; }; +struct XFormObjectData_GPencil { + struct XFormObjectData base; + struct GPencilPointCoordinates elem_array[0]; +}; + struct XFormObjectData *ED_object_data_xform_create_ex(ID *id, bool is_edit_mode) { struct XFormObjectData *xod_base = NULL; @@ -391,6 +398,15 @@ struct XFormObjectData *ED_object_data_xform_create_ex(ID *id, bool is_edit_mode xod_base = &xod->base; break; } + case ID_GD: { + bGPdata *gpd = (bGPdata *)id; + const int elem_array_len = BKE_gpencil_stroke_point_count(gpd); + struct XFormObjectData_GPencil *xod = MEM_mallocN( + sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__); + BKE_gpencil_point_coords_get(gpd, xod->elem_array); + xod_base = &xod->base; + break; + } default: { break; } @@ -471,6 +487,12 @@ void ED_object_data_xform_by_mat4(struct XFormObjectData *xod_base, const float metaball_coords_and_quats_apply_with_mat4(mb, xod->elem_array, mat); break; } + case ID_GD: { + bGPdata *gpd = (bGPdata *)xod_base->id; + struct XFormObjectData_GPencil *xod = (struct XFormObjectData_GPencil *)xod_base; + BKE_gpencil_point_coords_apply_with_mat4(gpd, xod->elem_array, mat); + break; + } default: { break; } @@ -529,6 +551,12 @@ void ED_object_data_xform_restore(struct XFormObjectData *xod_base) metaball_coords_and_quats_apply(mb, xod->elem_array); break; } + case ID_GD: { + bGPdata *gpd = (bGPdata *)xod_base->id; + struct XFormObjectData_GPencil *xod = (struct XFormObjectData_GPencil *)xod_base; + BKE_gpencil_point_coords_apply(gpd, xod->elem_array); + break; + } default: { break; } @@ -572,6 +600,12 @@ void ED_object_data_xform_tag_update(struct XFormObjectData *xod_base) DEG_id_tag_update(&mb->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); break; } + case ID_GD: { + /* Generic update. */ + bGPdata *gpd = (bGPdata *)xod_base->id; + DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); + break; + } default: { break; -- cgit v1.2.3