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:
authorAntonioya <blendergit@gmail.com>2018-08-15 17:07:16 +0300
committerAntonioya <blendergit@gmail.com>2018-08-15 21:27:59 +0300
commit8e8d93eb86109988db44730a0107e9da9e870328 (patch)
tree7a4e317f52de4e07d3261817e55a5444be1379f2
parentbb84f7ff5f5268226b4d14e0f1e44a2579354b37 (diff)
GP: Redesign logic of drawing engine for object instance support
The initial design assumed that there was only one object for each unique name, but that was not the case when instances were created. Now, instances are supported and speed has been greatly improved when repetitions are used. As a result of this change, the option to create objects has been removed in the Instances modifier. This option was strange and was also against Blender's design rules, since a modifier should never create objects. The old functionality of the modifier can be achieved with instances. Also, several memory leakage problems that were not previously detected have been eliminated, and especially in the grid and in the drawing process Onion Skin is not supported in multi-user datablocks. Support this, makes incompatible with instances. We need find a solution in the long term, but now it's better keep disabled and make instances work. Anyway, the new instances makes unnecessary to use muli-user datablocks.
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py1
-rw-r--r--source/blender/blenkernel/intern/library.c8
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c65
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c34
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c184
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c200
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h42
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_shader_fx.c49
-rw-r--r--source/blender/editors/object/object_add.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilinstance.c127
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h1
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h2
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c5
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)