Pondering about Mechanical Bearings

This commit is contained in:
simibubi 2021-03-10 19:18:25 +01:00
parent 2ddf57cd76
commit d8ab00b66e
11 changed files with 345 additions and 21 deletions

View file

@ -602,6 +602,10 @@ public class PonderUI extends AbstractSimiScreen {
return true;
}
if (hasShiftDown())
clipboardHelper.setClipboardString(handle, "util.select.position(" + hoveredBlockPos.getX() + ", "
+ hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")");
else
clipboardHelper.setClipboardString(handle, "util.grid.at(" + hoveredBlockPos.getX() + ", "
+ hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")");
copiedBlockPos = hoveredBlockPos;

View file

@ -34,6 +34,7 @@ import com.simibubi.create.foundation.ponder.instructions.DisplayWorldSectionIns
import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction;
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;
@ -284,6 +285,15 @@ public class SceneBuilder {
addInstruction(new ChaseAABBInstruction(color, slot, boundingBox, duration));
}
public void showCenteredScrollInput(BlockPos pos, Direction side, int duration) {
Axis axis = side.getAxis();
float s = 1 / 16f;
float q = 1 / 4f;
Vec3d expands = new Vec3d(axis == Axis.X ? s : q, axis == Axis.Y ? s : q, axis == Axis.Z ? s : q);
addInstruction(new HighlightValueBoxInstruction(scene.getSceneBuildingUtil().vector.blockSurface(pos, side),
expands, duration));
}
public void showLine(PonderPalette color, Vec3d start, Vec3d end, int duration) {
addInstruction(new LineInstruction(color, start, end, duration));
}
@ -350,6 +360,12 @@ public class SceneBuilder {
Optional.of(() -> scene.resolve(link))));
}
public void glueBlockOnto(BlockPos position, Direction fadeInDirection, ElementLink<WorldSectionElement> link) {
addInstruction(new DisplayWorldSectionInstruction(15, fadeInDirection,
scene.getSceneBuildingUtil().select.position(position), Optional.of(() -> scene.resolve(link)),
position));
}
public ElementLink<WorldSectionElement> showIndependentSection(Selection selection, Direction fadeInDirection) {
DisplayWorldSectionInstruction instruction =
new DisplayWorldSectionInstruction(15, fadeInDirection, selection, Optional.empty());
@ -405,6 +421,11 @@ public class SceneBuilder {
.setCenterOfRotation(anchor));
}
public void configureStabilization(ElementLink<WorldSectionElement> link, Vec3d anchor) {
addInstruction(scene -> scene.resolve(link)
.stabilizeRotation(anchor));
}
public void moveSection(ElementLink<WorldSectionElement> link, Vec3d offset, int duration) {
addInstruction(AnimateWorldSectionInstruction.move(link, offset, duration));
}
@ -596,8 +617,7 @@ public class SceneBuilder {
modifyTileNBT(selection, teType, consumer, false);
}
public <T extends TileEntity> void modifyTileEntity(BlockPos position, Class<T> teType,
Consumer<T> consumer) {
public <T extends TileEntity> void modifyTileEntity(BlockPos position, Class<T> teType, Consumer<T> consumer) {
addInstruction(scene -> {
TileEntity tileEntity = scene.world.getTileEntity(position);
if (teType.isInstance(tileEntity))

View file

@ -14,7 +14,6 @@ import com.simibubi.create.foundation.utility.Pointing;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -102,7 +101,7 @@ public class BearingScenes {
scene.overlay.showText(60)
.pointAt(util.vector.topOf(windmill))
.placeNearTarget()
.text("Once Activated, the Windmill Bearing will start providing Rotational Force");
.text("Activated with Right-Click, the Windmill Bearing will start providing Rotational Force");
scene.idle(70);
scene.overlay.showText(60)
@ -113,19 +112,14 @@ public class BearingScenes {
scene.idle(90);
Vec3d surface = util.vector.blockSurface(windmill, Direction.WEST);
AxisAlignedBB point = new AxisAlignedBB(surface, surface);
AxisAlignedBB expanded = point.grow(1 / 16f, 1 / 4f, 1 / 4f);
scene.overlay.showControls(new InputWindowElement(surface, Pointing.DOWN).scroll()
.withWrench(), 60);
scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, point, point, 1);
scene.idle(1);
scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, point, expanded, 50);
scene.overlay.showCenteredScrollInput(windmill, Direction.WEST, 50);
scene.overlay.showText(60)
.pointAt(surface)
.placeNearTarget()
.text("Use a Wrench to configure its rotation direction");
scene.idle(35);
scene.idle(36);
scene.world.rotateBearing(windmill, -90 - 45, 75);
scene.world.rotateSection(structure, 0, 0, -90 - 45, 75);
@ -186,13 +180,241 @@ public class BearingScenes {
new InputWindowElement(util.vector.blockSurface(bearingPos, Direction.WEST), Pointing.LEFT).rightClick(),
40);
scene.idle(7);
scene.markAsFinished();
scene.world.rotateBearing(bearingPos, -720, 400);
scene.world.rotateSection(contraption, 0, -720, 0, 400);
scene.world.modifyTileEntity(util.grid.at(2, 1, 5), HarvesterTileEntity.class,
hte -> hte.setAnimatedSpeed(-150));
scene.markAsFinished();
scene.idle(400);
scene.world.modifyTileEntity(util.grid.at(2, 1, 5), HarvesterTileEntity.class, hte -> hte.setAnimatedSpeed(0));
}
public static void mechanicalBearing(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("mechanical_bearing", "Movings Structures using the Mechanical Bearing");
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
scene.world.showSection(util.select.layer(1), Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.layer(2), Direction.DOWN);
scene.idle(10);
Selection cog1 = util.select.position(6, 0, 4);
Selection cog2 = util.select.position(5, 1, 4);
Selection cog3 = util.select.position(4, 1, 3);
Selection cog4 = util.select.position(3, 1, 3);
Selection all = cog1.copy()
.add(cog2)
.add(cog3)
.add(cog4);
BlockPos bearingPos = util.grid.at(3, 2, 3);
scene.overlay.showSelectionWithText(util.select.position(bearingPos.up()), 60)
.colored(PonderPalette.GREEN)
.pointAt(util.vector.blockSurface(bearingPos, Direction.WEST))
.placeNearTarget()
.text("Mechanical Bearings attach to the block in front of them");
scene.idle(50);
ElementLink<WorldSectionElement> plank = scene.world.showIndependentSection(util.select.position(bearingPos.up()
.east()
.north()), Direction.DOWN);
scene.world.moveSection(plank, util.vector.of(-1, 0, 1), 0);
scene.idle(20);
scene.world.setKineticSpeed(cog1, -8);
scene.world.setKineticSpeed(cog2, 8);
scene.world.setKineticSpeed(cog3, -16);
scene.world.setKineticSpeed(cog4, 16);
scene.effects.rotationSpeedIndicator(bearingPos.down());
scene.world.rotateBearing(bearingPos, 360, 37 * 2);
scene.world.rotateSection(plank, 0, 360, 0, 37 * 2);
scene.overlay.showText(80)
.pointAt(util.vector.topOf(bearingPos.up()))
.placeNearTarget()
.text("Upon receiving Rotational Force, it will assemble it into a Rotating Contraption");
scene.idle(37 * 2);
scene.world.setKineticSpeed(all, 0);
scene.idle(20);
scene.world.hideIndependentSection(plank, Direction.UP);
scene.idle(15);
Selection plank2 = util.select.position(4, 3, 2);
ElementLink<WorldSectionElement> contraption = scene.world.showIndependentSection(util.select.layersFrom(3)
.substract(plank2), Direction.DOWN);
scene.idle(10);
scene.world.showSectionAndMerge(plank2, Direction.SOUTH, contraption);
scene.idle(15);
scene.effects.superGlue(util.grid.at(4, 3, 2), Direction.SOUTH, true);
scene.idle(5);
scene.world.configureCenterOfRotation(contraption, util.vector.topOf(bearingPos));
scene.world.setKineticSpeed(cog1, -8);
scene.world.setKineticSpeed(cog2, 8);
scene.world.setKineticSpeed(cog3, -16);
scene.world.setKineticSpeed(cog4, 16);
scene.effects.rotationSpeedIndicator(bearingPos.down());
scene.world.rotateBearing(bearingPos, 360 * 2, 37 * 4);
scene.world.rotateSection(contraption, 0, 360 * 2, 0, 37 * 4);
scene.overlay.showText(120)
.pointAt(util.vector.topOf(bearingPos.up()))
.placeNearTarget()
.sharedText("movement_anchors");
scene.idle(37 * 4);
scene.world.setKineticSpeed(all, 0);
}
public static void bearingModes(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("bearing_modes", "Movement Modes of the Mechanical Bearing");
Selection sideCog = util.select.position(util.grid.at(7, 0, 3));
Selection cogColumn = util.select.fromTo(6, 1, 3, 6, 4, 3);
Selection cogAndClutch = util.select.fromTo(5, 3, 1, 5, 4, 2);
BlockPos leverPos = util.grid.at(5, 3, 1);
scene.world.setKineticSpeed(sideCog, 4);
scene.world.setKineticSpeed(cogColumn, -4);
scene.world.setKineticSpeed(cogAndClutch, 8);
scene.world.toggleRedstonePower(cogAndClutch);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
scene.world.showSection(cogColumn, Direction.DOWN);
scene.idle(5);
scene.world.showSection(cogAndClutch, Direction.DOWN);
scene.idle(10);
BlockPos bearingPos = util.grid.at(5, 2, 2);
scene.world.showSection(util.select.position(bearingPos), Direction.UP);
scene.idle(10);
ElementLink<WorldSectionElement> contraption =
scene.world.showIndependentSection(util.select.fromTo(5, 1, 2, 2, 1, 2), Direction.EAST);
scene.world.configureCenterOfRotation(contraption, util.vector.centerOf(bearingPos));
scene.idle(20);
scene.world.toggleRedstonePower(cogAndClutch);
scene.effects.indicateRedstone(leverPos);
scene.world.rotateSection(contraption, 0, 55, 0, 23);
scene.world.rotateBearing(bearingPos, 55, 23);
scene.idle(24);
scene.world.toggleRedstonePower(cogAndClutch);
scene.effects.indicateRedstone(leverPos);
scene.world.rotateSection(contraption, 0, 35, 0, 0);
scene.world.rotateBearing(bearingPos, 35, 0);
Vec3d target = util.vector.topOf(bearingPos.down());
scene.overlay.showLine(PonderPalette.RED, target.add(-2.5, 0, 3.5), target, 50);
scene.overlay.showLine(PonderPalette.GREEN, target.add(0, 0, 4.5), target, 50);
scene.idle(50);
scene.overlay.showText(100)
.pointAt(util.vector.blockSurface(bearingPos, Direction.WEST))
.placeNearTarget()
.colored(PonderPalette.RED)
.text("When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle");
scene.idle(110);
scene.overlay.showCenteredScrollInput(bearingPos, Direction.NORTH, 60);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(bearingPos, Direction.NORTH), Pointing.DOWN).scroll()
.withWrench(),
60);
scene.idle(10);
scene.overlay.showText(60)
.pointAt(util.vector.blockSurface(bearingPos, Direction.WEST))
.placeNearTarget()
.text("This behaviour can be modified using a Wrench");
scene.idle(70);
scene.world.toggleRedstonePower(cogAndClutch);
scene.effects.indicateRedstone(leverPos);
scene.world.rotateSection(contraption, 0, -55, 0, 23);
scene.world.rotateBearing(bearingPos, -55, 23);
scene.idle(24);
scene.world.toggleRedstonePower(cogAndClutch);
scene.effects.indicateRedstone(leverPos);
scene.idle(40);
scene.overlay.showText(120)
.colored(PonderPalette.GREEN)
.pointAt(util.vector.blockSurface(util.grid.at(3, 1, 3), Direction.UP))
.placeNearTarget()
.text("It can be configured never to revert to solid blocks, or only near the angle it started at");
}
public static void stabilizedBearings(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("stabilized_bearings", "Stabilized Contraptions");
Selection beltAndBearing = util.select.fromTo(3, 3, 4, 3, 1, 6);
Selection largeCog = util.select.position(2, 0, 6);
BlockPos parentBearingPos = util.grid.at(3, 3, 4);
BlockPos bearingPos = util.grid.at(3, 4, 2);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
scene.world.showSection(beltAndBearing, Direction.DOWN);
scene.idle(10);
ElementLink<WorldSectionElement> contraption =
scene.world.showIndependentSection(util.select.fromTo(3, 3, 3, 3, 4, 3), Direction.SOUTH);
scene.world.configureCenterOfRotation(contraption, util.vector.centerOf(parentBearingPos));
scene.idle(20);
scene.world.glueBlockOnto(bearingPos, Direction.SOUTH, contraption);
scene.idle(15);
scene.overlay.showSelectionWithText(util.select.position(bearingPos), 60)
.text("Whenever Mechanical Bearings are themselves part of a moving Structure..")
.placeNearTarget();
scene.idle(70);
scene.world.setKineticSpeed(largeCog, -8);
scene.world.setKineticSpeed(beltAndBearing, 16);
scene.world.rotateBearing(parentBearingPos, 360, 74);
scene.world.rotateSection(contraption, 0, 0, 360, 74);
scene.world.rotateBearing(bearingPos, -360, 74);
scene.idle(74);
scene.world.setKineticSpeed(largeCog, 0);
scene.world.setKineticSpeed(beltAndBearing, 0);
scene.overlay.showText(60)
.text("..they will attempt to keep themselves upright")
.pointAt(util.vector.blockSurface(bearingPos, Direction.NORTH))
.placeNearTarget();
scene.idle(70);
scene.overlay.showSelectionWithText(util.select.position(bearingPos.north()), 60)
.colored(PonderPalette.GREEN)
.text("Once again, the bearing will attach to the block in front of it")
.placeNearTarget();
scene.idle(70);
ElementLink<WorldSectionElement> subContraption =
scene.world.showIndependentSection(util.select.fromTo(4, 4, 1, 2, 4, 1), Direction.SOUTH);
scene.world.configureCenterOfRotation(subContraption, util.vector.centerOf(parentBearingPos));
scene.world.configureStabilization(subContraption, util.vector.centerOf(bearingPos));
scene.idle(20);
scene.overlay.showText(80)
.text("As a result, the entire sub-Contraption will stay upright");
scene.world.setKineticSpeed(largeCog, -8);
scene.world.setKineticSpeed(beltAndBearing, 16);
scene.world.rotateBearing(parentBearingPos, 360 * 2, 74 * 2);
scene.world.rotateSection(contraption, 0, 0, 360 * 2, 74 * 2);
scene.world.rotateBearing(bearingPos, -360 * 2, 74 * 2);
scene.world.rotateSection(subContraption, 0, 0, 360 * 2, 74 * 2);
scene.markAsFinished();
scene.idle(74 * 2);
scene.world.setKineticSpeed(largeCog, 0);
scene.world.setKineticSpeed(beltAndBearing, 0);
}
}

View file

@ -83,6 +83,14 @@ public class PonderIndex {
.addStoryBoard("windmill_bearing/structure", BearingScenes::windmillsAnyStructure,
PonderTag.MOVEMENT_ANCHOR);
// Mechanical Bearing
PonderRegistry.forComponents(AllBlocks.MECHANICAL_BEARING)
.addStoryBoard("mechanical_bearing/anchor", BearingScenes::mechanicalBearing, PonderTag.KINETIC_APPLIANCES,
PonderTag.MOVEMENT_ANCHOR)
.addStoryBoard("mechanical_bearing/modes", BearingScenes::bearingModes)
.addStoryBoard("mechanical_bearing/stabilized", BearingScenes::stabilizedBearings,
PonderTag.CONTRAPTION_ACTOR);
// Gantries
PonderRegistry.addStoryBoard(AllBlocks.GANTRY_SHAFT, "gantry/intro", GantryScenes::introForShaft,
PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR);

View file

@ -64,6 +64,7 @@ public class WorldSectionElement extends AnimatedSceneElement {
Vec3d prevAnimatedRotation = Vec3d.ZERO;
Vec3d animatedRotation = Vec3d.ZERO;
Vec3d centerOfRotation = Vec3d.ZERO;
Vec3d stabilizationAnchor = null;
BlockPos selectedBlock;
@ -103,6 +104,10 @@ public class WorldSectionElement extends AnimatedSceneElement {
centerOfRotation = center;
}
public void stabilizeRotation(Vec3d anchor) {
stabilizationAnchor = anchor;
}
@Override
public void reset(PonderScene scene) {
super.reset(scene);
@ -194,11 +199,21 @@ public class WorldSectionElement extends AnimatedSceneElement {
if (!animatedRotation.equals(Vec3d.ZERO) || !prevAnimatedRotation.equals(Vec3d.ZERO)) {
if (centerOfRotation == null)
centerOfRotation = section.getCenter();
double rotX = MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x);
double rotZ = MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z);
double rotY = MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y);
in = in.subtract(centerOfRotation);
in = VecHelper.rotate(in, -MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x), Axis.X);
in = VecHelper.rotate(in, -MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z), Axis.Z);
in = VecHelper.rotate(in, -MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y), Axis.Y);
in = VecHelper.rotate(in, -rotX, Axis.X);
in = VecHelper.rotate(in, -rotZ, Axis.Z);
in = VecHelper.rotate(in, -rotY, Axis.Y);
in = in.add(centerOfRotation);
if (stabilizationAnchor != null) {
in = in.subtract(stabilizationAnchor);
in = VecHelper.rotate(in, rotX, Axis.X);
in = VecHelper.rotate(in, rotZ, Axis.Z);
in = VecHelper.rotate(in, rotY, Axis.Y);
in = in.add(stabilizationAnchor);
}
}
return in;
}
@ -209,12 +224,23 @@ public class WorldSectionElement extends AnimatedSceneElement {
if (!animatedRotation.equals(Vec3d.ZERO) || !prevAnimatedRotation.equals(Vec3d.ZERO)) {
if (centerOfRotation == null)
centerOfRotation = section.getCenter();
double rotX = MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x);
double rotZ = MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z);
double rotY = MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y);
MatrixStacker.of(ms)
.translate(centerOfRotation)
.rotateX(MathHelper.lerp(pt, prevAnimatedRotation.x, animatedRotation.x))
.rotateZ(MathHelper.lerp(pt, prevAnimatedRotation.z, animatedRotation.z))
.rotateY(MathHelper.lerp(pt, prevAnimatedRotation.y, animatedRotation.y))
.rotateX(rotX)
.rotateZ(rotZ)
.rotateY(rotY)
.translateBack(centerOfRotation);
if (stabilizationAnchor != null) {
MatrixStacker.of(ms)
.translate(stabilizationAnchor)
.rotateX(-rotX)
.rotateZ(-rotZ)
.rotateY(-rotY)
.translateBack(stabilizationAnchor);
}
}
}

View file

@ -3,22 +3,33 @@ package com.simibubi.create.foundation.ponder.instructions;
import java.util.Optional;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem;
import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.Selection;
import com.simibubi.create.foundation.ponder.elements.WorldSectionElement;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public class DisplayWorldSectionInstruction extends FadeIntoSceneInstruction<WorldSectionElement> {
private Selection initialSelection;
private Optional<Supplier<WorldSectionElement>> mergeOnto;
private BlockPos glue;
public DisplayWorldSectionInstruction(int fadeInTicks, Direction fadeInFrom, Selection selection,
Optional<Supplier<WorldSectionElement>> mergeOnto) {
this(fadeInTicks, fadeInFrom, selection, mergeOnto, null);
}
public DisplayWorldSectionInstruction(int fadeInTicks, Direction fadeInFrom, Selection selection,
Optional<Supplier<WorldSectionElement>> mergeOnto, @Nullable BlockPos glue) {
super(fadeInTicks, fadeInFrom, new WorldSectionElement(selection));
initialSelection = selection;
this.mergeOnto = mergeOnto;
this.glue = glue;
}
@Override
@ -34,6 +45,8 @@ public class DisplayWorldSectionInstruction extends FadeIntoSceneInstruction<Wor
if (remainingTicks > 0)
return;
mergeOnto.ifPresent(c -> element.mergeOnto(c.get()));
if (glue != null)
SuperGlueItem.spawnParticles(scene.getWorld(), glue, fadeInFrom, true);
}
@Override

View file

@ -9,7 +9,7 @@ import net.minecraft.util.math.Vec3d;
public abstract class FadeIntoSceneInstruction<T extends AnimatedSceneElement> extends TickingInstruction {
private Direction fadeInFrom;
protected Direction fadeInFrom;
protected T element;
private ElementLink<T> elementLink;

View file

@ -0,0 +1,31 @@
package com.simibubi.create.foundation.ponder.instructions;
import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.content.PonderPalette;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
public class HighlightValueBoxInstruction extends TickingInstruction {
private Vec3d vec;
private Vec3d expands;
public HighlightValueBoxInstruction(Vec3d vec, Vec3d expands, int duration) {
super(false, duration);
this.vec = vec;
this.expands = expands;
}
@Override
public void tick(PonderScene scene) {
super.tick(scene);
AxisAlignedBB point = new AxisAlignedBB(vec, vec);
AxisAlignedBB expanded = point.grow(expands.x, expands.y, expands.z);
scene.getOutliner()
.chaseAABB(vec, remainingTicks == totalTicks ? point : expanded)
.lineWidth(1 / 32f)
.colored(PonderPalette.WHITE.getColor());
}
}

Binary file not shown.