Merge branch 'master' into greasepencil-object
authorAntonioya <blendergit@gmail.com>
Thu, 9 May 2019 11:28:24 +0000 (13:28 +0200)
committerAntonioya <blendergit@gmail.com>
Thu, 9 May 2019 11:28:24 +0000 (13:28 +0200)
12 files changed:
source/blender/blenkernel/BKE_gpencil.h
source/blender/blenkernel/BKE_gpencil_modifier.h
source/blender/blenkernel/intern/gpencil_modifier.c
source/blender/blenkernel/intern/object_update.c
source/blender/draw/engines/gpencil/gpencil_cache_utils.c
source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
source/blender/draw/engines/gpencil/gpencil_draw_utils.c
source/blender/draw/engines/gpencil/gpencil_engine.h
source/blender/editors/gpencil/gpencil_intern.h
source/blender/editors/gpencil/gpencil_select.c
source/blender/makesdna/DNA_gpencil_types.h
source/blender/makesdna/DNA_object_types.h

index 2e5d591123904a2ef1e40ea3ad7c126feec77c22..3c84c991019a1d16e9f9058e5b18102c09a33cb4 100644 (file)
@@ -49,6 +49,82 @@ struct bGPdata;
 struct MDeformVert;
 struct MDeformWeight;
 
+struct GPUBatch;
+struct GPUVertBuf;
+struct GPUVertFormat;
+struct GpencilBatchGroup;
+
+#define GP_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
+#define GP_SIMPLIFY_ONPLAY(playing) \
+  (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \
+   ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0))
+#define GP_SIMPLIFY_FILL(scene, playing) \
+  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
+    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
+#define GP_SIMPLIFY_MODIF(scene, playing) \
+  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
+    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
+#define GP_SIMPLIFY_FX(scene, playing) \
+  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
+    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
+#define GP_SIMPLIFY_BLEND(scene, playing) \
+  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
+    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
+
+/* GPUBatch Cache Element */
+typedef struct GpencilBatchCacheElem {
+  struct GPUBatch *batch;
+  struct GPUVertBuf *vbo;
+  int vbo_len;
+  /* attr ids */
+  struct GPUVertFormat *format;
+  uint pos_id;
+  uint color_id;
+  uint thickness_id;
+  uint uvdata_id;
+  uint prev_pos_id;
+
+  /* size for VBO alloc */
+  int tot_vertex;
+} GpencilBatchCacheElem;
+
+/* Defines each batch group to define later the shgroup */
+typedef struct GpencilBatchGroup {
+  struct bGPDlayer *gpl;  /* reference to original layer */
+  struct bGPDframe *gpf;  /* reference to original frame */
+  struct bGPDstroke *gps; /* reference to original stroke */
+  short type;             /* type of element */
+  bool onion;             /* the group is part of onion skin */
+  int vertex_idx;         /* index of vertex data */
+} GpencilBatchGroup;
+
+typedef enum GpencilBatchGroup_Type {
+  eGpencilBatchGroupType_Stroke = 1,
+  eGpencilBatchGroupType_Point = 2,
+  eGpencilBatchGroupType_Fill = 3,
+  eGpencilBatchGroupType_Edit = 4,
+  eGpencilBatchGroupType_Edlin = 5,
+} GpencilBatchGroup_Type;
+
+/* Runtime data for GPU and derived frames after applying modifiers */
+typedef struct GpencilBatchCache {
+  struct GpencilBatchCacheElem b_stroke;
+  struct GpencilBatchCacheElem b_point;
+  struct GpencilBatchCacheElem b_fill;
+  struct GpencilBatchCacheElem b_edit;
+  struct GpencilBatchCacheElem b_edlin;
+
+  /* settings to determine if cache is invalid */
+  bool is_dirty;
+  bool is_editmode;
+  int cache_frame;
+
+  /* data with the shading groups */
+  int grp_used;                        /* total groups in arrays */
+  int grp_size;                        /* max size of the array */
+  struct GpencilBatchGroup *grp_cache; /* array of elements */
+} GpencilBatchCache;
+
 /* ------------ Grease-Pencil API ------------------ */
 
 void BKE_gpencil_free_point_weights(struct MDeformVert *dvert);
index 4655abf6e0273ef80fbd3edd378cca030b34175f..63b1f2590493426907981c25a3473b50c22f32d2 100644 (file)
@@ -325,4 +325,8 @@ int BKE_gpencil_time_modifier(struct Depsgraph *depsgraph,
 void BKE_gpencil_lattice_init(struct Object *ob);
 void BKE_gpencil_lattice_clear(struct Object *ob);
 
+void BKE_gpencil_modifiers_calc(struct Depsgraph *depsgraph,
+                                struct Scene *scene,
+                                struct Object *ob);
+
 #endif /* __BKE_GPENCIL_MODIFIER_H__ */
index c8a45a9275803cba9aa654231e744fade0e82b1e..f0bcceb50b746fbe75e0e08301f91b8bc1136082 100644 (file)
@@ -781,6 +781,7 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
       pt_final->strength = pt->strength;
       pt_final->time = pt->time;
       pt_final->flag = pt->flag;
+      pt_final->runtime.pt_orig = pt->runtime.pt_orig;
 
       if (gps->dvert != NULL) {
         dvert = &temp_dverts[i];
@@ -803,6 +804,7 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
       pt_final->strength = interpf(pt->strength, next->strength, 0.5f);
       CLAMP(pt_final->strength, GPENCIL_STRENGTH_MIN, 1.0f);
       pt_final->time = interpf(pt->time, next->time, 0.5f);
+      pt_final->runtime.pt_orig = NULL;
 
       if (gps->dvert != NULL) {
         dvert = &temp_dverts[i];
@@ -848,3 +850,125 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
     }
   }
 }
+
+/* Copy frame but do not assign new memory */
+static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf)
+{
+  derived_gpf->prev = gpf->prev;
+  derived_gpf->next = gpf->next;
+  derived_gpf->framenum = gpf->framenum;
+  derived_gpf->flag = gpf->flag;
+  derived_gpf->key_type = gpf->key_type;
+  derived_gpf->runtime = gpf->runtime;
+  copy_m4_m4(derived_gpf->runtime.viewmatrix, gpf->runtime.viewmatrix);
+
+  /* copy strokes */
+  BLI_listbase_clear(&derived_gpf->strokes);
+  for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
+    /* make copy of source stroke */
+    bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
+
+    /* Save original pointers for using in edit and select operators. */
+    gps_dst->runtime.gps_orig = gps_src;
+    for (int i = 0; i < gps_src->totpoints; i++) {
+      bGPDspoint *pt_dst = &gps_dst->points[i];
+      pt_dst->runtime.pt_orig = &gps_src->points[i];
+    }
+
+    BLI_addtail(&derived_gpf->strokes, gps_dst);
+  }
+}
+
+/* Ensure there is a derived frame */
+static void gpencil_ensure_derived_frame(
+    int idx, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDframe **derived_gpf)
+{
+  /* create derived frames array data or expand */
+  bGPDframe *derived_frames = ob->runtime.derived_frames;
+  *derived_gpf = &derived_frames[idx];
+
+  /* if derived frame create a new one */
+  if (*derived_gpf != NULL) {
+    /* first clear temp data */
+    BKE_gpencil_free_frame_runtime_data(*derived_gpf);
+  }
+  /* copy data (do not assign new memory)*/
+  gpencil_copy_frame(gpf, *derived_gpf);
+}
+
+/* Calculate gpencil modifiers */
+void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
+{
+  /* use original data to set reference pointers to original data */
+  Object *ob_orig = DEG_get_original_object(ob);
+  bGPdata *gpd = (bGPdata *)ob_orig->data;
+  const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
+  const bool simplify_modif = GP_SIMPLIFY_MODIF(scene, false);
+  const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+  const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
+  int cfra_eval = (int)DEG_get_ctime(depsgraph);
+
+  /* Create array of derived frames equal to number of layers. */
+  ob->runtime.tot_layers = BLI_listbase_count(&gpd->layers);
+  CLAMP_MIN(ob->runtime.tot_layers, 1);
+  if (ob->runtime.derived_frames == NULL) {
+    ob->runtime.derived_frames = MEM_callocN(sizeof(struct bGPDframe) * ob->runtime.tot_layers,
+                                             __func__);
+  }
+  else {
+    ob->runtime.derived_frames = MEM_reallocN(ob->runtime.derived_frames,
+                                              sizeof(struct bGPDframe) * ob->runtime.tot_layers);
+  }
+
+  /* Init general modifiers data. */
+  if (ob->greasepencil_modifiers.first) {
+    BKE_gpencil_lattice_init(ob);
+  }
+
+  /* *****************************************************************
+   * Loop all layers, duplicate data and apply modifiers.
+   *
+   * ******************************************************************/
+  int idx = 0;
+  for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+    /* Remap frame (Time modifier) */
+    int remap_cfra = cfra_eval;
+    if ((time_remap) && (!simplify_modif)) {
+      remap_cfra = BKE_gpencil_time_modifier(depsgraph, scene, ob, gpl, cfra_eval, is_render);
+    }
+    bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
+
+    if (gpf == NULL) {
+      idx++;
+      continue;
+    }
+
+    /* Create a duplicate data set of stroke to modify. */
+    bGPDframe *derived_gpf = NULL;
+    gpencil_ensure_derived_frame(idx, ob, gpl, gpf, &derived_gpf);
+
+    /* Skip all if some disable flag is enabled. */
+    if ((ob->greasepencil_modifiers.first == NULL) || (is_multiedit) || (simplify_modif)) {
+      idx++;
+      continue;
+    }
+
+    /* Apply geometry modifiers (create new geometry). */
+    if (BKE_gpencil_has_geometry_modifiers(ob)) {
+      BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, is_render);
+    }
+
+    /* Loop all strokes and deform them. */
+    for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps->next) {
+      /* Apply modifiers that only deform geometry */
+      BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, derived_gpf, gps, is_render);
+    }
+
+    idx++;
+  }
+
+  /* Clear any lattice data. */
+  if (ob->greasepencil_modifiers.first) {
+    BKE_gpencil_lattice_clear(ob);
+  }
+}
index 183bc968897db691c4fec6f6daad786e90f9659d..0e6f3380f4df8052bba93e2e00aaf526df2fa07c 100644 (file)
@@ -42,6 +42,7 @@
 #include "BKE_displist.h"
 #include "BKE_editmesh.h"
 #include "BKE_effect.h"
+#include "BKE_gpencil_modifier.h"
 #include "BKE_image.h"
 #include "BKE_key.h"
 #include "BKE_layer.h"
@@ -209,6 +210,9 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
     case OB_LATTICE:
       BKE_lattice_modifiers_calc(depsgraph, scene, ob);
       break;
+    case OB_GPENCIL:
+      BKE_gpencil_modifiers_calc(depsgraph, scene, ob);
+      break;
   }
 
   /* particles */
index 67ffe62f3c66aee486404c118e8c14f9ab8a33d9..b0608343ab313f617f7216b67b9ad5ff5b2715b0 100644 (file)
@@ -274,11 +274,6 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
 
   cache->cache_frame = cfra;
 
-  /* create array of derived frames equal to number of layers */
-  cache->tot_layers = BLI_listbase_count(&gpd->layers);
-  CLAMP_MIN(cache->tot_layers, 1);
-  cache->derived_array = MEM_callocN(sizeof(struct bGPDframe) * cache->tot_layers, "Derived GPF");
-
   return cache;
 }
 
@@ -301,18 +296,16 @@ static void gpencil_batch_cache_clear(GpencilBatchCache *cache)
   MEM_SAFE_FREE(cache->b_edit.batch);
   MEM_SAFE_FREE(cache->b_edlin.batch);
 
+  /* internal format data */
+  MEM_SAFE_FREE(cache->b_stroke.format);
+  MEM_SAFE_FREE(cache->b_point.format);
+  MEM_SAFE_FREE(cache->b_fill.format);
+  MEM_SAFE_FREE(cache->b_edit.format);
+  MEM_SAFE_FREE(cache->b_edlin.format);
+
   MEM_SAFE_FREE(cache->grp_cache);
   cache->grp_size = 0;
   cache->grp_used = 0;
-
-  /* clear all frames derived data */
-  for (int i = 0; i < cache->tot_layers; i++) {
-    bGPDframe *derived_gpf = &cache->derived_array[i];
-    BKE_gpencil_free_frame_runtime_data(derived_gpf);
-    derived_gpf = NULL;
-  }
-  cache->tot_layers = 0;
-  MEM_SAFE_FREE(cache->derived_array);
 }
 
 /* get cache */
@@ -355,4 +348,14 @@ void DRW_gpencil_freecache(struct Object *ob)
       gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
     }
   }
+
+  /* clear all frames derived data */
+  for (int i = 0; i < ob->runtime.tot_layers; i++) {
+    bGPDframe *derived_gpf = &ob->runtime.derived_frames[i];
+    BKE_gpencil_free_frame_runtime_data(derived_gpf);
+    derived_gpf = NULL;
+  }
+
+  ob->runtime.tot_layers = 0;
+  MEM_SAFE_FREE(ob->runtime.derived_frames);
 }
index 7dabbcf4c41f1f9351120240a669dc89d24008a0..11cdcc792e4ccc2acfb5750017032d1ed14b1559 100644 (file)
@@ -129,6 +129,13 @@ static void gpencil_vbo_ensure_size(GpencilBatchCacheElem *be, int totvertex)
   }
 }
 
+static void gpencil_elem_format_ensure(GpencilBatchCacheElem *be)
+{
+  if (be->format == NULL) {
+    be->format = MEM_callocN(sizeof(GPUVertFormat), __func__);
+  }
+}
+
 /* create batch geometry data for points stroke shader */
 void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be,
                                 bGPDstroke *gps,
@@ -137,16 +144,17 @@ void DRW_gpencil_get_point_geom(GpencilBatchCacheElem *be,
 {
   int totvertex = gps->totpoints;
   if (be->vbo == NULL) {
-    be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-    be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+    gpencil_elem_format_ensure(be);
+    be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+    be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
     be->thickness_id = GPU_vertformat_attr_add(
-        &be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+        be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
     be->uvdata_id = GPU_vertformat_attr_add(
-        &be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+        be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
     be->prev_pos_id = GPU_vertformat_attr_add(
-        &be->format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+        be->format, "prev_pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 
-    be->vbo = GPU_vertbuf_create_with_format(&be->format);
+    be->vbo = GPU_vertbuf_create_with_format(be->format);
     GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
     be->vbo_len = 0;
   }
@@ -214,14 +222,15 @@ void DRW_gpencil_get_stroke_geom(struct GpencilBatchCacheElem *be,
   int totvertex = totpoints + cyclic_add + 2;
 
   if (be->vbo == NULL) {
-    be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-    be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+    gpencil_elem_format_ensure(be);
+    be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+    be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
     be->thickness_id = GPU_vertformat_attr_add(
-        &be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+        be->format, "thickness", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
     be->uvdata_id = GPU_vertformat_attr_add(
-        &be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+        be->format, "uvdata", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
 
-    be->vbo = GPU_vertbuf_create_with_format(&be->format);
+    be->vbo = GPU_vertbuf_create_with_format(be->format);
     GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
     be->vbo_len = 0;
   }
@@ -327,12 +336,13 @@ void DRW_gpencil_get_fill_geom(struct GpencilBatchCacheElem *be,
   int totvertex = gps->tot_triangles * 3;
 
   if (be->vbo == NULL) {
-    be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-    be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+    gpencil_elem_format_ensure(be);
+    be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+    be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
     be->uvdata_id = GPU_vertformat_attr_add(
-        &be->format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+        be->format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
 
-    be->vbo = GPU_vertbuf_create_with_format(&be->format);
+    be->vbo = GPU_vertbuf_create_with_format(be->format);
     GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
     be->vbo_len = 0;
   }
@@ -724,13 +734,17 @@ void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
   UI_GetThemeColor3fv(TH_GP_VERTEX, unselectColor);
   unselectColor[3] = alpha;
 
+  float linecolor[4];
+  copy_v4_v4(linecolor, gpd->line_color);
+
   if (be->vbo == NULL) {
-    be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-    be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+    gpencil_elem_format_ensure(be);
+    be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+    be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
     be->thickness_id = GPU_vertformat_attr_add(
-        &be->format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+        be->format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
 
-    be->vbo = GPU_vertbuf_create_with_format(&be->format);
+    be->vbo = GPU_vertbuf_create_with_format(be->format);
     GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
     be->vbo_len = 0;
   }
@@ -767,6 +781,12 @@ void DRW_gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
         ARRAY_SET_ITEMS(fcolor, 1.0f, 0.0f, 0.0f, 1.0f);
         fsize = vsize + 1;
       }
+      else if (pt->runtime.pt_orig == NULL) {
+        ARRAY_SET_ITEMS(fcolor, linecolor[0], linecolor[1], linecolor[2], selectColor[3]);
+        mul_v4_fl(fcolor, 0.9f);
+        copy_v4_v4(fcolor, fcolor);
+        fsize = vsize * 0.8f;
+      }
       else if (pt->flag & GP_SPOINT_SELECT) {
         copy_v4_v4(fcolor, selectColor);
         fsize = vsize;
@@ -810,10 +830,11 @@ void DRW_gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be,
   copy_v4_v4(linecolor, gpd->line_color);
 
   if (be->vbo == NULL) {
-    be->pos_id = GPU_vertformat_attr_add(&be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
-    be->color_id = GPU_vertformat_attr_add(&be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+    gpencil_elem_format_ensure(be);
+    be->pos_id = GPU_vertformat_attr_add(be->format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+    be->color_id = GPU_vertformat_attr_add(be->format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
 
-    be->vbo = GPU_vertbuf_create_with_format(&be->format);
+    be->vbo = GPU_vertbuf_create_with_format(be->format);
     GPU_vertbuf_data_alloc(be->vbo, be->tot_vertex);
     be->vbo_len = 0;
   }
index 4b6c913785d64c69bfc5b6d20aefa0925a045f29..b5008990b61219e5243160969ebdfbe9585d9f6b 100644 (file)
 #define TEXTURE 4
 #define PATTERN 5
 
-#define GP_SET_SRC_GPS(src_gps) \
-  if (src_gps) \
-  src_gps = src_gps->next
-
 /* Get number of vertex for using in GPU VBOs */
 static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
                                 tGPencilObjectCache *cache_ob,
@@ -88,16 +84,17 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
   const bool do_onion = (bool)((gpd->flag & GP_DATA_STROKE_WEIGHTMODE) == 0) && overlay &&
                         main_onion && DRW_gpencil_onion_active(gpd) && !playing;
 
-  const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
 
   cache_ob->tot_vertex = 0;
   cache_ob->tot_triangles = 0;
+  int derived_idx = 0;
 
   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
     bGPDframe *init_gpf = NULL;
     const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN));
     if (gpl->flag & GP_LAYER_HIDE) {
+      derived_idx++;
       continue;
     }
 
@@ -106,15 +103,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
       init_gpf = gpl->frames.first;
     }
     else {
-      /* verify time modifiers */
-      if ((time_remap) && (!stl->storage->simplify_modif)) {
-        int remap_cfra = BKE_gpencil_time_modifier(
-            draw_ctx->depsgraph, draw_ctx->scene, ob, gpl, cfra_eval, stl->storage->is_render);
-        init_gpf = BKE_gpencil_layer_getframe(gpl, remap_cfra, GP_GETFRAME_USE_PREV);
-      }
-      else {
-        init_gpf = gpl->actframe;
-      }
+      init_gpf = &ob->runtime.derived_frames[derived_idx];
     }
 
     if (init_gpf == NULL) {
@@ -130,6 +119,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
         break;
       }
     }
+    derived_idx++;
   }
 
   cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3;
@@ -1007,8 +997,7 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
                                  Object *ob,
                                  bGPdata *gpd,
                                  bGPDlayer *gpl,
-                                 bGPDframe *src_gpf,
-                                 bGPDframe *derived_gpf,
+                                 bGPDframe *gpf,
                                  const float opacity,
                                  const float tintcolor[4],
                                  const bool custonion,
@@ -1019,7 +1008,7 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
   const DRWContextState *draw_ctx = DRW_context_state_get();
   Scene *scene = draw_ctx->scene;
   View3D *v3d = draw_ctx->v3d;
-  bGPDstroke *gps, *src_gps;
+  bGPDstroke *gps;
   float viewmatrix[4][4];
   const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
   const bool playing = stl->storage->is_playing;
@@ -1035,42 +1024,23 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
 
   /* get parent matrix and save as static data */
   ED_gpencil_parent_location(depsgraph, ob, gpd, gpl, viewmatrix);
-  copy_m4_m4(derived_gpf->runtime.viewmatrix, viewmatrix);
+  copy_m4_m4(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) {
-      if (BKE_gpencil_has_geometry_modifiers(ob)) {
-        BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, stl->storage->is_render);
-      }
-    }
+    copy_m4_m4(gpf->runtime.viewmatrix, cache_ob->obmat);
   }
 
-  if (src_gpf) {
-    src_gps = src_gpf->strokes.first;
-  }
-  else {
-    src_gps = NULL;
-  }
-
-  for (gps = derived_gpf->strokes.first; gps; gps = gps->next) {
+  for (gps = gpf->strokes.first; gps; gps = gps->next) {
     MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
 
     /* check if stroke can be drawn */
     if (gpencil_can_draw_stroke(gp_style, gps, false, is_mat_preview) == false) {
-      GP_SET_SRC_GPS(src_gps);
       continue;
     }
 
     /* 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, gpl, gp_style, src_gps);
-    }
+    DRW_gpencil_recalc_geometry_caches(ob, gpl, gp_style, gps->runtime.gps_orig);
 
     /* if the fill has any value, it's considered a fill and is not drawn if simplify fill is
      * enabled */
@@ -1079,32 +1049,22 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
       if ((gp_style->fill_rgba[3] > GPENCIL_ALPHA_OPACITY_THRESH) ||
           (gp_style->fill_style > GP_STYLE_FILL_STYLE_SOLID) ||
           (gpl->blend_mode != eGplBlendMode_Normal)) {
-        GP_SET_SRC_GPS(src_gps);
         continue;
       }
     }
 
-    if ((gpl->actframe->framenum == derived_gpf->framenum) || (!is_multiedit) ||
-        (overlay_multiedit)) {
+    if ((gpl->actframe->framenum == gpf->framenum) || (!is_multiedit) || (overlay_multiedit)) {
       /* copy color to temp fields to apply temporal changes in the stroke */
       copy_v4_v4(gps->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
       copy_v4_v4(gps->runtime.tmp_fill_rgba, gp_style->fill_rgba);
 
-      /* apply modifiers (only modify geometry, but not create ) */
-      if ((cache->is_dirty) && (ob->greasepencil_modifiers.first) && (!is_multiedit)) {
-        if (!stl->storage->simplify_modif) {
-          BKE_gpencil_stroke_modifiers(
-              depsgraph, ob, gpl, derived_gpf, gps, stl->storage->is_render);
-        }
-      }
-
       /* hide any blend layer */
       if ((!stl->storage->simplify_blend) || (gpl->blend_mode == eGplBlendMode_Normal)) {
         /* fill */
         if ((gp_style->flag & GP_STYLE_FILL_SHOW) && (!stl->storage->simplify_fill) &&
             ((gps->flag & GP_STROKE_NOFILL) == 0)) {
           gpencil_add_fill_vertexdata(
-              cache, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion);
+              cache, ob, gpl, gpf, gps, opacity, tintcolor, false, custonion);
         }
         /* stroke */
         /* No fill strokes, must show stroke always */
@@ -1117,14 +1077,13 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
           }
 
           gpencil_add_stroke_vertexdata(
-              cache, ob, gpl, derived_gpf, gps, opacity, tintcolor, false, custonion);
+              cache, ob, gpl, gpf, gps, opacity, tintcolor, false, custonion);
         }
       }
     }
 
     /* edit points (only in edit mode and not play animation not render) */
-    if ((draw_ctx->obact == ob) && (src_gps) && (!playing) && (!is_render) &&
-        (!cache_ob->is_dup_ob)) {
+    if ((draw_ctx->obact == ob) && (!playing) && (!is_render) && (!cache_ob->is_dup_ob)) {
       if ((gpl->flag & GP_LAYER_LOCKED) == 0) {
         if (!stl->g_data->shgrps_edit_line) {
           stl->g_data->shgrps_edit_line = DRW_shgroup_create(e_data->gpencil_line_sh,
@@ -1137,11 +1096,9 @@ static void gpencil_draw_strokes(GpencilBatchCache *cache,
           DRW_shgroup_uniform_vec2(stl->g_data->shgrps_edit_point, "Viewport", viewport_size, 1);
         }
 
-        gpencil_add_editpoints_vertexdata(cache, ob, gpd, gpl, derived_gpf, src_gps);
+        gpencil_add_editpoints_vertexdata(cache, ob, gpd, gpl, gpf, gps);
       }
     }
-
-    GP_SET_SRC_GPS(src_gps);
   }
 }
 
@@ -1349,25 +1306,6 @@ static void gpencil_draw_onionskins(GpencilBatchCache *cache,
   }
 }
 
-static void gpencil_copy_frame(bGPDframe *gpf, bGPDframe *derived_gpf)
-{
-  derived_gpf->prev = gpf->prev;
-  derived_gpf->next = gpf->next;
-  derived_gpf->framenum = gpf->framenum;
-  derived_gpf->flag = gpf->flag;
-  derived_gpf->key_type = gpf->key_type;
-  derived_gpf->runtime = gpf->runtime;
-  copy_m4_m4(derived_gpf->runtime.viewmatrix, gpf->runtime.viewmatrix);
-
-  /* copy strokes */
-  BLI_listbase_clear(&derived_gpf->strokes);
-  for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
-    /* make copy of source stroke */
-    bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
-    BLI_addtail(&derived_gpf->strokes, gps_dst);
-  }
-}
-
 /* Triangulate stroke for high quality fill (this is done only if cache is null or stroke was
  * modified) */
 void DRW_gpencil_triangulate_stroke_fill(Object *ob, bGPDstroke *gps)
@@ -1878,7 +1816,6 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data,
                                gpd,
                                gpl,
                                gpf,
-                               gpf,
                                gpl->opacity,
                                gpl->tintcolor,
                                false,
@@ -1896,7 +1833,6 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data,
                              gpd,
                              gpl,
                              gpf,
-                             gpf,
                              gpl->opacity,
                              gpl->tintcolor,
                              false,
@@ -1912,28 +1848,6 @@ void DRW_gpencil_populate_multiedit(GPENCIL_e_data *e_data,
   cache->is_dirty = false;
 }
 
-/* ensure there is a derived frame */
-static void gpencil_ensure_derived_frame(bGPdata *gpd,
-                                         bGPDlayer *gpl,
-                                         bGPDframe *gpf,
-                                         GpencilBatchCache *cache,
-                                         bGPDframe **derived_gpf)
-{
-  /* create derived frames array data or expand */
-  int derived_idx = BLI_findindex(&gpd->layers, gpl);
-  *derived_gpf = &cache->derived_array[derived_idx];
-
-  /* if no derived frame or dirty cache, create a new one */
-  if ((*derived_gpf == NULL) || (cache->is_dirty)) {
-    if (*derived_gpf != NULL) {
-      /* first clear temp data */
-      BKE_gpencil_free_frame_runtime_data(*derived_gpf);
-    }
-    /* create new data (do not assign new memory)*/
-    gpencil_copy_frame(gpf, *derived_gpf);
-  }
-}
-
 /* helper for populate a complete grease pencil datablock */
 void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data,
                                     void *vedata,
@@ -1945,7 +1859,9 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data,
   const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph);
   Scene *scene = draw_ctx->scene;
 
-  bGPdata *gpd = (bGPdata *)ob->data;
+  /* Use original data to shared in edit/transform operators */
+  bGPdata *gpd_eval = (bGPdata *)ob->data;
+  bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
 
   View3D *v3d = draw_ctx->v3d;
   int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
@@ -1972,12 +1888,6 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data,
   /* calc max size of VBOs */
   gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
 
-  /* init general modifiers data */
-  if (!stl->storage->simplify_modif) {
-    if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
-      BKE_gpencil_lattice_init(ob);
-    }
-  }
   /* draw normal strokes */
   for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
     /* don't draw layer if hidden */
@@ -2025,8 +1935,9 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data,
       opacity = opacity * v3d->overlay.gpencil_fade_layer;
     }
 
-    /* create derived frames array data or expand */
-    gpencil_ensure_derived_frame(gpd, gpl, gpf, cache, &derived_gpf);
+    /* Get derived frames array data */
+    int derived_idx = BLI_findindex(&gpd->layers, gpl);
+    derived_gpf = &ob->runtime.derived_frames[derived_idx];
 
     /* draw onion skins */
     if (!ID_IS_LINKED(&gpd->id)) {
@@ -2046,7 +1957,6 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data,
                          ob,
                          gpd,
                          gpl,
-                         gpf,
                          derived_gpf,
                          opacity,
                          gpl->tintcolor,
@@ -2054,11 +1964,6 @@ void DRW_gpencil_populate_datablock(GPENCIL_e_data *e_data,
                          cache_ob);
   }
 
-  /* clear any lattice data */
-  if ((cache->is_dirty) && (ob->greasepencil_modifiers.first)) {
-    BKE_gpencil_lattice_clear(ob);
-  }
-
   /* create batchs and shading groups */
   DRW_gpencil_create_batches(cache);
   DRW_gpencil_shgroups_create(e_data, vedata, ob, cache, cache_ob);
index 2ac1dc3211c580e702f061f35b0fbe0a4a797519..52688f3768754a03f232adb0843b8c0b52edc646 100644 (file)
@@ -34,6 +34,9 @@ struct RenderEngine;
 struct RenderLayer;
 struct bGPDstroke;
 struct tGPspoint;
+struct GpencilBatchCache;
+struct GpencilBatchCacheElem;
+struct GpencilBatchGroup;
 
 #define GPENCIL_CACHE_BLOCK_SIZE 8
 #define GPENCIL_MAX_SHGROUPS 65536
@@ -46,23 +49,6 @@ struct tGPspoint;
 #define GPENCIL_COLOR_TEXTURE 1
 #define GPENCIL_COLOR_PATTERN 2
 
-#define GP_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
-#define GP_SIMPLIFY_ONPLAY(playing) \
-  (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \
-   ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0))
-#define GP_SIMPLIFY_FILL(scene, playing) \
-  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
-    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
-#define GP_SIMPLIFY_MODIF(scene, playing) \
-  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
-    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
-#define GP_SIMPLIFY_FX(scene, playing) \
-  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
-    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
-#define GP_SIMPLIFY_BLEND(scene, playing) \
-  ((GP_SIMPLIFY_ONPLAY(playing) && (GP_SIMPLIFY(scene)) && \
-    (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
-
 #define GP_IS_CAMERAVIEW ((rv3d != NULL) && (rv3d->persp == RV3D_CAMOB && v3d->camera))
 
 /* *********** OBJECTS CACHE *********** */
@@ -345,61 +331,6 @@ typedef struct GPENCIL_e_data {
 
 } GPENCIL_e_data; /* Engine data */
 
-/* GPUBatch Cache */
-typedef struct GpencilBatchCacheElem {
-  GPUBatch *batch;
-  GPUVertBuf *vbo;
-  int vbo_len;
-  /* attr ids */
-  GPUVertFormat format;
-  uint pos_id;
-  uint color_id;
-  uint thickness_id;
-  uint uvdata_id;
-  uint prev_pos_id;
-
-  /* size for VBO alloc */
-  int tot_vertex;
-} GpencilBatchCacheElem;
-
-typedef struct GpencilBatchGroup {
-  bGPDlayer *gpl;  /* reference to original layer */
-  bGPDframe *gpf;  /* reference to original frame */
-  bGPDstroke *gps; /* reference to original stroke */
-  short type;      /* type of element */
-  bool onion;      /* the group is part of onion skin */
-  int vertex_idx;  /* index of vertex data */
-} GpencilBatchGroup;
-
-typedef enum GpencilBatchGroup_Type {
-  eGpencilBatchGroupType_Stroke = 1,
-  eGpencilBatchGroupType_Point = 2,
-  eGpencilBatchGroupType_Fill = 3,
-  eGpencilBatchGroupType_Edit = 4,
-  eGpencilBatchGroupType_Edlin = 5,
-} GpencilBatchGroup_Type;
-
-typedef struct GpencilBatchCache {
-  GpencilBatchCacheElem b_stroke;
-  GpencilBatchCacheElem b_point;
-  GpencilBatchCacheElem b_fill;
-  GpencilBatchCacheElem b_edit;
-  GpencilBatchCacheElem b_edlin;
-
-  /* settings to determine if cache is invalid */
-  bool is_dirty;
-  bool is_editmode;
-  int cache_frame;
-
-  /* data with the shading groups */
-  int grp_used;                        /* total groups in arrays */
-  int grp_size;                        /* max size of the array */
-  struct GpencilBatchGroup *grp_cache; /* array of elements */
-
-  int tot_layers;
-  struct bGPDframe *derived_array; /* runtime data created by modifiers */
-} GpencilBatchCache;
-
 /* general drawing functions */
 struct DRWShadingGroup *DRW_gpencil_shgroup_stroke_create(struct GPENCIL_e_data *e_data,
                                                           struct GPENCIL_Data *vedata,
index c8d2547ad5154ffb6c142f58cab1d5ae33336d33..896cb8dd3a694f71de781a5120fc9d1d0e540664 100644 (file)
@@ -632,6 +632,59 @@ struct GP_EditableStrokes_Iter {
   } \
   (void)0
 
+/**
+ * Iterate over all editable strokes using derived data in the current context,
+ * stopping on each usable layer + stroke pair (i.e. gpl and gps)
+ * to perform some operations on the stroke.
+ *
+ * \param gpl: The identifier to use for the layer of the stroke being processed.
+ *                    Choose a suitable value to avoid name clashes.
+ * \param gps: The identifier to use for current stroke being processed.
+ *                    Choose a suitable value to avoid name clashes.
+ */
+#define GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \
+  { \
+    struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
+    Depsgraph *depsgraph_ = CTX_data_depsgraph(C); \
+    Object *obact_ = CTX_data_active_object(C); \
+    Object *obeval_ = DEG_get_evaluated_object(depsgraph_, obact_); \
+    bGPdata *gpd_ = CTX_data_gpencil_data(C); \
+    const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
+    int derived_idx = 0; \
+    for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { \
+      if (gpencil_layer_is_editable(gpl)) { \
+        bGPDframe *init_gpf_ = gpl->actframe; \
+        if (is_multiedit_) { \
+          init_gpf_ = gpl->frames.first; \
+        } \
+        for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \
+          if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \
+            ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \
+            /* get derived frame with modifiers applied */ \
+            bGPDframe *derived_gpf_ = &obeval_->runtime.derived_frames[derived_idx]; \
+            /* loop over strokes */ \
+            for (bGPDstroke *gps = derived_gpf_->strokes.first; gps; gps = gps->next) { \
+              /* skip strokes that are invalid for current view */ \
+              if (ED_gpencil_stroke_can_use(C, gps) == false) \
+                continue; \
+              /* check if the color is editable */ \
+              if (ED_gpencil_stroke_color_use(obact_, gpl, gps) == false) \
+                continue; \
+    /* ... Do Stuff With Strokes ...  */
+
+#define GP_DERIVED_STROKES_END(gpstroke_iter) \
+  } \
+  } \
+  if (!is_multiedit_) { \
+    break; \
+  } \
+  } \
+  } \
+  derived_idx++; \
+  } \
+  } \
+  (void)0
+
 /* ****************************************************** */
 
 #endif /* __GPENCIL_INTERN_H__ */
index ba806022d3e9eb4a44bf908658ad7da9ae9e867c..53dbd023e5179e04fa5280c6ba16c5ab68267140 100644 (file)
@@ -802,6 +802,7 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl,
 {
   bGPDspoint *pt1 = NULL;
   bGPDspoint *pt2 = NULL;
+  bGPDstroke *gps_orig = gps->runtime.gps_orig;
   int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
   int i;
   bool changed = false;
@@ -817,12 +818,12 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl,
       if (((x0 - mx) * (x0 - mx) + (y0 - my) * (y0 - my)) <= radius * radius) {
         /* change selection */
         if (select) {
-          gps->points->flag |= GP_SPOINT_SELECT;
-          gps->flag |= GP_STROKE_SELECT;
+          gps_orig->points->flag |= GP_SPOINT_SELECT;
+          gps_orig->flag |= GP_STROKE_SELECT;
         }
         else {
-          gps->points->flag &= ~GP_SPOINT_SELECT;
-          gps->flag &= ~GP_STROKE_SELECT;
+          gps_orig->points->flag &= ~GP_SPOINT_SELECT;
+          gps_orig->flag &= ~GP_STROKE_SELECT;
         }
 
         return true;
@@ -862,15 +863,21 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl,
            */
           hit = true;
           if (select) {
-            pt1->flag |= GP_SPOINT_SELECT;
-            pt2->flag |= GP_SPOINT_SELECT;
-
+            if (pt1->runtime.pt_orig != NULL) {
+              pt1->runtime.pt_orig->flag |= GP_SPOINT_SELECT;
+            }
+            if (pt2->runtime.pt_orig != NULL) {
+              pt2->runtime.pt_orig->flag |= GP_SPOINT_SELECT;
+            }
             changed = true;
           }
           else {
-            pt1->flag &= ~GP_SPOINT_SELECT;
-            pt2->flag &= ~GP_SPOINT_SELECT;
-
+            if (pt1->runtime.pt_orig != NULL) {
+              pt1->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT;
+            }
+            if (pt2->runtime.pt_orig != NULL) {
+              pt2->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT;
+            }
             changed = true;
           }
         }
@@ -884,24 +891,28 @@ static bool gp_stroke_do_circle_sel(bGPDlayer *gpl,
     /* if stroke mode expand selection */
     if ((hit) && (selectmode == GP_SELECTMODE_STROKE)) {
       for (i = 0, pt1 = gps->points; i < gps->totpoints; i++, pt1++) {
-        if (select) {
-          pt1->flag |= GP_SPOINT_SELECT;
-        }
-        else {
-          pt1->flag &= ~GP_SPOINT_SELECT;
+        if (pt1->runtime.pt_orig != NULL) {
+          if (select) {
+            pt1->runtime.pt_orig->flag |= GP_SPOINT_SELECT;
+          }
+          else {
+            pt1->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT;
+          }
         }
       }
     }
 
     /* expand selection to segment */
-    if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select)) {
+    if ((hit) && (selectmode == GP_SELECTMODE_SEGMENT) && (select) &&
+        (pt1->runtime.pt_orig != NULL)) {
       float r_hita[3], r_hitb[3];
       bool hit_select = (bool)(pt1->flag & GP_SPOINT_SELECT);
-      ED_gpencil_select_stroke_segment(gpl, gps, pt1, hit_select, false, scale, r_hita, r_hitb);
+      ED_gpencil_select_stroke_segment(
+          gpl, gps_orig, pt1->runtime.pt_orig, hit_select, false, scale, r_hita, r_hitb);
     }
 
     /* Ensure that stroke selection is in sync with its points */
-    BKE_gpencil_stroke_sync_selection(gps);
+    BKE_gpencil_stroke_sync_selection(gps_orig);
   }
 
   return changed;
@@ -955,11 +966,12 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
   rect.ymax = my + radius;
 
   /* find visible strokes, and select if hit */
-  GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+  GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
+  {
     changed |= gp_stroke_do_circle_sel(
         gpl, gps, &gsc, mx, my, radius, select, &rect, gpstroke_iter.diff_mat, selectmode, scale);
   }
-  GP_EDITABLE_STROKES_END(gpstroke_iter);
+  GP_DERIVED_STROKES_END(gpstroke_iter);
 
   /* updates */
   if (changed) {
@@ -1057,28 +1069,39 @@ static int gpencil_generic_select_exec(bContext *C,
   }
 
   /* select/deselect points */
-  GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+  GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
+  {
 
     bGPDspoint *pt;
     int i;
     bool hit = false;
     for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+      if (pt->runtime.pt_orig == NULL) {
+        continue;
+      }
+
       /* convert point coords to screenspace */
       const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
 
       if (strokemode == false) {
-        const bool is_select = (pt->flag & GP_SPOINT_SELECT) != 0;
+        const bool is_select = (pt->runtime.pt_orig->flag & GP_SPOINT_SELECT) != 0;
         const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
         if (sel_op_result != -1) {
-          SET_FLAG_FROM_TEST(pt->flag, sel_op_result, GP_SPOINT_SELECT);
+          SET_FLAG_FROM_TEST(pt->runtime.pt_orig->flag, sel_op_result, GP_SPOINT_SELECT);
           changed = true;
 
           /* expand selection to segment */
           if ((sel_op_result != -1) && (segmentmode)) {
-            bool hit_select = (bool)(pt->flag & GP_SPOINT_SELECT);
+            bool hit_select = (bool)(pt->runtime.pt_orig->flag & GP_SPOINT_SELECT);
             float r_hita[3], r_hitb[3];
-            ED_gpencil_select_stroke_segment(
-                gpl, gps, pt, hit_select, false, scale, r_hita, r_hitb);
+            ED_gpencil_select_stroke_segment(gpl,
+                                             gps->runtime.gps_orig,
+                                             pt->runtime.pt_orig,
+                                             hit_select,
+                                             false,
+                                             scale,
+                                             r_hita,
+                                             r_hitb);
           }
         }
       }
@@ -1092,16 +1115,19 @@ static int gpencil_generic_select_exec(bContext *C,
 
     /* if stroke mode expand selection */
     if (strokemode) {
-      const bool is_select = BKE_gpencil_stroke_select_check(gps);
+      const bool is_select = BKE_gpencil_stroke_select_check(gps->runtime.gps_orig);
       const bool is_inside = hit;
       const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
       if (sel_op_result != -1) {
         for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+          if (pt->runtime.pt_orig == NULL) {
+            continue;
+          }
           if (sel_op_result) {
-            pt->flag |= GP_SPOINT_SELECT;
+            pt->runtime.pt_orig->flag |= GP_SPOINT_SELECT;
           }
           else {
-            pt->flag &= ~GP_SPOINT_SELECT;
+            pt->runtime.pt_orig->flag &= ~GP_SPOINT_SELECT;
           }
         }
         changed = true;
@@ -1109,9 +1135,9 @@ static int gpencil_generic_select_exec(bContext *C,
     }
 
     /* Ensure that stroke selection is in sync with its points */
-    BKE_gpencil_stroke_sync_selection(gps);
+    BKE_gpencil_stroke_sync_selection(gps->runtime.gps_orig);
   }
-  GP_EDITABLE_STROKES_END(gpstroke_iter);
+  GP_DERIVED_STROKES_END(gpstroke_iter);
 
   /* if paint mode,delete selected points */
   if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
@@ -1328,13 +1354,17 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
 
   /* First Pass: Find stroke point which gets hit */
   /* XXX: maybe we should go from the top of the stack down instead... */
-  GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
+  GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
+  {
     bGPDspoint *pt;
     int i;
 
     /* firstly, check for hit-point */
     for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
       int xy[2];
+      if (pt->runtime.pt_orig == NULL) {
+        continue;
+      }
 
       bGPDspoint pt2;
       gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
@@ -1349,15 +1379,15 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
           /* only use this point if it is a better match than the current hit - T44685 */
           if (pt_distance < hit_distance) {
             hit_layer = gpl;
-            hit_stroke = gps;
-            hit_point = pt;
+            hit_stroke = gps->runtime.gps_orig;
+            hit_point = pt->runtime.pt_orig;
             hit_distance = pt_distance;
           }
         }
       }
     }
   }
-  GP_EDITABLE_STROKES_END(gpstroke_iter);
+  GP_DERIVED_STROKES_END(gpstroke_iter);
 
   /* Abort if nothing hit... */
   if (ELEM(NULL, hit_stroke, hit_point)) {
index bb38311cbac7e940b5377b3ed3049c5737bc27af..82fca6955587b88fcc530750ace104742360948c 100644 (file)
@@ -51,6 +51,11 @@ typedef struct bGPDcontrolpoint {
   int size;
 } bGPDcontrolpoint;
 
+typedef struct bGPDspoint_Runtime {
+  /** Original point (used to dereference evaluated data) */
+  struct bGPDspoint *pt_orig;
+} bGPDspoint_Runtime;
+
 /* Grease-Pencil Annotations - 'Stroke Point'
  * -> Coordinates may either be 2d or 3d depending on settings at the time
  * -> Coordinates of point on stroke, in proportions of window size
@@ -72,6 +77,10 @@ typedef struct bGPDspoint {
   float uv_fac;
   /** Uv rotation for dot mode. */
   float uv_rot;
+
+  /** Runtime data */
+  char _pad2[4];
+  bGPDspoint_Runtime runtime;
 } bGPDspoint;
 
 /* bGPDspoint->flag */
@@ -157,15 +166,21 @@ typedef enum eGPDpalette_Flag {
 
 /* Runtime temp data for bGPDstroke */
 typedef struct bGPDstroke_Runtime {
-  /* runtime final colors (result of original colors and modifiers) */
+  /** runtime final colors (result of original colors and modifiers) */
   float tmp_stroke_rgba[4];
+
+  /** runtime final fill colors (result of original colors and modifiers) */
   float tmp_fill_rgba[4];
 
-  /* temporary layer name only used during copy/paste to put the stroke in the original layer */
+  /** temporary layer name only used during copy/paste to put the stroke in the original layer */
   char tmp_layerinfo[128];
 
   /** Runtime falloff factor (only for transform). */
   float multi_frame_falloff;
+  char _pad[4];
+
+  /** Original stroke (used to dereference evaluated data) */
+  struct bGPDstroke *gps_orig;
 } bGPDstroke_Runtime;
 
 /* Grease-Pencil Annotations - 'Stroke'
@@ -211,7 +226,6 @@ typedef struct bGPDstroke {
   void *_pad3;
 
   bGPDstroke_Runtime runtime;
-  char _pad2[4];
 } bGPDstroke;
 
 /* bGPDstroke->flag */
index ae781ac4e9ef009d9f6d4ab9e055adcda3204b96..73b47f54c8fdea3fe759c756554ed3de43767404 100644 (file)
@@ -165,6 +165,10 @@ typedef struct Object_Runtime {
 
   /** Runtime grease pencil drawing data */
   struct GpencilBatchCache *gpencil_cache;
+  /** Runtime grease pencil derived data created by modifiers */
+  int tot_layers;
+  char _pad1[4];
+  struct bGPDframe *derived_frames;
 } Object_Runtime;
 
 typedef struct Object {