GPencil: Fix unreported error baking mesh animation

When the mesh is linked, the materials can not be available or be the same assigned to mesh. Now, if the mesh is linked, a simple two materials conversion is used.

To get the full list of materials, the mesh must not be linked.

Also checked some indexes to be sure never get a wrong value and that materials are not created again and again.
This commit is contained in:
Antonio Vazquez 2020-07-15 17:25:07 +02:00
parent 36e836d0e9
commit ae4098e234
4 changed files with 48 additions and 15 deletions

View File

@ -109,7 +109,8 @@ void BKE_gpencil_convert_mesh(struct Main *bmain,
const float matrix[4][4],
const int frame_offset,
const bool use_seams,
const bool use_faces);
const bool use_faces,
const bool simple_material);
#ifdef __cplusplus
}

View File

@ -2088,6 +2088,7 @@ static int gpencil_walk_edge(GHash *v_table,
static void gpencil_generate_edgeloops(Object *ob,
bGPDframe *gpf_stroke,
int stroke_mat_index,
const float angle,
const int thickness,
const float offset,
@ -2175,7 +2176,7 @@ static void gpencil_generate_edgeloops(Object *ob,
/* Create Stroke. */
bGPDstroke *gps_stroke = BKE_gpencil_stroke_add(
gpf_stroke, 0, array_len + 1, thickness * thickness, false);
gpf_stroke, MAX2(stroke_mat_index, 0), array_len + 1, thickness * thickness, false);
/* Create first segment. */
float fpt[3];
@ -2258,6 +2259,17 @@ static Material *gpencil_add_material(Main *bmain,
return mat_gp;
}
static int gpencil_material_find_index_byname(Object *ob, char *name, const int num)
{
for (int i = 0; i < ob->totcol; i++) {
Material *ma = BKE_object_material_get(ob, i + 1);
if ((ma != NULL) && (ma->gp_style != NULL) && (STREQLEN(ma->id.name + 2, name, num))) {
return i;
}
}
return -1;
}
/**
* Convert a mesh object to grease pencil stroke.
*
@ -2273,6 +2285,7 @@ static Material *gpencil_add_material(Main *bmain,
* \param frame_offset: Destination frame number offset.
* \param use_seams: Only export seam edges.
* \param use_faces: Export faces as filled strokes.
* \simple_material: Create only 2 materials (stroke and fill)
*/
void BKE_gpencil_convert_mesh(Main *bmain,
Depsgraph *depsgraph,
@ -2285,7 +2298,8 @@ void BKE_gpencil_convert_mesh(Main *bmain,
const float matrix[4][4],
const int frame_offset,
const bool use_seams,
const bool use_faces)
const bool use_faces,
const bool simple_material)
{
if (ELEM(NULL, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
return;
@ -2300,6 +2314,8 @@ void BKE_gpencil_convert_mesh(Main *bmain,
MLoop *mloop = me_eval->mloop;
int mpoly_len = me_eval->totpoly;
int i;
int stroke_mat_index = gpencil_material_find_index_byname(ob_gp, "Stroke", 6);
int fill_mat_index = gpencil_material_find_index_byname(ob_gp, "Fill", 4);
/* If the object has enough materials means it was created in a previous step. */
const bool create_mat = ((ob_gp->totcol > 0) && (ob_gp->totcol >= ob_mesh->totcol)) ? false :
@ -2314,12 +2330,15 @@ void BKE_gpencil_convert_mesh(Main *bmain,
const float default_colors[2][4] = {{0.0f, 0.0f, 0.0f, 1.0f}, {0.7f, 0.7f, 0.7f, 1.0f}};
/* Create stroke material. */
if (create_mat) {
gpencil_add_material(bmain, ob_gp, "Stroke", default_colors[0], true, false, &r_idx);
if (stroke_mat_index == -1) {
gpencil_add_material(bmain, ob_gp, "Stroke", default_colors[0], true, false, &r_idx);
stroke_mat_index = ob_gp->totcol - 1;
}
}
/* Export faces as filled strokes. */
if (use_faces) {
if (create_mat) {
/* Find a material slot with material assigned */
/* Find a material slot with material assigned. */
bool material_found = false;
for (i = 0; i < ob_mesh->totcol; i++) {
Material *ma = BKE_object_material_get(ob_mesh, i + 1);
@ -2329,9 +2348,12 @@ void BKE_gpencil_convert_mesh(Main *bmain,
}
}
/* If no materials, create a simple fill. */
if (!material_found) {
gpencil_add_material(bmain, ob_gp, "Fill", default_colors[1], false, true, &r_idx);
/* If no materials or use simple materials, create a simple fill. */
if ((!material_found) || (simple_material)) {
if (fill_mat_index == -1) {
gpencil_add_material(bmain, ob_gp, "Fill", default_colors[1], false, true, &r_idx);
fill_mat_index = ob_gp->totcol - 1;
}
}
else {
/* Create all materials for fill. */
@ -2359,8 +2381,11 @@ void BKE_gpencil_convert_mesh(Main *bmain,
for (i = 0, mp = mpoly; i < mpoly_len; i++, mp++) {
MLoop *ml = &mloop[mp->loopstart];
/* Create fill stroke. */
bGPDstroke *gps_fill = BKE_gpencil_stroke_add(
gpf_fill, mp->mat_nr + 1, mp->totloop, 10, false);
int mat_idx = (simple_material) || (mp->mat_nr + 1 > ob_gp->totcol - 1) ?
MAX2(fill_mat_index, 0) :
mp->mat_nr + 1;
bGPDstroke *gps_fill = BKE_gpencil_stroke_add(gpf_fill, mat_idx, mp->totloop, 10, false);
gps_fill->flag |= GP_STROKE_CYCLIC;
/* Add points to strokes. */
@ -2387,7 +2412,8 @@ void BKE_gpencil_convert_mesh(Main *bmain,
}
bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get(
gpl_stroke, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
gpencil_generate_edgeloops(ob_eval, gpf_stroke, angle, thickness, offset, matrix, use_seams);
gpencil_generate_edgeloops(
ob_eval, gpf_stroke, stroke_mat_index, angle, thickness, offset, matrix, use_seams);
/* Tag for recalculation */
DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);

View File

@ -104,9 +104,10 @@ static void gpencil_bake_duplilist(Depsgraph *depsgraph, Scene *scene, Object *o
free_object_duplilist(lb);
}
static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list)
static bool gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene, ListBase *list)
{
GpBakeOb *elem = NULL;
bool simple_material = false;
/* Add active object. In some files this could not be in selected array. */
Object *obact = CTX_data_active_object(C);
@ -119,6 +120,7 @@ static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene
/* Add duplilist. */
else if (obact->type == OB_EMPTY) {
gpencil_bake_duplilist(depsgraph, scene, obact, list);
simple_material |= true;
}
/* Add other selected objects. */
@ -139,6 +141,8 @@ static void gpencil_bake_ob_list(bContext *C, Depsgraph *depsgraph, Scene *scene
}
}
CTX_DATA_END;
return simple_material;
}
static void gpencil_bake_free_ob_list(ListBase *list)
@ -158,7 +162,7 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
Object *ob_gpencil = NULL;
ListBase list = {NULL, NULL};
gpencil_bake_ob_list(C, depsgraph, scene, &list);
const bool simple_material = gpencil_bake_ob_list(C, depsgraph, scene, &list);
/* Cannot check this in poll because the active object changes. */
if (list.first == NULL) {
@ -260,7 +264,8 @@ static int gpencil_bake_mesh_animation_exec(bContext *C, wmOperator *op)
ob_eval->obmat,
frame_offset,
use_seams,
use_faces);
use_faces,
simple_material);
/* Reproject all untaged created strokes. */
if (project_type != GP_REPROJECT_KEEP) {

View File

@ -2451,7 +2451,8 @@ static int object_convert_exec(bContext *C, wmOperator *op)
matrix,
0,
use_seams,
use_faces);
use_faces,
false);
gpencilConverted = true;
/* Remove unused materials. */