diff options
14 files changed, 308 insertions, 421 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py index 90dc86a20bb..effa527e6db 100644 --- a/release/scripts/startup/bl_ui/properties_data_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py @@ -266,7 +266,10 @@ class DATA_PT_gpencil_onionpanel(Panel): layout = self.layout layout.use_property_split = True - layout.enabled = gpd.use_onion_skinning + layout.enabled = gpd.use_onion_skinning and gpd.users <= 1 + + if gpd.use_onion_skinning and gpd.users > 1: + layout.label("Multiuser datablock not supported", icon='ERROR') GreasePencilOnionPanel.draw_settings(layout, gpd) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index f865a7f7226..45af80c0a62 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -1843,7 +1843,6 @@ class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel): col = layout.column() col.prop(md, "count") - col.prop(md, "use_make_objects") split = layout.split() col = split.column() diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index d81dddb2b98..08d68f4a480 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -785,6 +785,14 @@ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) RNA_property_pointer_set(ptr, prop, idptr); RNA_property_update(C, ptr, prop); + /* tag grease pencil datablock and disable onion */ + if (GS(id->name) == ID_GD) { + DEG_id_tag_update(id, OB_RECALC_OB | OB_RECALC_DATA); + DEG_id_tag_update(newid, OB_RECALC_OB | OB_RECALC_DATA); + bGPdata *gpd = (bGPdata *)newid; + gpd->flag &= ~GP_DATA_SHOW_ONIONSKINS; + } + return true; } } diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c index e8bb27b2724..4c427a672d2 100644 --- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c @@ -37,9 +37,44 @@ #include "draw_cache_impl.h" +static bool gpencil_check_ob_duplicated(tGPencilObjectCache *cache_array, int gp_cache_used, Object *ob) +{ + if (gp_cache_used == 0) { + return false; + } + + for (int i = 0; i < gp_cache_used + 1; i++) { + tGPencilObjectCache *cache_elem = &cache_array[i]; + if (STREQ(cache_elem->ob_name, ob->id.name) && + (cache_elem->is_dup_ob == false)) + { + return true; + } + } + return false; +} + +static bool gpencil_check_datablock_duplicated(tGPencilObjectCache *cache_array, int gp_cache_used, + Object *ob, bGPdata *gpd) +{ + if (gp_cache_used == 0) { + return false; + } + + for (int i = 0; i < gp_cache_used + 1; i++) { + tGPencilObjectCache *cache_elem = &cache_array[i]; + if (!STREQ(cache_elem->ob_name, ob->id.name) && + (cache_elem->gpd == gpd)) + { + return true; + } + } + return false; +} + /* add a gpencil object to cache to defer drawing */ tGPencilObjectCache *gpencil_object_cache_add( - tGPencilObjectCache *cache_array, Object *ob, bool is_temp, + tGPencilObjectCache *cache_array, Object *ob, int *gp_cache_size, int *gp_cache_used) { const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -61,16 +96,26 @@ tGPencilObjectCache *gpencil_object_cache_add( } cache_array = p; } - /* zero out all pointers */ cache_elem = &cache_array[*gp_cache_used]; memset(cache_elem, 0, sizeof(*cache_elem)); - /* save object */ - cache_elem->ob = ob; - cache_elem->temp_ob = is_temp; + cache_elem->is_dup_ob = gpencil_check_ob_duplicated(cache_array, *gp_cache_used, ob); + + sprintf(cache_elem->ob_name, "%s", ob->id.name); + cache_elem->gpd = (bGPdata *)ob->data; + + copy_v3_v3(cache_elem->loc, ob->loc); + copy_m4_m4(cache_elem->obmat, ob->obmat); cache_elem->idx = *gp_cache_used; + cache_elem->is_dup_onion = gpencil_check_datablock_duplicated(cache_array, *gp_cache_used, + ob, cache_elem->gpd); + + /* save FXs */ + cache_elem->pixfactor = cache_elem->gpd->pixfactor; + cache_elem->shader_fx = ob->shader_fx; + cache_elem->init_grp = 0; cache_elem->end_grp = -1; @@ -203,7 +248,7 @@ static void gpencil_batch_cache_init(Object *ob, int cfra) } /* clear cache */ -static void gpencil_batch_cache_clear(GpencilBatchCache *cache, bGPdata *gpd) +static void gpencil_batch_cache_clear(GpencilBatchCache *cache) { if (!cache) { return; @@ -213,10 +258,6 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache, bGPdata *gpd) return; } - if (G.debug_value >= 664) { - printf("gpencil_batch_cache_clear: %s\n", gpd->id.name); - } - if (cache->cache_size > 0) { for (int i = 0; i < cache->cache_size; i++) { GPU_BATCH_DISCARD_SAFE(cache->batch_stroke[i]); @@ -245,7 +286,7 @@ GpencilBatchCache *gpencil_batch_cache_get(Object *ob, int cfra) GpencilBatchCache *cache = gpencil_batch_get_element(ob); if (cache) { - gpencil_batch_cache_clear(cache, gpd); + gpencil_batch_cache_clear(cache); BLI_ghash_remove(gpd->runtime.batch_cache_data, ob->id.name, NULL, NULL); } gpencil_batch_cache_init(ob, cfra); @@ -283,7 +324,7 @@ void DRW_gpencil_batch_cache_free(bGPdata *gpd) while (!BLI_ghashIterator_done(ihash)) { GpencilBatchCache *cache = (GpencilBatchCache *)BLI_ghashIterator_getValue(ihash); if (cache) { - gpencil_batch_cache_clear(cache, gpd); + gpencil_batch_cache_clear(cache); } BLI_ghashIterator_step(ihash); } diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c index 83a52e077ca..2102f255f75 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c @@ -52,12 +52,11 @@ /* Helper to add stroke point to vbo */ static void gpencil_set_stroke_point( - GPUVertBuf *vbo, float matrix[4][4], const bGPDspoint *pt, int idx, + GPUVertBuf *vbo, const bGPDspoint *pt, int idx, uint pos_id, uint color_id, uint thickness_id, uint uvdata_id, short thickness, const float ink[4]) { - float viewfpt[3]; float alpha = ink[3] * pt->strength; CLAMP(alpha, GPENCIL_STRENGTH_MIN, 1.0f); @@ -71,7 +70,6 @@ static void gpencil_set_stroke_point( GPU_vertbuf_attr_set(vbo, uvdata_id, idx, uvdata); /* the thickness of the stroke must be affected by zoom, so a pixel scale is calculated */ - mul_v3_m4v3(viewfpt, matrix, &pt->x); float thick = max_ff(pt->pressure * thickness, 1.0f); GPU_vertbuf_attr_set(vbo, thickness_id, idx, &thick); @@ -132,7 +130,7 @@ GPUBatch *DRW_gpencil_get_point_geom(bGPDstroke *gps, short thickness, const flo } /* create batch geometry data for stroke shader */ -GPUBatch *DRW_gpencil_get_stroke_geom(bGPDframe *gpf, bGPDstroke *gps, short thickness, const float ink[4]) +GPUBatch *DRW_gpencil_get_stroke_geom(bGPDstroke *gps, short thickness, const float ink[4]) { bGPDspoint *points = gps->points; int totpoints = gps->totpoints; @@ -159,20 +157,20 @@ GPUBatch *DRW_gpencil_get_stroke_geom(bGPDframe *gpf, bGPDstroke *gps, short thi if (i == 0) { if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) { gpencil_set_stroke_point( - vbo, gpf->runtime.viewmatrix, &points[totpoints - 1], idx, + vbo, &points[totpoints - 1], idx, pos_id, color_id, thickness_id, uvdata_id, thickness, ink); idx++; } else { gpencil_set_stroke_point( - vbo, gpf->runtime.viewmatrix, &points[1], idx, + vbo, &points[1], idx, pos_id, color_id, thickness_id, uvdata_id, thickness, ink); idx++; } } /* set point */ gpencil_set_stroke_point( - vbo, gpf->runtime.viewmatrix, pt, idx, + vbo, pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, ink); idx++; } @@ -180,19 +178,19 @@ GPUBatch *DRW_gpencil_get_stroke_geom(bGPDframe *gpf, bGPDstroke *gps, short thi if (gps->flag & GP_STROKE_CYCLIC && totpoints > 2) { /* draw line to first point to complete the cycle */ gpencil_set_stroke_point( - vbo, gpf->runtime.viewmatrix, &points[0], idx, + vbo, &points[0], idx, pos_id, color_id, thickness_id, uvdata_id, thickness, ink); idx++; /* now add adjacency point (not drawn) */ gpencil_set_stroke_point( - vbo, gpf->runtime.viewmatrix, &points[1], idx, + vbo, &points[1], idx, pos_id, color_id, thickness_id, uvdata_id, thickness, ink); idx++; } /* last adjacency point (not drawn) */ else { gpencil_set_stroke_point( - vbo, gpf->runtime.viewmatrix, &points[totpoints - 2], idx, + vbo, &points[totpoints - 2], idx, pos_id, color_id, thickness_id, uvdata_id, thickness, ink); } @@ -200,7 +198,7 @@ GPUBatch *DRW_gpencil_get_stroke_geom(bGPDframe *gpf, bGPDstroke *gps, short thi } /* create batch geometry data for current buffer stroke shader */ -GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, float matrix[4][4], short thickness) +GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, short thickness) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; @@ -244,19 +242,19 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, float matrix[4][4], s if (totpoints > 1) { ED_gpencil_tpoint_to_point(ar, origin, &points[1], &pt2); gpencil_set_stroke_point( - vbo, matrix, &pt2, idx, + vbo, &pt2, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); } else { gpencil_set_stroke_point( - vbo, matrix, &pt, idx, + vbo, &pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); } idx++; } /* set point */ gpencil_set_stroke_point( - vbo, matrix, &pt, idx, + vbo, &pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); idx++; } @@ -265,12 +263,12 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, float matrix[4][4], s if (totpoints > 2) { ED_gpencil_tpoint_to_point(ar, origin, &points[totpoints - 2], &pt2); gpencil_set_stroke_point( - vbo, matrix, &pt2, idx, + vbo, &pt2, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); } else { gpencil_set_stroke_point( - vbo, matrix, &pt, idx, + vbo, &pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); } @@ -278,7 +276,7 @@ GPUBatch *DRW_gpencil_get_buffer_stroke_geom(bGPdata *gpd, float matrix[4][4], s } /* create batch geometry data for current buffer point shader */ -GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, float matrix[4][4], short thickness) +GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, short thickness) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; @@ -319,7 +317,7 @@ GPUBatch *DRW_gpencil_get_buffer_point_geom(bGPdata *gpd, float matrix[4][4], sh /* set point */ gpencil_set_stroke_point( - vbo, matrix, &pt, idx, + vbo, &pt, idx, pos_id, color_id, thickness_id, uvdata_id, thickness, gpd->runtime.scolor); idx++; diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c index 401934b35a7..16412dda3f8 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c @@ -587,7 +587,8 @@ static void gpencil_add_fill_shgroup( /* add stroke shading group to pass */ static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup *strokegrp, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, - const float opacity, const float tintcolor[4], const bool onion, const bool custonion) + const float opacity, const float tintcolor[4], const bool onion, + const bool custonion) { float tcolor[4]; float ink[4]; @@ -622,7 +623,7 @@ static void gpencil_add_stroke_shgroup(GpencilBatchCache *cache, DRWShadingGroup if (cache->is_dirty) { gpencil_batch_cache_check_free_slots(ob); if ((gps->totpoints > 1) && (gp_style->mode == GP_STYLE_MODE_LINE)) { - cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_stroke_geom(gpf, gps, sthickness, ink); + cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_stroke_geom(gps, sthickness, ink); } else { cache->batch_stroke[cache->cache_idx] = DRW_gpencil_get_point_geom(gps, sthickness, ink); @@ -742,7 +743,8 @@ static void gpencil_draw_onion_strokes( static void gpencil_draw_strokes( GpencilBatchCache *cache, GPENCIL_e_data *e_data, void *vedata, ToolSettings *ts, Object *ob, bGPdata *gpd, bGPDlayer *gpl, bGPDframe *src_gpf, bGPDframe *derived_gpf, - const float opacity, const float tintcolor[4], const bool custonion) + const float opacity, const float tintcolor[4], + const bool custonion, tGPencilObjectCache *cache_ob) { GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; @@ -769,6 +771,10 @@ static void gpencil_draw_strokes( ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix); copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix); + if ((cache_ob != NULL) && (cache_ob->is_dup_ob)) { + copy_m4_m4(derived_gpf->runtime.viewmatrix, cache_ob->obmat); + } + /* apply geometry modifiers */ if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) { if (!stl->storage->simplify_modif) { @@ -797,7 +803,7 @@ static void gpencil_draw_strokes( continue; } - /* be sure recalc all chache in source stroke to avoid recalculation when frame change + /* be sure recalc all cache in source stroke to avoid recalculation when frame change * and improve fps */ if (src_gps) { DRW_gpencil_recalc_geometry_caches(ob, gp_style, src_gps); @@ -859,17 +865,21 @@ static void gpencil_draw_strokes( /* fill */ if ((fillgrp) && (!stl->storage->simplify_fill)) { gpencil_add_fill_shgroup( - cache, fillgrp, ob, gpl, derived_gpf, gps, tintcolor, false, custonion); + cache, fillgrp, ob, gpl, derived_gpf, gps, + tintcolor, false, custonion); } /* stroke */ if (strokegrp) { gpencil_add_stroke_shgroup( - cache, strokegrp, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion); + cache, strokegrp, ob, gpl, derived_gpf, gps, + opacity, tintcolor, false, custonion); } } /* edit points (only in edit mode and not play animation not render) */ - if ((src_gps) && (!playing) && (!is_render)) { + if ((draw_ctx->obact == ob) && (src_gps) && + (!playing) && (!is_render) && (!cache_ob->is_dup_ob)) + { if (!stl->g_data->shgrps_edit_line) { stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh, psl->edit_pass); } @@ -942,11 +952,11 @@ void DRW_gpencil_populate_buffer_strokes(GPENCIL_e_data *e_data, void *vedata, T /* use unit matrix because the buffer is in screen space and does not need conversion */ if (gpd->runtime.mode == GP_STYLE_MODE_LINE) { e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_stroke_geom( - gpd, stl->storage->unit_matrix, lthick); + gpd, lthick); } else { e_data->batch_buffer_stroke = DRW_gpencil_get_buffer_point_geom( - gpd, stl->storage->unit_matrix, lthick); + gpd, lthick); } DRW_shgroup_call_add( @@ -1146,8 +1156,10 @@ static void gpencil_draw_onionskins( } /* populate a datablock for multiedit (no onions, no modifiers) */ -void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob, bGPdata *gpd) +void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob, + tGPencilObjectCache *cache_ob) { + bGPdata *gpd = (bGPdata *)ob->data; bGPDframe *gpf = NULL; GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; @@ -1172,7 +1184,7 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene if ((gpf == gpl->actframe) || (gpf->flag & GP_FRAME_SELECT)) { gpencil_draw_strokes( cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf, - gpl->opacity, gpl->tintcolor, false); + gpl->opacity, gpl->tintcolor, false, cache_ob); } } } @@ -1181,7 +1193,7 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene if (gpf) { gpencil_draw_strokes( cache, e_data, vedata, ts, ob, gpd, gpl, gpf, gpf, - gpl->opacity, gpl->tintcolor, false); + gpl->opacity, gpl->tintcolor, false, cache_ob); } } @@ -1191,16 +1203,20 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data, void *vedata, Scene } /* helper for populate a complete grease pencil datablock */ -void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene *scene, Object *ob, bGPdata *gpd) +void DRW_gpencil_populate_datablock( + GPENCIL_e_data *e_data, void *vedata, + Scene *scene, Object *ob, + tGPencilObjectCache *cache_ob) { GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; const DRWContextState *draw_ctx = DRW_context_state_get(); + bGPdata *gpd = (bGPdata *)ob->data; View3D *v3d = draw_ctx->v3d; int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph); ToolSettings *ts = scene->toolsettings; bGPDframe *derived_gpf = NULL; - const bool main_onion = v3d != NULL ? ((v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) == 0) : true; - const bool no_onion = (bool)(gpd->flag & GP_DATA_STROKE_WEIGHTMODE) || main_onion; + const bool main_onion = v3d != NULL ? (v3d->gp_flag & V3D_GP_SHOW_ONION_SKIN) : true; + const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && main_onion; const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) : true; /* check if playing animation */ @@ -1230,17 +1246,21 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene gpl->runtime.derived_data = (GHash *)BLI_ghash_str_new(gpl->info); } - if (BLI_ghash_haskey(gpl->runtime.derived_data, ob->id.name)) { + if (BLI_ghash_haskey(gpl->runtime.derived_data,ob->id.name)) { derived_gpf = BLI_ghash_lookup(gpl->runtime.derived_data, ob->id.name); } else { + /* verify we have frame duplicated already */ + if (cache_ob->is_dup_ob) { + continue; + } derived_gpf = NULL; } if (derived_gpf == NULL) { cache->is_dirty = true; } - if (cache->is_dirty) { + if ((!cache_ob->is_dup_ob) && (cache->is_dirty)) { if (derived_gpf != NULL) { /* first clear temp data */ if (BLI_ghash_haskey(gpl->runtime.derived_data, ob->id.name)) { @@ -1258,24 +1278,36 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene BLI_ghash_reinsert(gpl->runtime.derived_data, ob->id.name, derived_gpf, NULL, NULL); } } - /* draw onion skins */ - if ((gpd->flag & GP_DATA_SHOW_ONIONSKINS) && - (!no_onion) && (overlay) && - (gpl->onion_flag & GP_LAYER_ONIONSKIN) && - ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS))) - { - if ((!stl->storage->is_render) || - ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS))) + if (!ID_IS_LINKED(&gpd->id)) { + ID *orig_id = gpd->id.orig_id; + /* GPXX: Now only a datablock with one use is allowed to be compatible + * with instances + */ + if ((!cache_ob->is_dup_onion) && (gpd->flag & GP_DATA_SHOW_ONIONSKINS) && + (do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN) && + ((!playing) || (gpd->onion_flag & GP_ONION_GHOST_ALWAYS)) && + (!cache_ob->is_dup_ob) && (orig_id->us <= 1)) { - gpencil_draw_onionskins(cache, e_data, vedata, ob, gpd, gpl, gpf); + if (((!stl->storage->is_render) && (overlay)) || + ((stl->storage->is_render) && (gpd->onion_flag & GP_ONION_GHOST_ALWAYS))) + { + gpencil_draw_onionskins(cache, e_data, vedata, ob, gpd, gpl, gpf); + } } } - /* draw normal strokes */ + if (!cache_ob->is_dup_ob) { + /* save batch index */ + gpl->runtime.batch_index = cache->cache_idx; + } + else { + cache->cache_idx = gpl->runtime.batch_index; + } + gpencil_draw_strokes( cache, e_data, vedata, ts, ob, gpd, gpl, gpf, derived_gpf, - gpl->opacity, gpl->tintcolor, false); + gpl->opacity, gpl->tintcolor, false, cache_ob); } @@ -1286,99 +1318,3 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data, void *vedata, Scene cache->is_dirty = false; } - -/* Helper for gpencil_instance_modifiers() - * See also MOD_gpencilinstance.c -> bakeModifier() - */ -static void gp_instance_modifier_make_instances(GPENCIL_StorageList *stl, Object *ob, InstanceGpencilModifierData *mmd) -{ - /* reset random */ - mmd->rnd[0] = 1; - int e = 0; - - /* Generate instances */ - for (int x = 0; x < mmd->count[0]; x++) { - for (int y = 0; y < mmd->count[1]; y++) { - for (int z = 0; z < mmd->count[2]; z++) { - if ((x == 0) && (y == 0) && (z == 0)) { - continue; - } - - Object *newob = NULL; - const int elem_idx[3] = {x, y, z}; - float mat[4][4]; - int sh; - - /* original strokes are at index = 0,0,0 */ - if ((x == 0) && (y == 0) && (z == 0)) { - continue; - } - - /* compute transform for instance */ - BKE_gpencil_instance_modifier_instance_tfm(mmd, elem_idx, mat); - - /* add object to cache */ - newob = MEM_dupallocN(ob); - - /* Create a unique name or the object hash used in draw will fail. - * the name must be unique in the hash, not in the scene because - * the object never is linked to scene and is removed after drawing. - * - * It uses special characters to be sure the name cannot be equal - * to any existing name because UI limits the use of special characters. - * - * Name = OB\t_{pointer}_{index} - */ - sprintf(newob->id.name, "OB\t_%p_%d", &ob, e++); - - mul_m4_m4m4(newob->obmat, ob->obmat, mat); - - /* apply scale */ - ARRAY_SET_ITEMS(newob->size, mat[0][0], mat[1][1], mat[2][2]); - - /* apply shift */ - sh = x; - if (mmd->lock_axis == GP_LOCKAXIS_Y) { - sh = y; - } - if (mmd->lock_axis == GP_LOCKAXIS_Z) { - sh = z; - } - madd_v3_v3fl(newob->obmat[3], mmd->shift, sh); - - /* add temp object to cache */ - stl->g_data->gp_object_cache = gpencil_object_cache_add( - stl->g_data->gp_object_cache, newob, true, - &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used); - } - } - } -} - -/* create instances using instance modifiers */ -void gpencil_instance_modifiers(GPENCIL_StorageList *stl, Object *ob) -{ - if ((ob) && (ob->data)) { - bGPdata *gpd = ob->data; - if (GPENCIL_ANY_EDIT_MODE(gpd)) { - return; - } - } - - for (GpencilModifierData *md = ob->greasepencil_modifiers.first; md; md = md->next) { - if (((md->mode & eGpencilModifierMode_Realtime) && (stl->storage->is_render == false)) || - ((md->mode & eGpencilModifierMode_Render) && (stl->storage->is_render == true))) - { - if (md->type == eGpencilModifierType_Instance) { - InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; - - /* Only add instances if the "Make Objects" flag is set - * FIXME: This is a workaround for z-ordering weirdness when all instances are in the same object - */ - if (mmd->flag & GP_INSTANCE_MAKE_OBJECTS) { - gp_instance_modifier_make_instances(stl, ob, mmd); - } - } - } - } -} diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 2a4f2f999bc..90ef6fedd58 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -273,6 +273,9 @@ static void GPENCIL_engine_free(void) GPU_BATCH_DISCARD_SAFE(e_data.batch_buffer_fill); MEM_SAFE_FREE(e_data.batch_buffer_fill); + GPU_BATCH_DISCARD_SAFE(e_data.batch_grid); + MEM_SAFE_FREE(e_data.batch_grid); + /* effects */ GPENCIL_delete_fx_shaders(&e_data); } @@ -333,9 +336,16 @@ void GPENCIL_cache_init(void *vedata) DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND); /* detect if playing animation */ - stl->storage->is_playing = false; if (draw_ctx->evil_C) { - stl->storage->is_playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL; + bool playing = ED_screen_animation_playing(CTX_wm_manager(draw_ctx->evil_C)) != NULL; + if (playing != stl->storage->is_playing) { + stl->storage->reset_cache = true; + } + stl->storage->is_playing = playing; + } + else { + stl->storage->is_playing = false; + stl->storage->reset_cache = false; } /* save render state */ stl->storage->is_render = DRW_state_is_image_render(); @@ -477,6 +487,56 @@ void GPENCIL_cache_init(void *vedata) } } +static void gpencil_add_draw_data(void *vedata, Object *ob) +{ + GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + Scene *scene = draw_ctx->scene; + bGPdata *gpd = (bGPdata *)ob->data; + bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); + + int i = stl->g_data->gp_cache_used - 1; + tGPencilObjectCache *cache_ob = &stl->g_data->gp_object_cache[i]; + + if (cache_ob->is_dup_ob == false) { + /* save init shading group */ + cache_ob->init_grp = stl->storage->shgroup_id; + + /* fill shading groups */ + if (!is_multiedit) { + DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, cache_ob); + } + else { + DRW_gpencil_populate_multiedit(&e_data, vedata, scene, ob, cache_ob); + } + + /* save end shading group */ + cache_ob->end_grp = stl->storage->shgroup_id - 1; + } + else { + /* save init shading group */ + cache_ob->init_grp = stl->storage->shgroup_id; + + DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, + cache_ob); + + /* save end shading group */ + cache_ob->end_grp = stl->storage->shgroup_id - 1; + } + + /* FX passses */ + cache_ob->has_fx = false; + if ((!stl->storage->simplify_fx) && + (BKE_shaderfx_has_gpencil(ob))) + { + cache_ob->has_fx = true; + if ((!stl->storage->simplify_fx) && (!is_multiedit)) { + DRW_gpencil_fx_prepare(&e_data, vedata, cache_ob); + } + } + +} + void GPENCIL_cache_populate(void *vedata, Object *ob) { /* object must be visible */ @@ -489,31 +549,40 @@ void GPENCIL_cache_populate(void *vedata, Object *ob) Scene *scene = draw_ctx->scene; ToolSettings *ts = scene->toolsettings; View3D *v3d = draw_ctx->v3d; + tGPencilObjectCache *cache_ob = NULL; /* object datablock (this is not draw now) */ if (ob->type == OB_GPENCIL && ob->data) { bGPdata *gpd = (bGPdata *)ob->data; - if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) { - /* if render set as dirty */ - if (stl->storage->is_render == true) { - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - } + /* when start/stop animation the cache must be set as dirty to reset all data */ + if (stl->storage->reset_cache) { + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + stl->storage->reset_cache = false; + } - /* allocate memory for saving gp objects for drawing later */ + /* is edit mode only current object, not instances */ + if ((draw_ctx->obact != ob) && GPENCIL_ANY_EDIT_MODE(gpd)) { + return; + } + + if ((stl->g_data->session_flag & GP_DRW_PAINT_READY) == 0) { + + /* save gp objects for drawing later */ stl->g_data->gp_object_cache = gpencil_object_cache_add( - stl->g_data->gp_object_cache, ob, false, - &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used); - - /* generate instances as separate cache objects for instance modifiers - * with the "Make as Objects" option enabled - */ - if (!stl->storage->simplify_modif) { - gpencil_instance_modifiers(stl, ob); - } + stl->g_data->gp_object_cache, ob, + &stl->g_data->gp_cache_size, &stl->g_data->gp_cache_used); + + cache_ob = &stl->g_data->gp_object_cache[stl->g_data->gp_cache_used - 1]; + + /* load drawing data */ + gpencil_add_draw_data(vedata, ob); } + /* draw current painting strokes */ - DRW_gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob); + if (draw_ctx->obact == ob) { + DRW_gpencil_populate_buffer_strokes(&e_data, vedata, ts, ob); + } /* grid */ if ((v3d) && @@ -521,57 +590,21 @@ void GPENCIL_cache_populate(void *vedata, Object *ob) (v3d->gp_flag & V3D_GP_SHOW_GRID) && (ob->type == OB_GPENCIL) && (ob == draw_ctx->obact)) { - stl->g_data->batch_grid = DRW_gpencil_get_grid(); + GPU_BATCH_DISCARD_SAFE(e_data.batch_grid); + MEM_SAFE_FREE(e_data.batch_grid); + + e_data.batch_grid = DRW_gpencil_get_grid(); DRW_shgroup_call_add(stl->g_data->shgrps_grid, - stl->g_data->batch_grid, - ob->obmat); + e_data.batch_grid, + ob->obmat); } } } -void GPENCIL_cache_finish(void *vedata) +void GPENCIL_cache_finish(void *UNUSED(vedata)) { - GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - const DRWContextState *draw_ctx = DRW_context_state_get(); - Scene *scene = draw_ctx->scene; - bool is_multiedit = false; - - /* if painting session, don't need to do more */ - if (stl->g_data->session_flag & GP_DRW_PAINT_PAINTING) { - return; - } - - /* Draw all pending objects */ - if (stl->g_data->gp_cache_used > 0) { - for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - Object *ob = stl->g_data->gp_object_cache[i].ob; - bGPdata *gpd = ob->data; - - /* save init shading group */ - stl->g_data->gp_object_cache[i].init_grp = stl->storage->shgroup_id; + return; - /* fill shading groups */ - is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd); - if (!is_multiedit) { - DRW_gpencil_populate_datablock(&e_data, vedata, scene, ob, gpd); - } - else { - DRW_gpencil_populate_multiedit(&e_data, vedata, scene, ob, gpd); - } - - /* save end shading group */ - stl->g_data->gp_object_cache[i].end_grp = stl->storage->shgroup_id - 1; - /* if render set to dirty to refresh viewport */ - if (stl->storage->is_render == true) { - gpd->flag |= GP_DATA_CACHE_IS_DIRTY; - } - /* FX passses */ - tGPencilObjectCache *cache = &stl->g_data->gp_object_cache[i]; - if ((!stl->storage->simplify_fx) && (!is_multiedit)) { - DRW_gpencil_fx_prepare(&e_data, vedata, cache); - } - } - } } /* helper function to sort inverse gpencil objects using qsort */ @@ -605,21 +638,8 @@ static void gpencil_prepare_fast_drawing( } } -static void gpencil_free_obj_list(GPENCIL_StorageList *stl) +static void gpencil_free_obj_runtime(GPENCIL_StorageList *stl) { - /* Clear temp objects created for display instances only. These objects are created - * while the draw manager draw the scene, but only to hold the strokes data. - * see: gp_instance_modifier_make_instances() - * - * the normal objects are not freed because they are not tagged as temp objects - */ - for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - Object *ob = stl->g_data->gp_object_cache[i].ob; - if (stl->g_data->gp_object_cache[i].temp_ob) { - MEM_SAFE_FREE(ob); - } - } - /* free the cache itself */ MEM_SAFE_FREE(stl->g_data->gp_object_cache); } @@ -636,7 +656,7 @@ void GPENCIL_draw_scene(void *ved) GPENCIL_TextureList *txl = ((GPENCIL_Data *)vedata)->txl; int init_grp, end_grp; - tGPencilObjectCache *cache; + tGPencilObjectCache *cache_ob; const float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; const DRWContextState *draw_ctx = DRW_context_state_get(); @@ -667,7 +687,7 @@ void GPENCIL_draw_scene(void *ved) MULTISAMPLE_GP_SYNC_DISABLE(stl->storage->multisamples, fbl, dfbl->default_fb, txl); /* free memory */ - gpencil_free_obj_list(stl); + gpencil_free_obj_runtime(stl); /* grid pass */ if ((!is_render) && (obact) && (obact->type == OB_GPENCIL)) { @@ -699,11 +719,11 @@ void GPENCIL_draw_scene(void *ved) sizeof(tGPencilObjectCache), gpencil_object_cache_compare_zdepth); for (int i = 0; i < stl->g_data->gp_cache_used; i++) { - cache = &stl->g_data->gp_object_cache[i]; - Object *ob = cache->ob; - bGPdata *gpd = ob->data; - init_grp = cache->init_grp; - end_grp = cache->end_grp; + cache_ob = &stl->g_data->gp_object_cache[i]; + bGPdata *gpd = cache_ob->gpd; + init_grp = cache_ob->init_grp; + end_grp = cache_ob->end_grp; + /* Render stroke in separated framebuffer */ GPU_framebuffer_bind(fbl->temp_fb_a); GPU_framebuffer_clear_color_depth(fbl->temp_fb_a, clearcol, 1.0f); @@ -724,15 +744,15 @@ void GPENCIL_draw_scene(void *ved) } /* Current buffer drawing */ - if ((!is_render) && (gpd->runtime.sbuffer_size > 0)) { + if ((!is_render) && (cache_ob->is_dup_ob == false)) + { DRW_draw_pass(psl->drawing_pass); } /* fx passes */ - if ((!stl->storage->simplify_fx) && - (BKE_shaderfx_has_gpencil(ob))) + if (cache_ob->has_fx == true) { stl->storage->tonemapping = 0; - DRW_gpencil_fx_draw(&e_data, vedata, cache); + DRW_gpencil_fx_draw(&e_data, vedata, cache_ob); } e_data.input_depth_tx = e_data.temp_depth_tx_a; @@ -754,6 +774,10 @@ void GPENCIL_draw_scene(void *ved) if (!is_render) { gpencil_prepare_fast_drawing(stl, dfbl, fbl, psl->mix_pass_noblend, clearcol); } + else { + /* if render, the cache must be dirty for next loop */ + gpd->flag |= GP_DATA_CACHE_IS_DIRTY; + } } /* edit points */ if ((!is_render) && (!playing)) { @@ -770,7 +794,7 @@ void GPENCIL_draw_scene(void *ved) } } /* free memory */ - gpencil_free_obj_list(stl); + gpencil_free_obj_runtime(stl); /* detach temp textures */ if (DRW_state_is_fbo()) { diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h index 21ac6045792..40522f10b48 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.h +++ b/source/blender/draw/engines/gpencil/gpencil_engine.h @@ -38,9 +38,6 @@ struct MaterialGPencilStyle; struct RenderEngine; struct RenderLayer; - /* TODO: these could be system parameter in userprefs screen */ -#define GPENCIL_MAX_GP_OBJ 256 - #define GPENCIL_CACHE_BLOCK_SIZE 8 #define GPENCIL_MAX_SHGROUPS 65536 #define GPENCIL_MIN_BATCH_SLOTS_CHUNK 16 @@ -59,13 +56,17 @@ struct RenderLayer; /* *********** OBJECTS CACHE *********** */ - /* used to save gpencil objects */ + /* used to save gpencil object data for drawing */ typedef struct tGPencilObjectCache { - struct Object *ob; + struct bGPdata *gpd; + char ob_name[64]; int init_grp, end_grp; int idx; /*original index, can change after sort */ /* effects */ + bool has_fx; + ListBase shader_fx; + float pixfactor; DRWShadingGroup *fx_wave_sh; DRWShadingGroup *fx_blur_sh; DRWShadingGroup *fx_colorize_sh; @@ -75,8 +76,11 @@ typedef struct tGPencilObjectCache { DRWShadingGroup *fx_flip_sh; DRWShadingGroup *fx_light_sh; + float loc[3]; + float obmat[4][4]; float zdepth; /* z-depth value to sort gp object */ - bool temp_ob; /* flag to tag temporary objects that must be removed after drawing loop */ + bool is_dup_ob; /* flag to tag duplicate objects */ + bool is_dup_onion; /* other object display onion already */ } tGPencilObjectCache; /* *********** LISTS *********** */ @@ -108,6 +112,7 @@ typedef struct GPENCIL_Storage { bool is_playing; bool is_render; bool is_mat_preview; + bool reset_cache; bool buffer_stroke; bool buffer_fill; const float *pixsize; @@ -191,9 +196,6 @@ typedef struct g_data { struct DRWShadingGroup *shgrps_drawing_fill; struct DRWShadingGroup *shgrps_grid; - /* grid geometry */ - GPUBatch *batch_grid; - int gp_cache_used; /* total objects in cache */ int gp_cache_size; /* size of the cache */ struct tGPencilObjectCache *gp_object_cache; @@ -259,6 +261,9 @@ typedef struct GPENCIL_e_data { GPUBatch *batch_buffer_stroke; GPUBatch *batch_buffer_fill; + /* grid geometry */ + GPUBatch *batch_grid; + } GPENCIL_e_data; /* Engine data */ /* GPUBatch Cache */ @@ -286,35 +291,36 @@ typedef struct GpencilBatchCache { struct DRWShadingGroup *DRW_gpencil_shgroup_stroke_create( struct GPENCIL_e_data *e_data, struct GPENCIL_Data *vedata, struct DRWPass *pass, struct GPUShader *shader, struct Object *ob, struct bGPdata *gpd, struct MaterialGPencilStyle *gp_style, int id, bool onion); -void DRW_gpencil_populate_datablock(struct GPENCIL_e_data *e_data, void *vedata, struct Scene *scene, struct Object *ob, struct bGPdata *gpd); +void DRW_gpencil_populate_datablock(struct GPENCIL_e_data *e_data, void *vedata, + struct Scene *scene, + struct Object *ob, struct tGPencilObjectCache *cache_ob); void DRW_gpencil_populate_buffer_strokes(struct GPENCIL_e_data *e_data, void *vedata, struct ToolSettings *ts, struct Object *ob); -void DRW_gpencil_populate_multiedit(struct GPENCIL_e_data *e_data, void *vedata, struct Scene *scene, struct Object *ob, struct bGPdata *gpd); +void DRW_gpencil_populate_multiedit(struct GPENCIL_e_data *e_data, void *vedata, + struct Scene *scene, struct Object *ob, struct tGPencilObjectCache *cache_ob); void DRW_gpencil_triangulate_stroke_fill(struct bGPDstroke *gps); void DRW_gpencil_multisample_ensure(struct GPENCIL_Data *vedata, int rect_w, int rect_h); /* create geometry functions */ struct GPUBatch *DRW_gpencil_get_point_geom(struct bGPDstroke *gps, short thickness, const float ink[4]); -struct GPUBatch *DRW_gpencil_get_stroke_geom(struct bGPDframe *gpf, struct bGPDstroke *gps, short thickness, const float ink[4]); +struct GPUBatch *DRW_gpencil_get_stroke_geom(struct bGPDstroke *gps, short thickness, const float ink[4]); struct GPUBatch *DRW_gpencil_get_fill_geom(struct Object *ob, struct bGPDstroke *gps, const float color[4]); struct GPUBatch *DRW_gpencil_get_edit_geom(struct bGPDstroke *gps, float alpha, short dflag); struct GPUBatch *DRW_gpencil_get_edlin_geom(struct bGPDstroke *gps, float alpha, short dflag); -struct GPUBatch *DRW_gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, float matrix[4][4], short thickness); +struct GPUBatch *DRW_gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, short thickness); struct GPUBatch *DRW_gpencil_get_buffer_fill_geom(struct bGPdata *gpd); -struct GPUBatch *DRW_gpencil_get_buffer_point_geom(struct bGPdata *gpd, float matrix[4][4], short thickness); +struct GPUBatch *DRW_gpencil_get_buffer_point_geom(struct bGPdata *gpd, short thickness); struct GPUBatch *DRW_gpencil_get_grid(void); /* object cache functions */ struct tGPencilObjectCache *gpencil_object_cache_add( struct tGPencilObjectCache *cache_array, struct Object *ob, - bool is_temp, int *gp_cache_size, int *gp_cache_used); + int *gp_cache_size, int *gp_cache_used); /* geometry batch cache functions */ void gpencil_batch_cache_check_free_slots(struct Object *ob); struct GpencilBatchCache *gpencil_batch_cache_get(struct Object *ob, int cfra); - -/* modifier functions */ -void gpencil_instance_modifiers(struct GPENCIL_StorageList *stl, struct Object *ob); +struct GpencilBatchCache *gpencil_batch_get_element(struct Object *ob); /* effects */ void GPENCIL_create_fx_shaders(struct GPENCIL_e_data *e_data); diff --git a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c index 827f2e9344b..c3bf241baf5 100644 --- a/source/blender/draw/engines/gpencil/gpencil_shader_fx.c +++ b/source/blender/draw/engines/gpencil/gpencil_shader_fx.c @@ -52,13 +52,12 @@ extern char datatoc_gpencil_fx_swirl_frag_glsl[]; extern char datatoc_gpencil_fx_wave_frag_glsl[]; /* verify if this fx is active */ -static bool effect_is_active(Object *ob, ShaderFxData *fx, bool is_render) +static bool effect_is_active(bGPdata *gpd, ShaderFxData *fx, bool is_render) { if (fx == NULL) { return false; } - bGPdata *gpd = ob->data; if (gpd == NULL) { return false; } @@ -161,9 +160,6 @@ static void DRW_gpencil_fx_blur( RegionView3D *rv3d = draw_ctx->rv3d; DRWShadingGroup *fx_shgrp; - Object *ob = cache->ob; - bGPdata *gpd = (bGPdata *)ob->data; - fxd->blur[0] = fxd->radius[0]; fxd->blur[1] = fxd->radius[1]; @@ -219,10 +215,10 @@ static void DRW_gpencil_fx_blur( DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_a); DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &cache->loc[0], 1); DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1); fxd->runtime.fx_sh = fx_shgrp; } @@ -291,7 +287,6 @@ static void DRW_gpencil_fx_light( if (fx == NULL) { return; } - Object *ob = cache->ob; LightShaderFxData *fxd = (LightShaderFxData *)fx; if (fxd->object == NULL) { @@ -317,11 +312,11 @@ static void DRW_gpencil_fx_light( */ float r_point[3], r_normal[3]; float r_plane[4]; - bGPdata *gpd = (bGPdata *)ob->data; + bGPdata *gpd = cache->gpd; if (!get_normal_vector(gpd, r_point, r_normal)) { return; } - mul_mat3_m4_v3(ob->obmat, r_normal); /* only rotation component */ + mul_mat3_m4_v3(cache->obmat, r_normal); /* only rotation component */ plane_from_point_normal_v3(r_plane, r_point, r_normal); float dt = dist_to_plane_v3(fxd->object->loc, r_plane); fxd->loc[3] = dt; /* use last element to save it */ @@ -333,7 +328,7 @@ static void DRW_gpencil_fx_light( DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1); fxd->runtime.fx_sh = fx_shgrp; } @@ -346,13 +341,12 @@ static void DRW_gpencil_fx_pixel( if (fx == NULL) { return; } - Object *ob = cache->ob; PixelShaderFxData *fxd = (PixelShaderFxData *)fx; GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; DRWShadingGroup *fx_shgrp; - bGPdata *gpd = (bGPdata *)ob->data; + bGPdata *gpd = cache->gpd; fxd->size[2] = (int)fxd->flag & FX_PIXEL_USE_LINES; @@ -364,7 +358,7 @@ static void DRW_gpencil_fx_pixel( DRW_shgroup_uniform_int(fx_shgrp, "size", &fxd->size[0], 3); DRW_shgroup_uniform_vec4(fx_shgrp, "color", &fxd->rgba[0], 1); - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &cache->loc[0], 1); DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1); DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); @@ -380,13 +374,11 @@ static void DRW_gpencil_fx_rim( if (fx == NULL) { return; } - Object *ob = cache->ob; RimShaderFxData *fxd = (RimShaderFxData *)fx; GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; DRWShadingGroup *fx_shgrp; - bGPdata *gpd = (bGPdata *)ob->data; struct GPUBatch *fxquad = DRW_cache_fullscreen_quad_get(); /* prepare pass */ @@ -402,10 +394,10 @@ static void DRW_gpencil_fx_rim( DRW_shgroup_uniform_vec3(fx_shgrp, "rim_color", &fxd->rim_rgb[0], 1); DRW_shgroup_uniform_vec3(fx_shgrp, "mask_color", &fxd->mask_rgb[0], 1); - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &cache->loc[0], 1); DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1); fxd->runtime.fx_sh = fx_shgrp; @@ -418,10 +410,10 @@ static void DRW_gpencil_fx_rim( DRW_shgroup_uniform_texture_ref(fx_shgrp, "strokeDepth", &e_data->temp_depth_tx_rim); DRW_shgroup_uniform_int(fx_shgrp, "blur", &fxd->blur[0], 2); - DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &ob->loc[0], 1); + DRW_shgroup_uniform_vec3(fx_shgrp, "loc", &cache->loc[0], 1); DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1); fxd->runtime.fx_sh_b = fx_shgrp; @@ -447,7 +439,6 @@ static void DRW_gpencil_fx_swirl( if (fx == NULL) { return; } - Object *ob = cache->ob; SwirlShaderFxData *fxd = (SwirlShaderFxData *)fx; if (fxd->object == NULL) { return; @@ -456,7 +447,6 @@ static void DRW_gpencil_fx_swirl( GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; DRWShadingGroup *fx_shgrp; - bGPdata *gpd = (bGPdata *)ob->data; fxd->transparent = (int)fxd->flag & FX_SWIRL_MAKE_TRANSPARENT; @@ -476,7 +466,7 @@ static void DRW_gpencil_fx_swirl( DRW_shgroup_uniform_float(fx_shgrp, "pixsize", stl->storage->pixsize, 1); DRW_shgroup_uniform_float(fx_shgrp, "pixelsize", &U.pixelsize, 1); - DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &gpd->pixfactor, 1); + DRW_shgroup_uniform_float(fx_shgrp, "pixfactor", &cache->pixfactor, 1); fxd->runtime.fx_sh = fx_shgrp; } @@ -584,15 +574,14 @@ void DRW_gpencil_fx_prepare( struct tGPencilObjectCache *cache) { GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; - Object *ob = cache->ob; int ob_idx = cache->idx; - if (ob->shader_fx.first == NULL) { + if (cache->shader_fx.first == NULL) { return; } /* loop FX */ - for (ShaderFxData *fx = ob->shader_fx.first; fx; fx = fx->next) { - if (effect_is_active(ob, fx, stl->storage->is_render)) { + for (ShaderFxData *fx = cache->shader_fx.first; fx; fx = fx->next) { + if (effect_is_active(cache->gpd, fx, stl->storage->is_render)) { switch (fx->type) { case eShaderFxType_Blur: DRW_gpencil_fx_blur(fx, ob_idx, e_data, vedata, cache); @@ -790,12 +779,12 @@ void DRW_gpencil_fx_draw( GPENCIL_StorageList *stl = ((GPENCIL_Data *)vedata)->stl; GPENCIL_PassList *psl = ((GPENCIL_Data *)vedata)->psl; GPENCIL_FramebufferList *fbl = ((GPENCIL_Data *)vedata)->fbl; - Object *ob = cache->ob; /* loop FX modifiers */ - for (ShaderFxData *fx = ob->shader_fx.first; fx; fx = fx->next) { - if (effect_is_active(ob, fx, stl->storage->is_render)) { + for (ShaderFxData *fx = cache->shader_fx.first; fx; fx = fx->next) { + if (effect_is_active(cache->gpd, fx, stl->storage->is_render)) { switch (fx->type) { + case eShaderFxType_Blur: { BlurShaderFxData *fxd = (BlurShaderFxData *)fx; diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index f322e544307..7e9390e893a 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1365,6 +1365,12 @@ static int object_delete_exec(bContext *C, wmOperator *op) continue; } + /* if grease pencil object, set cache as dirty */ + if (ob->type == OB_GPENCIL) { + bGPdata *gpd = (bGPdata *)ob->data; + DEG_id_tag_update(&gpd->id, OB_RECALC_OB | OB_RECALC_DATA); + } + /* This is sort of a quick hack to address T51243 - Proper thing to do here would be to nuke most of all this * custom scene/object/base handling, and use generic lib remap/query for that. * But this is for later (aka 2.8, once layers & co are settled and working). diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c index a35174d882f..10f96d3a22f 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c @@ -77,7 +77,6 @@ static void initData(GpencilModifierData *md) gpmd->rnd_rot = 0.5f; gpmd->rnd_size = 0.5f; gpmd->lock_axis |= GP_LOCKAXIS_X; - gpmd->flag |= GP_INSTANCE_MAKE_OBJECTS; /* fill random values */ BLI_array_frand(gpmd->rnd, 20, 1); @@ -197,11 +196,10 @@ static void generate_geometry( MEM_SAFE_FREE(valid_strokes); } -/* bakeModifier - "Bake to Data" Mode */ -static void bakeModifierGP_strokes( - Depsgraph *depsgraph, - GpencilModifierData *md, Object *ob) +static void bakeModifier(Main *UNUSED(bmain), Depsgraph *depsgraph, + GpencilModifierData *md, Object *ob) { + bGPdata *gpd = ob->data; for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { @@ -213,127 +211,12 @@ static void bakeModifierGP_strokes( /* -------------------------------- */ -/* helper to create a new object */ -static Object *array_instance_add_ob_copy(Main *bmain, Scene *scene, Object *from_ob) -{ - Object *ob; - - ob = BKE_object_copy(bmain, from_ob); - BKE_collection_object_add_from(bmain, scene, from_ob, ob); - - zero_v3(ob->loc); - zero_v3(ob->rot); - - DEG_id_type_tag(bmain, ID_OB); - DEG_relations_tag_update(bmain); - DEG_id_tag_update(&scene->id, 0); - - return ob; -} - -/* bakeModifier - "Make Objects" Mode */ -static void bakeModifierGP_objects(Main *bmain, Depsgraph *depsgraph, GpencilModifierData *md, Object *ob) -{ - InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; - Scene *scene = DEG_get_evaluated_scene(depsgraph); - /* reset random */ - mmd->rnd[0] = 1; - - /* generate instances as objects */ - for (int x = 0; x < mmd->count[0]; x++) { - for (int y = 0; y < mmd->count[1]; y++) { - for (int z = 0; z < mmd->count[2]; z++) { - Object *newob; - GpencilModifierData *fmd; - - const int elem_idx[3] = {x, y, z}; - float mat[4][4], finalmat[4][4]; - int sh; - - /* original strokes are at index = 0,0,0 */ - if ((x == 0) && (y == 0) && (z == 0)) { - continue; - } - - /* compute transform for instance */ - BKE_gpencil_instance_modifier_instance_tfm(mmd, elem_idx, mat); - mul_m4_m4m4(finalmat, ob->obmat, mat); - - /* moves to new origin */ - sh = x; - if (mmd->lock_axis == GP_LOCKAXIS_Y) { - sh = y; - } - if (mmd->lock_axis == GP_LOCKAXIS_Z) { - sh = z; - } - madd_v3_v3fl(finalmat[3], mmd->shift, sh); - - /* Create a new object - * - * NOTE: Copies share the same original GP datablock - * Artists can later user make_single_user on these - * to make them unique (if necessary), without too - * much extra memory usage. - */ - newob = array_instance_add_ob_copy(bmain, scene, ob); - - /* remove array on destination object */ - fmd = (GpencilModifierData *)BLI_findstring(&newob->greasepencil_modifiers, md->name, offsetof(GpencilModifierData, name)); - if (fmd) { - BLI_remlink(&newob->greasepencil_modifiers, fmd); - BKE_gpencil_modifier_free(fmd); - } - - /* copy transforms to destination object */ - copy_m4_m4(newob->obmat, finalmat); - - copy_v3_v3(newob->loc, finalmat[3]); - mat4_to_eul(newob->rot, finalmat); - mat4_to_size(newob->size, finalmat); - } - } - } -} - -/* -------------------------------- */ - /* Generic "generateStrokes" callback */ static void generateStrokes( GpencilModifierData *md, Depsgraph *depsgraph, Object *ob, bGPDlayer *gpl, bGPDframe *gpf) { - InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; - - /* When the "make_objects" flag is set, this modifier is handled as part of the - * draw engine instead. The main benefit is that the instances won't suffer from - * z-ordering problems. - * - * FIXME: Ultimately, the draw-engine hack here shouldn't be necessary, but until - * we find a better fix to the z-ordering problems, it's better to have - * working functionality - */ - if ((mmd->flag & GP_INSTANCE_MAKE_OBJECTS) == 0) { - generate_geometry(md, depsgraph, ob, gpl, gpf); - } -} - -/* Generic "bakeModifier" callback */ -static void bakeModifier( - Main *bmain, Depsgraph *depsgraph, - GpencilModifierData *md, Object *ob) -{ - InstanceGpencilModifierData *mmd = (InstanceGpencilModifierData *)md; - - /* Create new objects or add all to current datablock. - * Sometimes it's useful to have the option to do either of these... - */ - if (mmd->flag & GP_INSTANCE_MAKE_OBJECTS) { - bakeModifierGP_objects(bmain, depsgraph, md, ob); - } - else { - bakeModifierGP_strokes(depsgraph, md, ob); - } + generate_geometry(md, depsgraph, ob, gpl, gpf); } GpencilModifierTypeInfo modifierType_Gpencil_Instance = { @@ -347,7 +230,7 @@ GpencilModifierTypeInfo modifierType_Gpencil_Instance = { /* deformStroke */ NULL, /* generateStrokes */ generateStrokes, - /* bakeModifier */ bakeModifier, + /* bakeModifier */ bakeModifier, /* initData */ initData, /* freeData */ NULL, diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index ae3621576f2..0cc7e9e40da 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -217,7 +217,6 @@ typedef enum eInstanceGpencil_Flag { GP_INSTANCE_RANDOM_ROT = (1 << 1), GP_INSTANCE_INVERT_LAYER = (1 << 2), GP_INSTANCE_INVERT_PASS = (1 << 3), - GP_INSTANCE_MAKE_OBJECTS = (1 << 4), } eInstanceGpencil_Flag; typedef struct BuildGpencilModifierData { diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 8febfbc8ffc..204b6e8741f 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -236,7 +236,7 @@ typedef enum eGPDframe_Flag { typedef struct bGPDlayer_runtime { struct GHash *derived_data; /* runtime data created by modifiers */ int icon_id; /* id for dynamic icon used to show annotation color preview for layer */ - char pad[4]; + int batch_index; /* batch used for dupli instances */ } bGPDlayer_runtime; /* Grease-Pencil Annotations - 'Layer' */ diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index d4252601c6a..c4d1e93a2ef 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -928,11 +928,6 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "use_make_objects", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_INSTANCE_MAKE_OBJECTS); - RNA_def_property_ui_text(prop, "Make Objects", - "When applying this modifier, instances get created as separate objects"); - RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); } static void rna_def_modifier_gpencilbuild(BlenderRNA *brna) |