From 9e7818fcae373c05413206ad2675967c74f781d0 Mon Sep 17 00:00:00 2001 From: AterAnimAvis Date: Sun, 10 Jan 2021 14:26:15 +0000 Subject: [PATCH] fix: AnimationRender not handling animations that take longer than 1 frame --- Signed-off-by: AterAnimAvis --- .../fabric/client/render/RenderManager.java | 48 ++++++++++++++++--- .../client/render/report/ProgressManager.java | 6 ++- .../forge/client/render/RenderManager.java | 47 +++++++++++++++--- .../client/render/report/ProgressManager.java | 5 ++ 4 files changed, 93 insertions(+), 13 deletions(-) diff --git a/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/RenderManager.java b/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/RenderManager.java index de0aed0..7ca3a2b 100644 --- a/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/RenderManager.java +++ b/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/RenderManager.java @@ -84,6 +84,7 @@ public static void bulk(IRenderer renderer, ImageHandler handler private static final int FPS = 20; private static final int AUTO_LOOP_LENGTH = 30; private static final long NANOS_IN_A_SECOND = 1_000_000_000L; + private static final int MAX_CONSUME = FPS * AUTO_LOOP_LENGTH; public static void animated(IAnimatedRenderer renderer, Function provider, @@ -118,29 +119,53 @@ public static void animated(IAnimatedRenderer renderer, private static final Text RENDERING_GIF = new LiteralText("Rendering GIF").formatted(Formatting.GOLD); private static final Text RENDERING_AUTO = new LiteralText("Auto Loop").formatted(Formatting.GOLD); + private static final Text RENDERING_SKIP = new LiteralText("Skipping First").formatted(Formatting.GOLD); private static void animated(IAnimatedRenderer renderer, Consumer callback, S params, int length, boolean loop, T value, ImageHandler write) throws RuntimeException { - AtomicBoolean isSameAsInitial = new AtomicBoolean(false); + AtomicBoolean isSameAsInitial = new AtomicBoolean(true); AtomicReference initial = new AtomicReference<>(); RenderManager.isRendering = true; + int frame = 0; renderer.setup(params); ImageHandler init = (v, image) -> initial.compareAndSet(null, image); ImageHandler checkImage = (v, image) -> isSameAsInitial.set(Images.same(initial.get(), image)); - ImageHandler writeFinal = checkImage.andThen((v, image) -> { + ImageHandler checkWrite = checkImage.andThen(write); + ImageHandler writeDifferent = checkImage.andThen((v, image) -> { if (!isSameAsInitial.get()) write.accept(v, image); }); + ImageHandler writeSame = checkImage.andThen((v, image) -> { + if (isSameAsInitial.get()) write.accept(v, image); + }); + + /* Skip First Frame + Render Second */ + ProgressManager.init(RENDERING_SKIP, -1); + /* We need to handle the case where the target doesn't actually animate so we add a timeout */ + int timeout = MAX_CONSUME; + while (isSameAsInitial.get() && timeout > 0) { + timeout--; + final ImageHandler consumer = frame == 0 ? init : timeout == 0 ? write : writeDifferent; + + ProgressManager.push(ProgressManager.getProgress()); + renderer.render(value, consumer, NANOS_IN_A_SECOND / FPS * frame++); + ProgressManager.pop(); + + ProgressManager.render(); + } + ProgressManager.end(); /* Render for Specified Length */ ProgressManager.init(RENDERING_GIF, length); - for (int i = 0; i < length; i++) { - final ImageHandler consumer = i == 0 ? init.andThen(write) : i == length - 1 ? checkImage.andThen(write) : write; + ProgressManager.skip(); + + for (int i = 1; i < length; i++) { + final ImageHandler consumer = i == length - 1 ? checkWrite : write; ProgressManager.push(ProgressManager.getProgress()); - renderer.render(value, consumer, NANOS_IN_A_SECOND / FPS * i); + renderer.render(value, consumer, NANOS_IN_A_SECOND / FPS * frame++); ProgressManager.pop(); ProgressManager.render(); @@ -153,10 +178,21 @@ private static void animated(IAnimatedRenderer renderer, Consumer 0) { + timeout--; + + ProgressManager.push(ProgressManager.getProgress()); + renderer.render(value, writeSame, NANOS_IN_A_SECOND / FPS * frame++); + ProgressManager.pop(); + ProgressManager.render(); } ProgressManager.end(); diff --git a/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/report/ProgressManager.java b/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/report/ProgressManager.java index 6406c53..7124d73 100644 --- a/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/report/ProgressManager.java +++ b/fabric/src/main/java/com/unascribed/blockrenderer/fabric/client/render/report/ProgressManager.java @@ -1,6 +1,5 @@ package com.unascribed.blockrenderer.fabric.client.render.report; - import com.unascribed.blockrenderer.fabric.client.varia.rendering.Display; import com.unascribed.blockrenderer.fabric.client.varia.rendering.GL; import com.unascribed.blockrenderer.varia.debug.Debug; @@ -56,6 +55,11 @@ public static void pop() { last = now; } + public static void skip() { + push(getProgress()); + pop(); + } + public static void end() { /* Log Time */ long now = System.nanoTime(); diff --git a/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/RenderManager.java b/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/RenderManager.java index cb994f5..f73a7bd 100644 --- a/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/RenderManager.java +++ b/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/RenderManager.java @@ -84,6 +84,7 @@ public static void bulk(IRenderer renderer, ImageHandler handler private static final int FPS = 20; private static final int AUTO_LOOP_LENGTH = 30; private static final long NANOS_IN_A_SECOND = 1_000_000_000L; + private static final int MAX_CONSUME = FPS * AUTO_LOOP_LENGTH; public static void animated(IAnimatedRenderer renderer, Function provider, @@ -118,29 +119,52 @@ public static void animated(IAnimatedRenderer renderer, private static final ITextComponent RENDERING_GIF = new StringTextComponent("Rendering GIF").mergeStyle(TextFormatting.GOLD); private static final ITextComponent RENDERING_AUTO = new StringTextComponent("Auto Loop").mergeStyle(TextFormatting.GOLD); + private static final ITextComponent RENDERING_SKIP = new StringTextComponent("Skipping First").mergeStyle(TextFormatting.GOLD); private static void animated(IAnimatedRenderer renderer, Consumer callback, S params, int length, boolean loop, T value, ImageHandler write) throws RuntimeException { - AtomicBoolean isSameAsInitial = new AtomicBoolean(false); + AtomicBoolean isSameAsInitial = new AtomicBoolean(true); AtomicReference initial = new AtomicReference<>(); RenderManager.isRendering = true; + int frame = 0; renderer.setup(params); ImageHandler init = (v, image) -> initial.compareAndSet(null, image); ImageHandler checkImage = (v, image) -> isSameAsInitial.set(Images.same(initial.get(), image)); - ImageHandler writeFinal = checkImage.andThen((v, image) -> { + ImageHandler checkWrite = checkImage.andThen(write); + ImageHandler writeDifferent = checkImage.andThen((v, image) -> { if (!isSameAsInitial.get()) write.accept(v, image); }); + ImageHandler writeSame = checkImage.andThen((v, image) -> { + if (isSameAsInitial.get()) write.accept(v, image); + }); + + /* Skip First Frame + Render Second */ + ProgressManager.init(RENDERING_SKIP, -1); + /* We need to handle the case where the target doesn't actually animate so we add a timeout */ + int timeout = MAX_CONSUME; + while (isSameAsInitial.get() && timeout > 0) { + timeout--; + final ImageHandler consumer = frame == 0 ? init : timeout == 0 ? write : writeDifferent; + + ProgressManager.push(ProgressManager.getProgress()); + renderer.render(value, consumer, NANOS_IN_A_SECOND / FPS * frame++); + ProgressManager.pop(); + + ProgressManager.render(); + } + ProgressManager.end(); /* Render for Specified Length */ ProgressManager.init(RENDERING_GIF, length); - for (int i = 0; i < length; i++) { - final ImageHandler consumer = i == 0 ? init.andThen(write) : i == length - 1 ? checkImage.andThen(write) : write; + ProgressManager.skip(); + for (int i = 1; i < length; i++) { + final ImageHandler consumer = i == length - 1 ? checkWrite : write; ProgressManager.push(ProgressManager.getProgress()); - renderer.render(value, consumer, NANOS_IN_A_SECOND / FPS * i); + renderer.render(value, consumer, NANOS_IN_A_SECOND / FPS * frame++); ProgressManager.pop(); ProgressManager.render(); @@ -153,10 +177,21 @@ private static void animated(IAnimatedRenderer renderer, Consumer 0) { + timeout--; + + ProgressManager.push(ProgressManager.getProgress()); + renderer.render(value, writeSame, NANOS_IN_A_SECOND / FPS * frame++); + ProgressManager.pop(); + ProgressManager.render(); } ProgressManager.end(); diff --git a/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/report/ProgressManager.java b/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/report/ProgressManager.java index 9cb5ead..65034ca 100644 --- a/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/report/ProgressManager.java +++ b/forge/src/main/java/com/unascribed/blockrenderer/forge/client/render/report/ProgressManager.java @@ -55,6 +55,11 @@ public static void pop() { last = now; } + public static void skip() { + push(getProgress()); + pop(); + } + public static void end() { /* Log Time */ long now = System.nanoTime();