From 841bba04bd05fa09950d133085ae762c98147f5e Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Fri, 12 Mar 2021 20:42:37 +0100 Subject: [PATCH] Pondering too quickly - Fixed idle instruction only idling for t-1 - Made keyframe skipping a little easier - Added option to register keyframes as part of a text window builder - PonderUI now stalls the scene briefly after skips --- .../foundation/ponder/PonderProgressBar.java | 230 ++++++++++-------- .../create/foundation/ponder/PonderScene.java | 10 +- .../create/foundation/ponder/PonderUI.java | 25 +- .../foundation/ponder/SceneBuilder.java | 20 +- .../ponder/content/GantryScenes.java | 22 +- .../ponder/elements/TextWindowElement.java | 5 + .../instructions/KeyframeInstruction.java | 11 +- 7 files changed, 188 insertions(+), 135 deletions(-) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java index 93816d125..63f813347 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java @@ -5,150 +5,170 @@ import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.LerpedFloat; + +import net.minecraft.client.Minecraft; import net.minecraft.client.audio.SoundHandler; +import net.minecraft.client.gui.FontRenderer; import net.minecraftforge.fml.client.gui.GuiUtils; import org.antlr.v4.runtime.misc.IntegerList; public class PonderProgressBar extends AbstractSimiWidget { - LerpedFloat progress; - LerpedFloat flash; + LerpedFloat progress; + LerpedFloat flash; - PonderUI ponder; + PonderUI ponder; - public PonderProgressBar(PonderUI ponder, int xIn, int yIn, int widthIn, int heightIn) { - super(xIn, yIn, widthIn, heightIn); + public PonderProgressBar(PonderUI ponder, int xIn, int yIn, int widthIn, int heightIn) { + super(xIn, yIn, widthIn, heightIn); - this.ponder = ponder; - progress = LerpedFloat.linear() - .startWithValue(0); - flash = LerpedFloat.linear() - .startWithValue(0); - } + this.ponder = ponder; + progress = LerpedFloat.linear() + .startWithValue(0); + flash = LerpedFloat.linear() + .startWithValue(0); + } - public void tick() { - progress.chase(ponder.getActiveScene().getSceneProgress(), .5f, LerpedFloat.Chaser.EXP); - progress.tickChaser(); + public void tick() { + progress.chase(ponder.getActiveScene() + .getSceneProgress(), .5f, LerpedFloat.Chaser.EXP); + progress.tickChaser(); - if (isHovered) - flash(); - } + if (isHovered) + flash(); + } - public void flash() { - float value = flash.getValue(); - flash.setValue(value + (1 - value) * .2f); - } + public void flash() { + float value = flash.getValue(); + flash.setValue(value + (1 - value) * .2f); + } - public void dim() { - float value = flash.getValue(); - flash.setValue(value * .5f); - } + public void dim() { + float value = flash.getValue(); + flash.setValue(value * .5f); + } - @Override - protected boolean clicked(double mouseX, double mouseY) { - return this.active && this.visible && - !ponder.getActiveScene().keyframeTimes.isEmpty() && - mouseX >= (double)this.x && - mouseX < (double)(this.x + this.width) && - mouseY >= (double)this.y - 3 && - mouseY < (double)(this.y + this.height + 3); - } + @Override + protected boolean clicked(double mouseX, double mouseY) { + return this.active && this.visible && !ponder.getActiveScene().keyframeTimes.isEmpty() + && mouseX >= (double) this.x && mouseX < (double) (this.x + this.width) && mouseY >= (double) this.y - 3 + && mouseY < (double) (this.y + this.height + 20); + } - @Override - public void onClick(double mouseX, double mouseY) { - PonderScene activeScene = ponder.getActiveScene(); - int clickedAtTime = (int) ((mouseX - x) / ((double) width) * activeScene.totalTime); + @Override + public void onClick(double mouseX, double mouseY) { + PonderScene activeScene = ponder.getActiveScene(); + int clickedAtTime = (int) ((mouseX - x) / ((double) width) * activeScene.totalTime); - int seekTime = 0; + int seekTime = 0; - IntegerList keyframeTimes = activeScene.keyframeTimes; - for (int i = 0; i < keyframeTimes.size(); i++) { - int keyframeTime = keyframeTimes.get(i); + IntegerList keyframeTimes = activeScene.keyframeTimes; + for (int i = 0; i < keyframeTimes.size(); i++) { + int keyframeTime = keyframeTimes.get(i); - if (keyframeTime > clickedAtTime) - break; + if (keyframeTime > clickedAtTime) + break; - seekTime = keyframeTime; - } - ponder.seekToTime(seekTime); - } + seekTime = keyframeTime; + } + ponder.seekToTime(seekTime); + } - public int getHoveredKeyframeIndex(double mouseX) { - PonderScene activeScene = ponder.getActiveScene(); - int clickedAtTime = (int) ((mouseX - x) / ((double) width) * activeScene.totalTime); + public int getHoveredKeyframeIndex(double mouseX) { + PonderScene activeScene = ponder.getActiveScene(); + int clickedAtTime = (int) ((mouseX - x) / ((double) width) * activeScene.totalTime); - int index = -1; + int index = -1; - IntegerList keyframeTimes = activeScene.keyframeTimes; - for (int i = 0; i < keyframeTimes.size(); i++) { - int keyframeTime = keyframeTimes.get(i); + IntegerList keyframeTimes = activeScene.keyframeTimes; + for (int i = 0; i < keyframeTimes.size(); i++) { + int keyframeTime = keyframeTimes.get(i); - if (keyframeTime > clickedAtTime) - break; + if (keyframeTime > clickedAtTime) + break; - index = i; - } + index = i; + } - return index; - } + return index; + } - @Override - public void renderButton(int mouseX, int mouseY, float partialTicks) { + @Override + public void renderButton(int mouseX, int mouseY, float partialTicks) { - isHovered = clicked(mouseX, mouseY); + isHovered = clicked(mouseX, mouseY); - RenderSystem.pushMatrix(); - RenderSystem.translated(0, 0, 400); - PonderUI.renderBox(x, y, width, height, false); - RenderSystem.popMatrix(); + RenderSystem.pushMatrix(); + RenderSystem.translated(0, 0, 400); + PonderUI.renderBox(x, y, width, height, false); + RenderSystem.popMatrix(); - RenderSystem.pushMatrix(); - RenderSystem.translated(x - 2, y - 2, 0); + RenderSystem.pushMatrix(); + RenderSystem.translated(x - 2, y - 2, 0); - RenderSystem.pushMatrix(); - RenderSystem.scaled((width + 4) * progress.getValue(partialTicks), 1, 1); - GuiUtils.drawGradientRect(500, 0, 3, 1, 4, 0x60ffeedd, 0x60ffeedd); - RenderSystem.popMatrix(); + RenderSystem.pushMatrix(); + RenderSystem.scaled((width + 4) * progress.getValue(partialTicks), 1, 1); + GuiUtils.drawGradientRect(500, 0, 3, 1, 4, 0x80ffeedd, 0x80ffeedd); + GuiUtils.drawGradientRect(500, 0, 4, 1, 5, 0x50ffeedd, 0x50ffeedd); + RenderSystem.popMatrix(); - renderKeyframes(mouseX, partialTicks); + renderKeyframes(mouseX, partialTicks); - RenderSystem.popMatrix(); - } + RenderSystem.popMatrix(); + } - private void renderKeyframes(int mouseX, float partialTicks) { - PonderScene activeScene = ponder.getActiveScene(); + private void renderKeyframes(int mouseX, float partialTicks) { + PonderScene activeScene = ponder.getActiveScene(); - int hoverStartColor; - int hoverEndColor; - int hoverIndex; - if (isHovered) { - hoverIndex = getHoveredKeyframeIndex(mouseX); + int hoverStartColor; + int hoverEndColor; + int hoverIndex; - float flashValue = flash.getValue(partialTicks) * 3 + (float) Math.sin((AnimationTickHolder.getTicks() + partialTicks) / 6); + if (isHovered) { + hoverIndex = getHoveredKeyframeIndex(mouseX); + float flashValue = flash.getValue(partialTicks) * 3 + + (float) Math.sin((AnimationTickHolder.getTicks() + partialTicks) / 6); - hoverEndColor = ColorHelper.applyAlpha(0x70ffffff, flashValue); - hoverStartColor = ColorHelper.applyAlpha(0x30ffffff, flashValue); - } - else { - hoverIndex = -1; - hoverEndColor = 0; - hoverStartColor = 0; - } + hoverEndColor = ColorHelper.applyAlpha(0x70ffffff, flashValue); + hoverStartColor = ColorHelper.applyAlpha(0x30ffffff, flashValue); + } else { + hoverIndex = -1; + hoverEndColor = 0; + hoverStartColor = 0; + } - IntegerList keyframeTimes = activeScene.keyframeTimes; - for (int i = 0; i < keyframeTimes.size(); i++) { - int keyframeTime = keyframeTimes.get(i); + IntegerList keyframeTimes = activeScene.keyframeTimes; + for (int i = 0; i < keyframeTimes.size(); i++) { + int keyframeTime = keyframeTimes.get(i); + int keyframePos = (int) (((float) keyframeTime) / ((float) activeScene.totalTime) * (width + 4)); - int startColor = i == hoverIndex ? hoverStartColor : 0x60ffeedd; - int endColor = i == hoverIndex ? hoverEndColor : 0x60ffeedd; + int startColor = i == hoverIndex ? hoverStartColor : 0x30ffeedd; + int endColor = i == hoverIndex ? hoverEndColor : 0x60ffeedd; + int height = i == hoverIndex ? 8 : 4; - int keyframePos = (int) (((float) keyframeTime) / ((float) activeScene.totalTime) * (width + 4)); - GuiUtils.drawGradientRect(500, keyframePos, 1, keyframePos + 1, 4, startColor, endColor); - } - } + if (i == hoverIndex) { + FontRenderer font = Minecraft.getInstance().fontRenderer; + GuiUtils.drawGradientRect(500, keyframePos, 10, keyframePos + 1, 10 + height, endColor, startColor); + RenderSystem.pushMatrix(); + RenderSystem.translated(0, 0, 400); + String text; + int offset; + if (activeScene.currentTime < keyframeTime) { + text = ">"; + offset = -1 - font.getStringWidth(text); + } else { + text = "<"; + offset = 3; + } + font.drawString(text, keyframePos + offset, 10, endColor); + RenderSystem.popMatrix(); + } + GuiUtils.drawGradientRect(500, keyframePos, -1, keyframePos + 1, 2 + height, startColor, endColor); + } + } - @Override - public void playDownSound(SoundHandler handler) { + @Override + public void playDownSound(SoundHandler handler) { - } + } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java index 155f88c22..f341d127f 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java @@ -13,7 +13,6 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -import com.simibubi.create.foundation.ponder.instructions.KeyframeInstruction; import org.antlr.v4.runtime.misc.IntegerList; import org.apache.commons.lang3.mutable.MutableDouble; import org.apache.commons.lang3.mutable.MutableObject; @@ -271,6 +270,8 @@ public class PonderScene { instruction.tick(this); if (instruction.isComplete()) { iterator.remove(); + if (instruction.isBlocking()) + break; continue; } if (instruction.isBlocking()) @@ -299,10 +300,9 @@ public class PonderScene { stoppedCounting = true; } - public void markKeyframe() { - if (!stoppedCounting) { - keyframeTimes.add(totalTime); - } + public void markKeyframe(int offset) { + if (!stoppedCounting) + keyframeTimes.add(totalTime + offset); } public void addElement(PonderElement e) { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java index e5670d0f4..52fd625c5 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java @@ -68,6 +68,7 @@ public class PonderUI extends AbstractSimiScreen { private PonderButton left, right, scan, chap, userMode; private PonderProgressBar progressBar; + private int skipCooling = 0; public static PonderUI of(ResourceLocation id) { return new PonderUI(PonderRegistry.compile(id)); @@ -200,6 +201,9 @@ public class PonderUI extends AbstractSimiScreen { public void tick() { super.tick(); + if (skipCooling > 0) + skipCooling--; + if (referredToByTag != null) { for (int i = 0; i < scenes.size(); i++) { PonderScene ponderScene = scenes.get(i); @@ -222,7 +226,8 @@ public class PonderUI extends AbstractSimiScreen { PonderScene activeScene = scenes.get(index); if (!identifyMode) { ponderTicks++; - activeScene.tick(); + if (skipCooling == 0) + activeScene.tick(); } lazyIndex.tickChaser(); fadeIn.tickChaser(); @@ -247,6 +252,8 @@ public class PonderUI extends AbstractSimiScreen { replay(); getActiveScene().seekToTime(time); + if (time != 0) + coolDownAfterSkip(); } public void updateIdentifiedItem(PonderScene activeScene) { @@ -312,7 +319,8 @@ public class PonderUI extends AbstractSimiScreen { @Override protected void renderWindow(int mouseX, int mouseY, float partialTicks) { RenderSystem.enableBlend(); - renderVisibleScenes(mouseX, mouseY, identifyMode ? ponderPartialTicksPaused : partialTicks); + renderVisibleScenes(mouseX, mouseY, + skipCooling > 0 ? 0 : identifyMode ? ponderPartialTicksPaused : partialTicks); renderWidgets(mouseX, mouseY, identifyMode ? ponderPartialTicksPaused : partialTicks); } @@ -362,7 +370,7 @@ public class PonderUI extends AbstractSimiScreen { for (int f = 0; f < 4; f++) { RenderSystem.translated(story.basePlateSize, 0, 0); RenderSystem.pushMatrix(); - RenderSystem.translated(0, 0, 1/1024f); + RenderSystem.translated(0, 0, 1 / 1024f); GuiUtils.drawGradientRect(0, 0, 0, -story.basePlateSize, 4, 0x66_000000, 0x00_000000); RenderSystem.popMatrix(); RenderSystem.rotatef(-90, 0, 1, 0); @@ -480,7 +488,7 @@ public class PonderUI extends AbstractSimiScreen { } if (identifyMode) { - if (noWidgetsHovered) { + if (noWidgetsHovered && mouseY < height - 80) { RenderSystem.pushMatrix(); RenderSystem.translated(mouseX, mouseY, 100); if (hoveredTooltipItem.isEmpty()) { @@ -518,11 +526,12 @@ public class PonderUI extends AbstractSimiScreen { { // Scene overlay + float scenePT = skipCooling > 0 ? 0 : partialTicks; RenderSystem.pushMatrix(); RenderSystem.translated(0, 0, 100); - renderOverlay(index, partialTicks); + renderOverlay(index, scenePT); if (indexDiff > 1 / 512f) - renderOverlay(lazyIndexValue < index ? index - 1 : index + 1, partialTicks); + renderOverlay(lazyIndexValue < index ? index - 1 : index + 1, scenePT); RenderSystem.popMatrix(); } @@ -841,4 +850,8 @@ public class PonderUI extends AbstractSimiScreen { return true; } + public void coolDownAfterSkip() { + skipCooling = 15; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java index fa463b3cc..2190daabf 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java @@ -203,6 +203,22 @@ public class SceneBuilder { addInstruction(new RotateSceneInstruction(0, degrees, true)); } + /** + * Adds a Key Frame at the end of the last delay() instruction for the users to + * skip to + */ + public void addKeyframe() { + addInstruction(KeyframeInstruction.IMMEDIATE); + } + + /** + * Adds a Key Frame a couple ticks after the last delay() instruction for the + * users to skip to + */ + public void addLazyKeyframe() { + addInstruction(KeyframeInstruction.DELAYED); + } + public class EffectInstructions { public void emitParticles(Vec3d location, Emitter emitter, float amountPerCycle, int cycles) { @@ -349,10 +365,6 @@ public class SceneBuilder { addInstruction(AnimateParrotInstruction.move(link, offset, duration)); } - public void addKeyframe() { - addInstruction(KeyframeInstruction.INSTANCE); - } - } public class WorldInstructions { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java index bdda5d67a..ea37f82ae 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/GantryScenes.java @@ -27,7 +27,7 @@ public class GantryScenes { String id = "gantry_" + (pinion ? "carriage" : "shaft"); String title = "Using Gantry " + (pinion ? "Carriages" : "Shafts"); scene.title(id, title); - + scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -2 * f); scene.configureBasePlate(0, 0, 5); scene.world.showSection(util.select.layer(0), Direction.UP); @@ -46,10 +46,9 @@ public class GantryScenes { : "Gantry Shafts form the basis of a gantry setup. Attached Carriages will move along them."; scene.overlay.showText(80) + .attachKeyFrame() .text(text) .pointAt(util.vector.centerOf(centralShaft)); - - scene.special.addKeyframe(); scene.idle(80); scene.world.hideIndependentSection(gantry, Direction.UP); @@ -58,10 +57,10 @@ public class GantryScenes { Vec3d gantryTop = util.vector.topOf(4, 2, 2); scene.world.modifyKineticSpeed(util.select.everywhere(), f -> 0f); scene.overlay.showText(40) + .attachKeyFrame() .text("Gantry setups can move attached Blocks.") .pointAt(gantryTop) .placeNearTarget(); - scene.special.addKeyframe(); scene.idle(30); Selection planks = util.select.position(5, 3, 1); @@ -75,12 +74,11 @@ public class GantryScenes { scene.idle(20); scene.overlay.showText(80) + .attachKeyFrame() .sharedText("movement_anchors") .pointAt(gantryTop) .placeNearTarget(); - scene.special.addKeyframe(); scene.idle(80); - scene.special.addKeyframe(); scene.world.modifyKineticSpeed(util.select.layer(0), f -> 32f); scene.world.modifyKineticSpeed(util.select.layer(1), f -> -64f); @@ -122,12 +120,12 @@ public class GantryScenes { BlockPos cogPos = util.grid.at(1, 2, 1); scene.overlay.showText(60) + .attachKeyFrame() .colored(PonderPalette.RED) .pointAt(util.vector.centerOf(cogPos.down() .south())) .text("Redstone-powered gantry shafts stop moving their carriages") .placeNearTarget(); - scene.special.addKeyframe(); scene.idle(70); Selection cogSelection = util.select.position(cogPos); @@ -171,10 +169,10 @@ public class GantryScenes { scene.world.moveSection(gantry2, util.vector.of(-1, 0, 0), 20); scene.overlay.showText(80) + .attachKeyFrame() .text("The movement direction of carriages depend on their shafts' orientation") .pointAt(util.vector.topOf(1, 1, 3)) .placeNearTarget(); - scene.special.addKeyframe(); scene.idle(80); BlockPos lastShaft = util.grid.at(0, 1, 2); @@ -192,10 +190,10 @@ public class GantryScenes { if (i == 0) { scene.overlay.showText(80) + .attachKeyFrame() .text("...as well as the rotation direction of the shaft") .pointAt(util.vector.blockSurface(lastShaft, Direction.WEST)) .placeNearTarget(); - scene.special.addKeyframe(); } scene.idle(30); @@ -221,10 +219,10 @@ public class GantryScenes { scene.idle(20); scene.overlay.showText(120) + .attachKeyFrame() .text("Same rules apply for the propagated rotation") .pointAt(util.vector.topOf(0, 3, 3)) .placeNearTarget(); - scene.special.addKeyframe(); scene.idle(20); for (boolean flip2 : Iterate.trueAndFalse) { @@ -268,9 +266,9 @@ public class GantryScenes { scene.world.moveSection(gantry, util.vector.of(0, 2, 0), 40); scene.overlay.showText(60) + .attachKeyFrame() .text("Gantry shafts attach to a carriage without the need of super glue") .independent(20); - scene.special.addKeyframe(); scene.idle(40); scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); @@ -281,9 +279,9 @@ public class GantryScenes { scene.world.showIndependentSection(util.select.position(gantryPos2), Direction.DOWN); scene.idle(15); scene.overlay.showText(60) + .attachKeyFrame() .text("Same applies for carriages on moved Gantry Shafts") .independent(20); - scene.special.addKeyframe(); scene.idle(15); scene.world.moveSection(gantry, util.vector.of(0, 2, 0), 40); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java index 0afd83aee..615169fee 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java @@ -71,6 +71,11 @@ public class TextWindowElement extends AnimatedOverlayElement { return this; } + public Builder attachKeyFrame() { + scene.builder().addLazyKeyframe(); + return this; + } + } @Override diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/KeyframeInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/KeyframeInstruction.java index 1330c0fdb..8bc6ea00a 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/KeyframeInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/KeyframeInstruction.java @@ -5,9 +5,14 @@ import com.simibubi.create.foundation.ponder.PonderScene; public class KeyframeInstruction extends PonderInstruction { - public static final KeyframeInstruction INSTANCE = new KeyframeInstruction(); + public static final KeyframeInstruction IMMEDIATE = new KeyframeInstruction(false); + public static final KeyframeInstruction DELAYED = new KeyframeInstruction(true); + + private boolean delayed; - private KeyframeInstruction() { } + private KeyframeInstruction(boolean delayed) { + this.delayed = delayed; + } @Override public boolean isComplete() { @@ -19,6 +24,6 @@ public class KeyframeInstruction extends PonderInstruction { @Override public void onScheduled(PonderScene scene) { - scene.markKeyframe(); + scene.markKeyframe(delayed ? 6 : 0); } }