Pondering back and forth.

- Only about gantries so far.
 - Reduce Backend log spam.
This commit is contained in:
JozsefA 2021-03-11 15:59:26 -08:00
parent ea90196250
commit f9eb4dd2e7
9 changed files with 238 additions and 44 deletions

View file

@ -0,0 +1,150 @@
package com.simibubi.create.foundation.ponder;
import com.mojang.blaze3d.systems.RenderSystem;
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.audio.SoundHandler;
import net.minecraftforge.fml.client.gui.GuiUtils;
import org.antlr.v4.runtime.misc.IntegerList;
public class PonderProgressBar extends AbstractSimiWidget {
LerpedFloat progress;
LerpedFloat flash;
PonderUI ponder;
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);
}
public void tick() {
progress.chase(ponder.getActiveScene().getSceneProgress(), .5f, LerpedFloat.Chaser.EXP);
progress.tickChaser();
if (isHovered)
flash();
}
public void flash() {
float value = flash.getValue();
flash.setValue(value + (1 - value) * .2f);
}
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
public void onClick(double mouseX, double mouseY) {
PonderScene activeScene = ponder.getActiveScene();
int clickedAtTime = (int) ((mouseX - x) / ((double) width) * activeScene.totalTime);
int seekTime = 0;
IntegerList keyframeTimes = activeScene.keyframeTimes;
for (int i = 0; i < keyframeTimes.size(); i++) {
int keyframeTime = keyframeTimes.get(i);
if (keyframeTime > clickedAtTime)
break;
seekTime = keyframeTime;
}
ponder.seekToTime(seekTime);
}
public int getHoveredKeyframeIndex(double mouseX) {
PonderScene activeScene = ponder.getActiveScene();
int clickedAtTime = (int) ((mouseX - x) / ((double) width) * activeScene.totalTime);
int index = -1;
IntegerList keyframeTimes = activeScene.keyframeTimes;
for (int i = 0; i < keyframeTimes.size(); i++) {
int keyframeTime = keyframeTimes.get(i);
if (keyframeTime > clickedAtTime)
break;
index = i;
}
return index;
}
@Override
public void renderButton(int mouseX, int mouseY, float partialTicks) {
isHovered = clicked(mouseX, mouseY);
PonderUI.renderBox(x, y, width, height, false);
RenderSystem.pushMatrix();
RenderSystem.translated(x - 2, y - 2, 0);
RenderSystem.pushMatrix();
RenderSystem.scaled((width + 4) * progress.getValue(partialTicks), 1, 1);
GuiUtils.drawGradientRect(200, 0, 3, 1, 4, 0x60ffeedd, 0x60ffeedd);
RenderSystem.popMatrix();
renderKeyframes(mouseX, partialTicks);
RenderSystem.popMatrix();
}
private void renderKeyframes(int mouseX, float partialTicks) {
PonderScene activeScene = ponder.getActiveScene();
int hoverStartColor;
int hoverEndColor;
int hoverIndex;
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;
}
IntegerList keyframeTimes = activeScene.keyframeTimes;
for (int i = 0; i < keyframeTimes.size(); i++) {
int keyframeTime = keyframeTimes.get(i);
int startColor = i == hoverIndex ? hoverStartColor : 0x60ffeedd;
int endColor = i == hoverIndex ? hoverEndColor : 0x60ffeedd;
int keyframePos = (int) (((float) keyframeTime) / ((float) activeScene.totalTime) * (width + 4));
GuiUtils.drawGradientRect(200, keyframePos, 1, keyframePos + 1, 4, startColor, endColor);
}
}
@Override
public void playDownSound(SoundHandler handler) {
}
}

View file

@ -13,6 +13,8 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; 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.MutableDouble;
import org.apache.commons.lang3.mutable.MutableObject; import org.apache.commons.lang3.mutable.MutableObject;
@ -59,6 +61,8 @@ public class PonderScene {
int textIndex; int textIndex;
String sceneId; String sceneId;
IntegerList keyframeTimes;
List<PonderInstruction> schedule, activeSchedule; List<PonderInstruction> schedule, activeSchedule;
Map<UUID, PonderElement> linkedElements; Map<UUID, PonderElement> linkedElements;
Set<PonderElement> elements; Set<PonderElement> elements;
@ -102,6 +106,7 @@ public class PonderScene {
info = new SceneRenderInfo(); info = new SceneRenderInfo();
baseWorldSection = new WorldSectionElement(); baseWorldSection = new WorldSectionElement();
renderViewEntity = new ArmorStandEntity(world, 0, 0, 0); renderViewEntity = new ArmorStandEntity(world, 0, 0, 0);
keyframeTimes = new IntegerList(4);
setPointOfInterest(new Vec3d(0, 4, 0)); setPointOfInterest(new Vec3d(0, 4, 0));
} }
@ -180,6 +185,7 @@ public class PonderScene {
world.restore(); world.restore();
elements.clear(); elements.clear();
linkedElements.clear(); linkedElements.clear();
keyframeTimes.clear();
transform = new SceneTransform(); transform = new SceneTransform();
finished = false; finished = false;
@ -270,6 +276,15 @@ public class PonderScene {
finished = true; finished = true;
} }
public void seekToTime(int time) {
if (time < currentTime)
throw new IllegalStateException("Cannot seek backwards. Rewind first.");
while (currentTime < time && !finished) {
tick();
}
}
public void addToSceneTime(int time) { public void addToSceneTime(int time) {
if (!stoppedCounting) if (!stoppedCounting)
totalTime += time; totalTime += time;
@ -279,6 +294,12 @@ public class PonderScene {
stoppedCounting = true; stoppedCounting = true;
} }
public void markKeyframe() {
if (!stoppedCounting) {
keyframeTimes.add(totalTime);
}
}
public void addElement(PonderElement e) { public void addElement(PonderElement e) {
elements.add(e); elements.add(e);
} }

View file

@ -64,7 +64,6 @@ public class PonderUI extends AbstractSimiScreen {
private List<PonderButton> tagButtons; private List<PonderButton> tagButtons;
private List<LerpedFloat> tagFades; private List<LerpedFloat> tagFades;
private LerpedFloat fadeIn; private LerpedFloat fadeIn;
private LerpedFloat sceneProgress;
ItemStack stack; ItemStack stack;
PonderChapter chapter = null; PonderChapter chapter = null;
@ -80,6 +79,7 @@ public class PonderUI extends AbstractSimiScreen {
private PonderTag referredToByTag; private PonderTag referredToByTag;
private PonderButton left, right, scan, chap; private PonderButton left, right, scan, chap;
private PonderProgressBar progressBar;
public static PonderUI of(ItemStack item) { public static PonderUI of(ItemStack item) {
return new PonderUI(PonderRegistry.compile(item.getItem() return new PonderUI(PonderRegistry.compile(item.getItem()
@ -115,8 +115,6 @@ public class PonderUI extends AbstractSimiScreen {
} }
lazyIndex = LerpedFloat.linear() lazyIndex = LerpedFloat.linear()
.startWithValue(index); .startWithValue(index);
sceneProgress = LerpedFloat.linear()
.startWithValue(0);
fadeIn = LerpedFloat.linear() fadeIn = LerpedFloat.linear()
.startWithValue(0) .startWithValue(0)
.chase(1, .1f, Chaser.EXP); .chase(1, .1f, Chaser.EXP);
@ -160,6 +158,11 @@ public class PonderUI extends AbstractSimiScreen {
int bX = (width - 20) / 2 - (70 + 2 * spacing); int bX = (width - 20) / 2 - (70 + 2 * spacing);
int bY = height - 20 - 31; int bY = height - 20 - 31;
int pX = (width / 2) - 110;
int pY = bY + PonderButton.SIZE + 4;
int pW = width - 2 * pX;
widgets.add(progressBar = new PonderProgressBar(this, pX, pY, pW, 1));
widgets.add(scan = new PonderButton(bX, bY, () -> { widgets.add(scan = new PonderButton(bX, bY, () -> {
identifyMode = !identifyMode; identifyMode = !identifyMode;
if (!identifyMode) if (!identifyMode)
@ -188,7 +191,6 @@ public class PonderUI extends AbstractSimiScreen {
widgets.add(new PonderButton(bX, bY, this::replay).showing(AllIcons.I_MTD_REPLAY) widgets.add(new PonderButton(bX, bY, this::replay).showing(AllIcons.I_MTD_REPLAY)
.shortcut(bindings.keyBindBack) .shortcut(bindings.keyBindBack)
.fade(0, -1)); .fade(0, -1));
} }
@Override @Override
@ -217,10 +219,9 @@ public class PonderUI extends AbstractSimiScreen {
PonderScene activeScene = scenes.get(index); PonderScene activeScene = scenes.get(index);
if (!identifyMode) if (!identifyMode)
activeScene.tick(); activeScene.tick();
sceneProgress.chase(activeScene.getSceneProgress(), .5f, Chaser.EXP);
lazyIndex.tickChaser(); lazyIndex.tickChaser();
fadeIn.tickChaser(); fadeIn.tickChaser();
sceneProgress.tickChaser(); progressBar.tick();
if (!identifyMode) { if (!identifyMode) {
float lazyIndexValue = lazyIndex.getValue(); float lazyIndexValue = lazyIndex.getValue();
@ -232,6 +233,17 @@ public class PonderUI extends AbstractSimiScreen {
updateIdentifiedItem(activeScene); updateIdentifiedItem(activeScene);
} }
public PonderScene getActiveScene() {
return scenes.get(index);
}
public void seekToTime(int time) {
if (getActiveScene().currentTime > time)
replay();
getActiveScene().seekToTime(time);
}
public void updateIdentifiedItem(PonderScene activeScene) { public void updateIdentifiedItem(PonderScene activeScene) {
hoveredTooltipItem = ItemStack.EMPTY; hoveredTooltipItem = ItemStack.EMPTY;
hoveredBlockPos = null; hoveredBlockPos = null;
@ -490,18 +502,6 @@ public class PonderUI extends AbstractSimiScreen {
else else
right.dim(); right.dim();
{
int x = (width / 2) - 110;
int y = right.y + right.getHeight() + 4;
int w = width - 2 * x;
renderBox(x, y, w, 1, false);
RenderSystem.pushMatrix();
RenderSystem.translated(x - 2, y - 2, 0);
RenderSystem.scaled((w + 4) * sceneProgress.getValue(partialTicks), 1, 1);
GuiUtils.drawGradientRect(200, 0, 3, 1, 4, 0x60ffeedd, 0x60ffeedd);
RenderSystem.popMatrix();
}
// Tags // Tags
List<PonderTag> sceneTags = activeScene.tags; List<PonderTag> sceneTags = activeScene.tags;
boolean highlightAll = sceneTags.contains(PonderTag.Highlight.ALL); boolean highlightAll = sceneTags.contains(PonderTag.Highlight.ALL);

View file

@ -24,26 +24,8 @@ import com.simibubi.create.foundation.ponder.elements.ParrotElement.ParrotPose;
import com.simibubi.create.foundation.ponder.elements.ParrotElement.SpinOnComponentPose; import com.simibubi.create.foundation.ponder.elements.ParrotElement.SpinOnComponentPose;
import com.simibubi.create.foundation.ponder.elements.TextWindowElement; import com.simibubi.create.foundation.ponder.elements.TextWindowElement;
import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement;
import com.simibubi.create.foundation.ponder.instructions.AnimateParrotInstruction; import com.simibubi.create.foundation.ponder.instructions.*;
import com.simibubi.create.foundation.ponder.instructions.AnimateTileEntityInstruction;
import com.simibubi.create.foundation.ponder.instructions.AnimateWorldSectionInstruction;
import com.simibubi.create.foundation.ponder.instructions.ChaseAABBInstruction;
import com.simibubi.create.foundation.ponder.instructions.CreateParrotInstruction;
import com.simibubi.create.foundation.ponder.instructions.DelayInstruction;
import com.simibubi.create.foundation.ponder.instructions.DisplayWorldSectionInstruction;
import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction;
import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction.Emitter; import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction.Emitter;
import com.simibubi.create.foundation.ponder.instructions.FadeOutOfSceneInstruction;
import com.simibubi.create.foundation.ponder.instructions.HighlightValueBoxInstruction;
import com.simibubi.create.foundation.ponder.instructions.LineInstruction;
import com.simibubi.create.foundation.ponder.instructions.MarkAsFinishedInstruction;
import com.simibubi.create.foundation.ponder.instructions.MovePoiInstruction;
import com.simibubi.create.foundation.ponder.instructions.OutlineSelectionInstruction;
import com.simibubi.create.foundation.ponder.instructions.ReplaceBlocksInstruction;
import com.simibubi.create.foundation.ponder.instructions.RotateSceneInstruction;
import com.simibubi.create.foundation.ponder.instructions.ShowInputInstruction;
import com.simibubi.create.foundation.ponder.instructions.TextInstruction;
import com.simibubi.create.foundation.ponder.instructions.TileEntityDataInstruction;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour;
@ -345,6 +327,10 @@ public class SceneBuilder {
addInstruction(AnimateParrotInstruction.move(link, offset, duration)); addInstruction(AnimateParrotInstruction.move(link, offset, duration));
} }
public void addKeyframe() {
addInstruction(KeyframeInstruction.INSTANCE);
}
} }
public class WorldInstructions { public class WorldInstructions {

View file

@ -48,6 +48,8 @@ public class GantryScenes {
scene.overlay.showText(80) scene.overlay.showText(80)
.text(text) .text(text)
.pointAt(util.vector.centerOf(centralShaft)); .pointAt(util.vector.centerOf(centralShaft));
scene.special.addKeyframe();
scene.idle(80); scene.idle(80);
scene.world.hideIndependentSection(gantry, Direction.UP); scene.world.hideIndependentSection(gantry, Direction.UP);
@ -59,6 +61,7 @@ public class GantryScenes {
.text("Gantry setups can move attached Blocks.") .text("Gantry setups can move attached Blocks.")
.pointAt(gantryTop) .pointAt(gantryTop)
.placeNearTarget(); .placeNearTarget();
scene.special.addKeyframe();
scene.idle(30); scene.idle(30);
Selection planks = util.select.position(5, 3, 1); Selection planks = util.select.position(5, 3, 1);
@ -75,6 +78,7 @@ public class GantryScenes {
.sharedText("movement_anchors") .sharedText("movement_anchors")
.pointAt(gantryTop) .pointAt(gantryTop)
.placeNearTarget(); .placeNearTarget();
scene.special.addKeyframe();
scene.idle(80); scene.idle(80);
scene.world.modifyKineticSpeed(util.select.layer(0), f -> 32f); scene.world.modifyKineticSpeed(util.select.layer(0), f -> 32f);
@ -107,6 +111,7 @@ public class GantryScenes {
scene.idle(15); scene.idle(15);
scene.world.moveSection(gantry, util.vector.of(-3, 0, 0), 40); scene.world.moveSection(gantry, util.vector.of(-3, 0, 0), 40);
scene.idle(40); scene.idle(40);
scene.special.addKeyframe();
scene.world.toggleRedstonePower(shaft); scene.world.toggleRedstonePower(shaft);
scene.world.toggleRedstonePower(util.select.position(3, 1, 0)); scene.world.toggleRedstonePower(util.select.position(3, 1, 0));
@ -122,6 +127,7 @@ public class GantryScenes {
.south())) .south()))
.text("Redstone-powered gantry shafts stop moving their carriages") .text("Redstone-powered gantry shafts stop moving their carriages")
.placeNearTarget(); .placeNearTarget();
scene.special.addKeyframe();
scene.idle(70); scene.idle(70);
Selection cogSelection = util.select.position(cogPos); Selection cogSelection = util.select.position(cogPos);
@ -168,6 +174,7 @@ public class GantryScenes {
.text("The movement direction of carriages depend on their shafts' orientation") .text("The movement direction of carriages depend on their shafts' orientation")
.pointAt(util.vector.topOf(1, 1, 3)) .pointAt(util.vector.topOf(1, 1, 3))
.placeNearTarget(); .placeNearTarget();
scene.special.addKeyframe();
scene.idle(80); scene.idle(80);
BlockPos lastShaft = util.grid.at(0, 1, 2); BlockPos lastShaft = util.grid.at(0, 1, 2);
@ -188,6 +195,7 @@ public class GantryScenes {
.text("...as well as the rotation direction of the shaft") .text("...as well as the rotation direction of the shaft")
.pointAt(util.vector.blockSurface(lastShaft, Direction.WEST)) .pointAt(util.vector.blockSurface(lastShaft, Direction.WEST))
.placeNearTarget(); .placeNearTarget();
scene.special.addKeyframe();
} }
scene.idle(30); scene.idle(30);
@ -216,6 +224,7 @@ public class GantryScenes {
.text("Same rules apply for the propagated rotation") .text("Same rules apply for the propagated rotation")
.pointAt(util.vector.topOf(0, 3, 3)) .pointAt(util.vector.topOf(0, 3, 3))
.placeNearTarget(); .placeNearTarget();
scene.special.addKeyframe();
scene.idle(20); scene.idle(20);
for (boolean flip2 : Iterate.trueAndFalse) { for (boolean flip2 : Iterate.trueAndFalse) {
@ -260,6 +269,7 @@ public class GantryScenes {
scene.overlay.showText(60) scene.overlay.showText(60)
.text("Gantry shafts attach to a carriage without the need of super glue") .text("Gantry shafts attach to a carriage without the need of super glue")
.independent(20); .independent(20);
scene.special.addKeyframe();
scene.idle(40); scene.idle(40);
scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f);
@ -272,6 +282,7 @@ public class GantryScenes {
scene.overlay.showText(60) scene.overlay.showText(60)
.text("Same applies for carriages on moved Gantry Shafts") .text("Same applies for carriages on moved Gantry Shafts")
.independent(20); .independent(20);
scene.special.addKeyframe();
scene.idle(15); scene.idle(15);
scene.world.moveSection(gantry, util.vector.of(0, 2, 0), 40); scene.world.moveSection(gantry, util.vector.of(0, 2, 0), 40);

View file

@ -0,0 +1,24 @@
package com.simibubi.create.foundation.ponder.instructions;
import com.simibubi.create.foundation.ponder.PonderInstruction;
import com.simibubi.create.foundation.ponder.PonderScene;
public class KeyframeInstruction extends PonderInstruction {
public static final KeyframeInstruction INSTANCE = new KeyframeInstruction();
private KeyframeInstruction() { }
@Override
public boolean isComplete() {
return true;
}
@Override
public void tick(PonderScene scene) { }
@Override
public void onScheduled(PonderScene scene) {
scene.markKeyframe();
}
}

View file

@ -122,6 +122,8 @@ public class Backend {
for (ProgramSpec<?> shader : registry.values()) { for (ProgramSpec<?> shader : registry.values()) {
loadProgram(manager, shader); loadProgram(manager, shader);
} }
log.info("Loaded all shader programs.");
} }
} }
} }
@ -140,7 +142,7 @@ public class Backend {
programs.put(programSpec, new ProgramGroup<>(programGroup)); programs.put(programSpec, new ProgramGroup<>(programGroup));
log.info("Loaded program {}", programSpec.name); log.debug("Loaded program {}", programSpec.name);
} catch (IOException ex) { } catch (IOException ex) {
log.error("Failed to load program {}", programSpec.name, ex); log.error("Failed to load program {}", programSpec.name, ex);
return; return;

View file

@ -39,7 +39,7 @@ public abstract class GlProgram extends GlObject {
int index = GL20.glGetUniformLocation(this.handle(), uniform); int index = GL20.glGetUniformLocation(this.handle(), uniform);
if (index < 0 && Backend.SHADER_DEBUG_OUTPUT) { if (index < 0 && Backend.SHADER_DEBUG_OUTPUT) {
Backend.log.warn("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name); Backend.log.debug("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name);
} }
return index; return index;
@ -106,8 +106,8 @@ public abstract class GlProgram extends GlObject {
String log = GL20.glGetProgramInfoLog(this.program); String log = GL20.glGetProgramInfoLog(this.program);
if (!log.isEmpty()) { if (!log.isEmpty() && Backend.SHADER_DEBUG_OUTPUT) {
Backend.log.warn("Program link log for " + this.name + ": " + log); Backend.log.debug("Program link log for " + this.name + ": " + log);
} }
int result = GL20.glGetProgrami(this.program, GL20.GL_LINK_STATUS); int result = GL20.glGetProgrami(this.program, GL20.GL_LINK_STATUS);

View file

@ -21,7 +21,7 @@ public class GlShader extends GlObject {
source = preProcessor.process(source); source = preProcessor.process(source);
if (Backend.SHADER_DEBUG_OUTPUT) if (Backend.SHADER_DEBUG_OUTPUT)
Backend.log.info("Preprocessor run on " + name);// + ":\n" + source); Backend.log.debug("Preprocessor run on " + name);// + ":\n" + source);
} }
GL20.glShaderSource(handle, source); GL20.glShaderSource(handle, source);
@ -30,11 +30,11 @@ public class GlShader extends GlObject {
String log = GL20.glGetShaderInfoLog(handle); String log = GL20.glGetShaderInfoLog(handle);
if (!log.isEmpty()) { if (!log.isEmpty()) {
Backend.log.warn("Shader compilation log for " + name + ": " + log); Backend.log.error("Shader compilation log for " + name + ": " + log);
} }
if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) { if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) {
throw new RuntimeException("Could not compile shader"); throw new RuntimeException("Could not compile shader. See log for details.");
} }
setHandle(handle); setHandle(handle);