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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** \} */
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user