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:
authorfiledescriptor <falkdavid@gmx.de>2022-06-15 16:34:54 +0300
committerPhilipp Oeser <info@graphics-engineer.com>2022-06-22 12:51:57 +0300
commit16112ac7fd4f2b8e66fa51345096b4fa83aa0349 (patch)
treec0a5bf8034f4ce2ef78871e0409758fa01f8aee4
parentf02d54440dea3716893962c6fcbe6e2f9173666f (diff)
Fix T98853: Blender crashes when moving grease pencil object has any invisible layers
Whats happening is that the modifier keeps adding new frames to the evaluated object resulting in an exponential increase. This is because when preparing the data for the modifiers we only copy visible strokes to the eval object. But the modifiers do not consider visibility and will generate the mirrored strokes even for layers that are hidden. Because those layers have not been copied (only their structure) we run into this issue. The solution is always copy the active frame of all layers (even if the layer is hidden).
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index faafd1e1040..5e6c00688b3 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -647,32 +647,38 @@ static bGPdata *gpencil_copy_structure_for_eval(bGPdata *gpd)
return gpd_eval;
}
-static void copy_frame_to_eval_cb(bGPDlayer *UNUSED(gpl),
+static void copy_frame_to_eval_ex(bGPDframe *gpf_orig, bGPDframe *gpf_eval)
+{
+ /* Free any existing eval stroke data. This happens in case we have a single user on the data
+ * block and the strokes have not been deleted. */
+ if (!BLI_listbase_is_empty(&gpf_eval->strokes)) {
+ BKE_gpencil_free_strokes(gpf_eval);
+ }
+ /* Copy strokes to eval frame and update internal orig pointers. */
+ BKE_gpencil_frame_copy_strokes(gpf_orig, gpf_eval);
+ BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
+}
+
+static void copy_frame_to_eval_cb(bGPDlayer *gpl,
bGPDframe *gpf,
bGPDstroke *UNUSED(gps),
void *UNUSED(thunk))
{
- /* Early return when callback is not provided with a frame. */
- if (gpf == NULL) {
+ /* Early return when callback:
+ * - Is not provided with a frame.
+ * - When the frame is the layer's active frame (already handled in
+ * gpencil_copy_visible_frames_to_eval).
+ */
+ if (gpf == NULL || gpf == gpl->actframe) {
return;
}
- /* Free any existing eval stroke data. This happens in case we have a single user on the data
- * block and the strokes have not been deleted. */
- if (!BLI_listbase_is_empty(&gpf->strokes)) {
- BKE_gpencil_free_strokes(gpf);
- }
-
- /* Get original frame. */
- bGPDframe *gpf_orig = gpf->runtime.gpf_orig;
- /* Copy strokes to eval frame and update internal orig pointers. */
- BKE_gpencil_frame_copy_strokes(gpf_orig, gpf);
- BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf);
+ copy_frame_to_eval_ex(gpf->runtime.gpf_orig, gpf);
}
static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- /* Remap layers' active frame with time modifiers applied. */
+ /* Remap layers'active frame with time modifiers applied. */
bGPdata *gpd_eval = ob->data;
LISTBASE_FOREACH (bGPDlayer *, gpl_eval, &gpd_eval->layers) {
bGPDframe *gpf_eval = gpl_eval->actframe;
@@ -680,9 +686,14 @@ static void gpencil_copy_visible_frames_to_eval(Depsgraph *depsgraph, Scene *sce
if (gpf_eval == NULL || gpf_eval->framenum != remap_cfra) {
gpl_eval->actframe = BKE_gpencil_layer_frame_get(gpl_eval, remap_cfra, GP_GETFRAME_USE_PREV);
}
+ /* Always copy active frame to eval, because the modifiers always evaluate the active frame,
+ * even if it's not visible (e.g. the layer is hidden).*/
+ if (gpl_eval->actframe != NULL) {
+ copy_frame_to_eval_ex(gpf_eval->runtime.gpf_orig, gpl_eval->actframe);
+ }
}
- /* Copy only visible frames to evaluated version. */
+ /* Copy visible frames that are not the active one to evaluated version. */
BKE_gpencil_visible_stroke_advanced_iter(
NULL, ob, copy_frame_to_eval_cb, NULL, NULL, true, scene->r.cfra);
}