create_ponder_wonder

Exports Create ponders to disk.
git clone git://git.oshgnacknak.de/create_ponder_wonder.git
Log | Files | Refs | README

commit 7ba708c3e165b37a4b59dc7502e1db1172b060fe
parent 271eb34f048753922b691ce9d6de131f3434e702
Author: Oshgnacknak <osh@oshgnacknak.de>
Date:   Wed, 14 Apr 2021 23:18:54 +0200

Your problem now, Grim!

Diffstat:
Msrc/main/java/com/simibubi/create/foundation/ponder/PonderWonderUI.java | 6++++++
Msrc/main/java/de/oshgnacknak/create_ponder_wonder/CreatePonderWonder.java | 2+-
Asrc/main/java/de/oshgnacknak/create_ponder_wonder/PonderRenderScheduler.java | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main/java/de/oshgnacknak/create_ponder_wonder/PonderRenderer.java | 220++++++++++++++++---------------------------------------------------------------
4 files changed, 160 insertions(+), 176 deletions(-)

diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderWonderUI.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderWonderUI.java @@ -14,8 +14,14 @@ public class PonderWonderUI extends PonderUI { this.textRenderer = Minecraft.getInstance().fontRenderer; init(); } + public void ponderWonderRenderWindow(MatrixStack ms, float partialTicks) { RenderSystem.enableBlend(); renderVisibleScenes(ms, -10, -10, partialTicks); + renderWidgets(ms, -10, -10, partialTicks); + } + + public boolean isFinished() { + return getActiveScene().finished; } } diff --git a/src/main/java/de/oshgnacknak/create_ponder_wonder/CreatePonderWonder.java b/src/main/java/de/oshgnacknak/create_ponder_wonder/CreatePonderWonder.java @@ -12,7 +12,7 @@ public class CreatePonderWonder { public static final String MODID = "create_ponder_wonder"; public static final Logger LOGGER = LogManager.getLogger(MODID); - public static final PonderRenderer PONDER_RENDERER = new PonderRenderer(); + public static final PonderRenderScheduler PONDER_RENDERER = new PonderRenderScheduler(); public CreatePonderWonder() { MinecraftForge.EVENT_BUS.addListener(AllCommands::register); diff --git a/src/main/java/de/oshgnacknak/create_ponder_wonder/PonderRenderScheduler.java b/src/main/java/de/oshgnacknak/create_ponder_wonder/PonderRenderScheduler.java @@ -0,0 +1,107 @@ +package de.oshgnacknak.create_ponder_wonder; + +import com.simibubi.create.foundation.ponder.PonderRegistry; +import com.simibubi.create.foundation.ponder.PonderScene; +import com.simibubi.create.foundation.ponder.PonderWonderUI; +import net.minecraft.client.renderer.texture.NativeImage; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.concurrent.*; + +public class PonderRenderScheduler { + + private ExecutorService executorService; + private boolean rendering; + + public void start(String basePath) { + if (rendering) { + CreatePonderWonder.chat("Error: cannot be done twice"); + throw new IllegalStateException("Cannot start rendering twice"); + } + + rendering = true; + executorService = Executors.newSingleThreadExecutor(); + + CreatePonderWonder.LOGGER.info("Started rendering ponders"); + CreatePonderWonder.chat("Started rendering ponders"); + + executorService.submit(() -> + renderAllPonders(basePath)); + } + + private void renderAllPonders(String basePath) { + PonderRegistry.all + .values() + .stream() + .map(PonderRegistry::compile) + .flatMap(List::stream) + .forEach(ponder -> saveFrames(ponder, basePath)); + + CreatePonderWonder.LOGGER.info("All ponders rendered: {}", basePath); + CreatePonderWonder.chat("All ponders rendered: " + basePath); + + finishRendering(); + } + + private void saveFrames(PonderScene ponder, String basePath) { + try { + Path path = getOutPath(ponder, basePath); + + for (PonderRenderer.RenderResult result : new PonderRenderer(ponder)) { + Path out = path.resolve(String.format("%06d.png", result.frame)); + result.image.write(out); + System.gc(); + } + + CreatePonderWonder.chat("Finished rendering Ponder: " + path); + CreatePonderWonder.LOGGER.info("Finished rendering Ponder: {}", path); + } catch (Exception e) { + CreatePonderWonder.chat("Error: " + e.getMessage()); + CreatePonderWonder.LOGGER.error("Could not save image", e); + e.printStackTrace(); + } + } + + private Path getOutPath(PonderScene ponder, String basePath) throws IOException { + Path path = Paths.get( + basePath, + CreatePonderWonder.MODID, + ponder.getString("out")); + Files.createDirectories(path); + return path; + } + + public void stop() { + if (!rendering) { + CreatePonderWonder.chat("Aleady stopped..."); + return; + } + + CreatePonderWonder.LOGGER.warn("Stopping rendering ponders abruptly"); + CreatePonderWonder.chat("Stopping rendering ponders abruptly"); + + try { + executorService.shutdown(); + while (!executorService.awaitTermination(3, TimeUnit.SECONDS)) { + executorService.shutdownNow(); + } + + finishRendering(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private void finishRendering() { + executorService = null; + rendering = false; + System.gc(); + + CreatePonderWonder.LOGGER.info("Stopped rendering ponders"); + CreatePonderWonder.chat("Stopped rendering ponders"); + } +}+ \ No newline at end of file diff --git a/src/main/java/de/oshgnacknak/create_ponder_wonder/PonderRenderer.java b/src/main/java/de/oshgnacknak/create_ponder_wonder/PonderRenderer.java @@ -1,207 +1,78 @@ package de.oshgnacknak.create_ponder_wonder; -import com.simibubi.create.foundation.ponder.PonderRegistry; +import com.simibubi.create.content.contraptions.components.actors.SeatEntity; +import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderWonderUI; import io.netty.util.concurrent.GlobalEventExecutor; import io.netty.util.concurrent.Promise; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.NativeImage; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; import java.util.List; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.ExecutionException; -public class PonderRenderer { +public class PonderRenderer implements Iterable<PonderRenderer.RenderResult>, Iterator<PonderRenderer.RenderResult> { - private static final int FPS = 60; - private static final int MAX_FRAMES = 15; - private static final int MAX_PONDERS_AT_ONCE = 3; - - private final BlockingQueue<PonderWonderUI> pondersToRender; - private final AtomicInteger currentlyRendering; - private final Lock lock; - private final Condition renderDone; - - private ExecutorService executorService; - private boolean rendering; - private boolean allEnqueued; - private String basePath; - - public PonderRenderer() { - pondersToRender = new ArrayBlockingQueue<>(MAX_PONDERS_AT_ONCE); - currentlyRendering = new AtomicInteger(); - lock = new ReentrantLock(); - renderDone = lock.newCondition(); - } + public static class RenderResult { + public final NativeImage image; + public final int frame; - public void start(String basePath) { - if (rendering) { - CreatePonderWonder.chat("Error: cannot be done twice"); - throw new IllegalStateException("Cannot start rendering twice"); + public RenderResult(NativeImage image, int frame) { + this.image = image; + this.frame = frame; } - - rendering = true; - this.basePath = basePath; - currentlyRendering.set(0); - pondersToRender.clear(); - - executorService = Executors.newCachedThreadPool(); - executorService.submit(this::renderPonders); - executorService.submit(this::enqueueAllPonders); - - CreatePonderWonder.LOGGER.info("Started rendering ponders"); - CreatePonderWonder.chat("Started rendering ponders"); } - public void stop() { - if (!rendering) { - CreatePonderWonder.chat("Aleady stopped..."); - return; - } + private static final int FPS = 60; + private static final int MAX_FRAMES = FPS*3; - CreatePonderWonder.LOGGER.warn("Stopping rendering ponders abruptly"); - CreatePonderWonder.chat("Stopping rendering ponders abruptly"); + private final PonderWonderUI ponder; + private int frame; - try { - executorService.shutdown(); - while (!executorService.awaitTermination(3, TimeUnit.SECONDS)) { - executorService.shutdownNow(); - } - rendering = false; - - CreatePonderWonder.LOGGER.info("Stopped rendering ponders"); - CreatePonderWonder.chat("Stopped rendering ponders"); - } catch (InterruptedException e) { - e.printStackTrace(); - } + public PonderRenderer(PonderScene ponder) { + this.ponder = new PonderWonderUI(ponder); + this.frame = 0; } - private void renderPonders() { - try { - while (rendering) { - if (currentlyRendering.get() < MAX_PONDERS_AT_ONCE) { - PonderWonderUI ponder = pondersToRender.take(); - currentlyRendering.incrementAndGet(); - executorService.submit(() -> - renderPonder(ponder)); - } else { - waitForRenderDone(); - } - - if (allEnqueued) { - rendering = false; - CreatePonderWonder.LOGGER.info("All ponders rendered: {}", basePath); - CreatePonderWonder.chat("All ponders rendered: " + basePath); - return; - } - } - } catch (Exception e) { - CreatePonderWonder.chat("Error: " + e.getMessage()); - CreatePonderWonder.LOGGER.error("Exception whilst rendering ponders", e); - } + @Override + public Iterator<RenderResult> iterator() { + return this; } - private void waitForRenderDone() throws InterruptedException { - lock.lock(); - try { - renderDone.await(); - } finally { - lock.unlock(); - } + @Override + public boolean hasNext() { + return !ponder.isFinished(); } - private void renderPonder(PonderWonderUI ponder) { + @Override + public RenderResult next() { try { - Path path = renderFrames(ponder); - - CreatePonderWonder.chat("Finished rendering Ponder: " + path); - CreatePonderWonder.LOGGER.info("Finished rendering Ponder: {}", path); - - } catch (IOException | InterruptedException | ExecutionException e) { - CreatePonderWonder.chat("Error: " + e.getMessage()); - CreatePonderWonder.LOGGER.error("Could not save image", e); - } finally { - signalRenderDone(); - } - } - - private void signalRenderDone() { - lock.lock(); - try { - currentlyRendering.decrementAndGet(); - renderDone.signal(); - } finally { - lock.unlock(); - } - } - - private Path renderFrames(PonderWonderUI ponder) throws InterruptedException, ExecutionException, IOException { - Path path = Paths.get( - basePath, - CreatePonderWonder.MODID, - ponder.getActiveScene().getString("out")); - Files.createDirectories(path); - - for (int frame = 0; frame < MAX_FRAMES; frame++) { - Promise<NativeImage> promise = renderFrame(ponder, frame); - NativeImage img = promise.get(); + Promise<NativeImage> promise = GlobalEventExecutor.INSTANCE.newPromise(); + + float pt = (frame % PonderRenderer.FPS) / (PonderRenderer.FPS / 3.0f); + Minecraft.getInstance().field_213275_aU.add(() -> { + try { + NativeImage img = RenderUtils.render(ms -> + ponder.ponderWonderRenderWindow(ms, pt)); + promise.setSuccess(img); + } catch (Exception e) { + promise.setFailure(e); + } + }); - Path out = path.resolve(String.format("%06d.png", frame)); - img.write(out); + RenderResult res = new RenderResult(promise.get(), frame); if (frame % 3 == 2) { ponder.tick(); } - } - - return path; - } - - public Promise<NativeImage> renderFrame(PonderWonderUI ponder, int frame) { - Promise<NativeImage> promise = GlobalEventExecutor.INSTANCE.newPromise(); - - float pt = (frame % FPS) / (FPS / 3.0f); - Minecraft.getInstance().field_213275_aU.add(() -> { - try { - NativeImage img = RenderUtils.render(ms -> - ponder.ponderWonderRenderWindow(ms, pt)); - promise.setSuccess(img); - } catch (Exception e) { - promise.setFailure(e); - } - }); - - return promise; - } - - private void enqueueAllPonders() { - allEnqueued = false; - Iterable<PonderWonderUI> ponders = getPonders(); + frame++; - try { - for (PonderWonderUI ponder : ponders) { - pondersToRender.put(ponder); - } - allEnqueued = true; - } catch (InterruptedException e) { - e.printStackTrace(); + return res; + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); } } - private Iterable<PonderWonderUI> getPonders() { - return PonderRegistry.all - .values() - .stream() - .map(PonderRegistry::compile) - .flatMap(List::stream) - .map(PonderWonderUI::new) - ::iterator; - } -}- \ No newline at end of file +}