Merge remote-tracking branch 'origin/mc1.15/dev' into mc1.15/dev

This commit is contained in:
zelophed 2021-03-11 15:29:40 +01:00
commit 0448d3f6f3
91 changed files with 2568 additions and 500 deletions

View file

@ -16,8 +16,11 @@ import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.A
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
import com.simibubi.create.content.contraptions.relays.belt.BeltData;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -259,4 +262,22 @@ public class AllBlockPartials {
return dispatcher.getMaterial(KineticRenderMaterials.ROTATING).getModel(this, referenceState, facing, ms);
}
public InstancedModel<ModelData> renderOnHorizontalModel(InstancedTileRenderer<?> dispatcher, BlockState referenceState) {
Direction facing = referenceState.get(HORIZONTAL_FACING);
return renderOnDirectionalSouthModel(dispatcher, referenceState, facing);
}
public InstancedModel<ModelData> renderOnDirectionalSouthModel(InstancedTileRenderer<?> dispatcher, BlockState referenceState, Direction facing) {
Supplier<MatrixStack> ms = () -> {
MatrixStack stack = new MatrixStack();
MatrixStacker.of(stack)
.centre()
.rotateY(AngleHelper.horizontalAngle(facing))
.rotateX(AngleHelper.verticalAngle(facing))
.unCentre();
return stack;
};
return dispatcher.getMaterial(RenderMaterials.MODELS).getModel(this, referenceState, facing, ms);
}
}

View file

@ -32,6 +32,7 @@ import com.simibubi.create.content.contraptions.components.fan.NozzleTileEntity;
import com.simibubi.create.content.contraptions.components.flywheel.FlyWheelInstance;
import com.simibubi.create.content.contraptions.components.flywheel.FlywheelRenderer;
import com.simibubi.create.content.contraptions.components.flywheel.FlywheelTileEntity;
import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineInstance;
import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineRenderer;
import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineTileEntity;
import com.simibubi.create.content.contraptions.components.millstone.MillStoneCogInstance;
@ -39,10 +40,12 @@ import com.simibubi.create.content.contraptions.components.millstone.MillstoneRe
import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity;
import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerRenderer;
import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity;
import com.simibubi.create.content.contraptions.components.mixer.MixerInstance;
import com.simibubi.create.content.contraptions.components.motor.CreativeMotorRenderer;
import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressRenderer;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.content.contraptions.components.press.PressInstance;
import com.simibubi.create.content.contraptions.components.saw.SawInstance;
import com.simibubi.create.content.contraptions.components.saw.SawRenderer;
import com.simibubi.create.content.contraptions.components.saw.SawTileEntity;
@ -137,6 +140,7 @@ import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity;
import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkTileEntity;
import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchTileEntity;
import com.simibubi.create.content.schematics.block.SchematicTableTileEntity;
import com.simibubi.create.content.schematics.block.SchematicannonInstance;
import com.simibubi.create.content.schematics.block.SchematicannonRenderer;
import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer;
@ -149,6 +153,7 @@ public class AllTileEntities {
.tileEntity("schematicannon", SchematicannonTileEntity::new)
.validBlocks(AllBlocks.SCHEMATICANNON)
.renderer(() -> SchematicannonRenderer::new)
.onRegister(SchematicannonInstance::register)
.register();
public static final TileEntityEntry<SchematicTableTileEntity> SCHEMATIC_TABLE = Create.registrate()
@ -454,6 +459,7 @@ public class AllTileEntities {
.tileEntity("furnace_engine", FurnaceEngineTileEntity::new)
.validBlocks(AllBlocks.FURNACE_ENGINE)
.renderer(() -> EngineRenderer::new)
.onRegister(EngineInstance::register)
.register();
public static final TileEntityEntry<MillstoneTileEntity> MILLSTONE = Create.registrate()
@ -488,14 +494,14 @@ public class AllTileEntities {
.tileEntity("mechanical_press", MechanicalPressTileEntity::new)
.validBlocks(AllBlocks.MECHANICAL_PRESS)
.renderer(() -> MechanicalPressRenderer::new)
.onRegister(ShaftInstance::register)
.onRegister(PressInstance::register)
.register();
public static final TileEntityEntry<MechanicalMixerTileEntity> MECHANICAL_MIXER = Create.registrate()
.tileEntity("mechanical_mixer", MechanicalMixerTileEntity::new)
.validBlocks(AllBlocks.MECHANICAL_MIXER)
.renderer(() -> MechanicalMixerRenderer::new)
.onRegister(ShaftlessCogInstance::register)
.onRegister(MixerInstance::register)
.register();
public static final TileEntityEntry<DeployerTileEntity> DEPLOYER = Create.registrate()

View file

@ -58,7 +58,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
}
public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) {
float time = AnimationTickHolder.getRenderTime();
float time = AnimationTickHolder.getRenderTime(te.getWorld());
float offset = getRotationOffsetForPosition(te, pos, axis);
float angle = ((time * te.getSpeed() * 3f / 10 + offset) % 360) / 180 * (float) Math.PI;
return angle;

View file

@ -24,6 +24,7 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.LightType;
import net.minecraft.world.World;
public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntity> {
@ -36,7 +37,8 @@ public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntit
int light, int overlay) {
BlockState blockState = te.getBlockState();
SuperByteBuffer superBuffer = AllBlockPartials.HARVESTER_BLADE.renderOn(blockState);
transform(blockState.get(HarvesterBlock.HORIZONTAL_FACING), superBuffer, te.manuallyAnimatedSpeed);
transform(te.getWorld(), blockState.get(HarvesterBlock.HORIZONTAL_FACING), superBuffer,
te.manuallyAnimatedSpeed);
superBuffer.light(light)
.renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped()));
}
@ -70,17 +72,17 @@ public class HarvesterRenderer extends SafeTileEntityRenderer<HarvesterTileEntit
if (context.contraption.stalled)
speed = 0;
transform(facing, superBuffer, speed);
transform(context.world, facing, superBuffer, speed);
superBuffer.light(msLocal.peek()
.getModel(), ContraptionRenderDispatcher.getLightOnContraption(context))
.renderInto(ms, buffers.getBuffer(RenderType.getCutoutMipped()));
}
public static void transform(Direction facing, SuperByteBuffer superBuffer, float speed) {
public static void transform(World world, Direction facing, SuperByteBuffer superBuffer, float speed) {
float originOffset = 1 / 16f;
Vec3d rotOffset = new Vec3d(0, -2 * originOffset, originOffset).add(VecHelper.getCenterOf(BlockPos.ZERO));
float time = AnimationTickHolder.getRenderTime() / 20;
float time = AnimationTickHolder.getRenderTime(world) / 20;
float angle = (time * speed) % 360;
superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing)))

View file

@ -89,7 +89,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer<DeployerTileEntity>
ms.translate(0, isBlockItem ? 9 / 16f : 11 / 16f, 0);
ms.scale(scale, scale, scale);
transform = TransformType.GROUND;
ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AnimationTickHolder.getRenderTime()));
ms.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(AnimationTickHolder.getRenderTime(te.getWorld())));
} else {
float scale = punching ? .75f : isBlockItem ? .75f - 1 / 64f : .5f;

View file

@ -41,7 +41,7 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer {
SuperByteBuffer fanInner =
AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouth(te.getBlockState(), direction.getOpposite());
float time = AnimationTickHolder.getRenderTime();
float time = AnimationTickHolder.getRenderTime(te.getWorld());
float speed = te.getSpeed() * 5;
if (speed > 0)
speed = MathHelper.clamp(speed, 80, 64 * 20);

View file

@ -1,34 +1,59 @@
package com.simibubi.create.content.contraptions.components.flywheel;
import java.util.function.Consumer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileInstance;
import com.simibubi.create.content.contraptions.base.RotatingData;
import com.simibubi.create.foundation.render.backend.instancing.InstanceKey;
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.*;
import net.minecraft.block.BlockState;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.LightType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> {
public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> implements ITickableInstance {
public static void register(TileEntityType<? extends FlywheelTileEntity> type) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
InstancedTileRenderRegistry.instance.register(type, FlyWheelInstance::new));
}
protected Direction facing;
protected boolean connectedLeft;
protected float connectorAngleMult;
protected Direction connection;
protected InstanceKey<RotatingData> shaft;
// protected InstanceKey<RotatingData> wheel;
protected InstanceKey<ModelData> wheel;
protected InstanceKey<ModelData> upperRotating;
protected InstanceKey<ModelData> lowerRotating;
protected InstanceKey<ModelData> upperSliding;
protected InstanceKey<ModelData> lowerSliding;
protected List<InstanceKey<ModelData>> connectors;
protected float lastAngle = Float.NaN;
protected boolean firstFrame = true;
public FlyWheelInstance(InstancedTileRenderer<?> modelManager, FlywheelTileEntity tile) {
super(modelManager, tile);
@ -40,35 +65,154 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> {
Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState);
shaft = setup(shaftModel().createInstance(), tile.getSpeed(), axis);
// wheel = wheelModel().setupInstance(setup);
wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontalModel(modelManager, lastState.rotate(Rotation.CLOCKWISE_90)).createInstance();
connection = FlywheelBlock.getConnection(lastState);
if (connection != null) {
connectedLeft = lastState.get(FlywheelBlock.CONNECTION) == FlywheelBlock.ConnectionState.LEFT;
boolean flipAngle = connection.getAxis() == Direction.Axis.X ^ connection.getAxisDirection() == Direction.AxisDirection.NEGATIVE;
connectorAngleMult = flipAngle ? -1 : 1;
RenderMaterial<?, InstancedModel<ModelData>> mat = modelManager.getMaterial(RenderMaterials.MODELS);
upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, lastState).createInstance();
lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, lastState).createInstance();
upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, lastState).createInstance();
lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, lastState).createInstance();
connectors = Lists.newArrayList(upperRotating, lowerRotating, upperSliding, lowerSliding);
} else {
connectors = Collections.emptyList();
}
updateLight();
firstFrame = true;
}
@Override
public void tick() {
float partialTicks = AnimationTickHolder.getPartialTicks();
float speed = tile.visualSpeed.get(partialTicks) * 3 / 10f;
float angle = tile.angle + speed * partialTicks;
if (!firstFrame && Math.abs(angle - lastAngle) < 0.001) return;
MatrixStack ms = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(ms);
msr.translate(getFloatingPos());
if (connection != null) {
float rotation = angle * connectorAngleMult;
ms.push();
rotateToFacing(msr, connection);
ms.push();
transformConnector(msr, true, true, rotation, connectedLeft);
upperRotating.getInstance().setTransform(ms);
ms.pop();
ms.push();
transformConnector(msr, false, true, rotation, connectedLeft);
lowerRotating.getInstance().setTransform(ms);
ms.pop();
ms.push();
transformConnector(msr, true, false, rotation, connectedLeft);
upperSliding.getInstance().setTransform(ms);
ms.pop();
ms.push();
transformConnector(msr, false, false, rotation, connectedLeft);
lowerSliding.getInstance().setTransform(ms);
ms.pop();
ms.pop();
}
msr.centre()
.rotate(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()), AngleHelper.rad(angle))
.unCentre();
wheel.getInstance().setTransformNoCopy(ms);
lastAngle = angle;
firstFrame = false;
}
@Override
protected void onUpdate() {
Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState);
updateRotation(shaft, axis);
// updateRotation(wheel, axis);
}
@Override
public void updateLight() {
relight(shaft);
// wheel.modifyInstance(this::relight);
int block = world.getLightLevel(LightType.BLOCK, pos);
int sky = world.getLightLevel(LightType.SKY, pos);
shaft.getInstance().setBlockLight(block).setSkyLight(sky);
wheel.getInstance().setBlockLight(block).setSkyLight(sky);
if (connection != null) {
BlockPos pos = this.pos.offset(connection);
int connectionBlock = world.getLightLevel(LightType.BLOCK, pos);
int connectionSky = world.getLightLevel(LightType.SKY, pos);
connectors.stream()
.map(InstanceKey::getInstance)
.forEach(data -> data.setBlockLight(connectionBlock).setSkyLight(connectionSky));
}
}
@Override
public void remove() {
shaft.delete();
// wheel.delete();
// wheel = null;
wheel.delete();
connectors.forEach(InstanceKey::delete);
connectors.clear();
}
protected InstancedModel<RotatingData> shaftModel() {
return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, facing.getOpposite());
}
protected InstancedModel<RotatingData> wheelModel() {
BlockState rotate = lastState.rotate(Rotation.CLOCKWISE_90);
return AllBlockPartials.FLYWHEEL.renderOnDirectionalSouthRotating(modelManager, rotate, rotate.get(BlockStateProperties.HORIZONTAL_FACING));
protected void transformConnector(MatrixStacker ms, boolean upper, boolean rotating, float angle, boolean flip) {
float shift = upper ? 1 / 4f : -1 / 8f;
float offset = upper ? 1 / 4f : 1 / 4f;
float radians = (float) (angle / 180 * Math.PI);
float shifting = MathHelper.sin(radians) * shift + offset;
float maxAngle = upper ? -5 : -15;
float minAngle = upper ? -45 : 5;
float barAngle = 0;
if (rotating)
barAngle = MathHelper.lerp((MathHelper.sin((float) (radians + Math.PI / 2)) + 1) / 2, minAngle, maxAngle);
float pivotX = (upper ? 8f : 3f) / 16;
float pivotY = (upper ? 8f : 2f) / 16;
float pivotZ = (upper ? 23f : 21.5f) / 16f;
ms.translate(pivotX, pivotY, pivotZ + shifting);
if (rotating)
ms.rotate(Direction.EAST, AngleHelper.rad(barAngle));
ms.translate(-pivotX, -pivotY, -pivotZ);
if (flip && !upper)
ms.translate(9 / 16f, 0, 0);
}
protected void rotateToFacing(MatrixStacker buffer, Direction facing) {
buffer.centre()
.rotate(Direction.UP, AngleHelper.rad(AngleHelper.horizontalAngle(facing)))
.unCentre();
}
}

View file

@ -9,6 +9,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock.ConnectionState;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.utility.AngleHelper;
import net.minecraft.block.BlockState;
@ -33,10 +34,11 @@ public class FlywheelRenderer extends KineticTileEntityRenderer {
int light, int overlay) {
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
if (FastRenderDispatcher.available(te.getWorld())) return;
BlockState blockState = te.getBlockState();
FlywheelTileEntity wte = (FlywheelTileEntity) te;
SuperByteBuffer wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontal(blockState.rotate(Rotation.CLOCKWISE_90));
float speed = wte.visualSpeed.get(partialTicks) * 3 / 10f;
float angle = wte.angle + speed * partialTicks;
@ -68,6 +70,7 @@ public class FlywheelRenderer extends KineticTileEntityRenderer {
.renderInto(ms, vb);
}
SuperByteBuffer wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontal(blockState.rotate(Rotation.CLOCKWISE_90));
kineticRotationTransform(wheel, te, blockState.get(HORIZONTAL_FACING)
.getAxis(), AngleHelper.rad(angle), light);
wheel.renderInto(ms, vb);

View file

@ -100,9 +100,4 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
updateGeneratedRotation();
}
}
@Override
public boolean shouldRenderAsTE() {
return true;
}
}

View file

@ -0,0 +1,78 @@
package com.simibubi.create.content.contraptions.components.flywheel.engine;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.InstanceKey;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.block.Block;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
public class EngineInstance extends TileEntityInstance<EngineTileEntity> {
public static void register(TileEntityType<? extends EngineTileEntity> type) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
InstancedTileRenderRegistry.instance.register(type, EngineInstance::new));
}
protected InstanceKey<ModelData> frame;
public EngineInstance(InstancedTileRenderer<?> modelManager, EngineTileEntity tile) {
super(modelManager, tile);
}
@Override
protected void init() {
Block block = lastState
.getBlock();
if (!(block instanceof EngineBlock))
return;
EngineBlock engineBlock = (EngineBlock) block;
AllBlockPartials frame = engineBlock.getFrameModel();
Direction facing = lastState.get(BlockStateProperties.HORIZONTAL_FACING);
this.frame = modelManager.getMaterial(RenderMaterials.MODELS).getModel(frame, lastState).createInstance();
float angle = AngleHelper.rad(AngleHelper.horizontalAngle(facing));
MatrixStack ms = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(ms);
msr.translate(getFloatingPos())
.nudge(tile.hashCode())
.centre()
.rotate(Direction.UP, angle)
.unCentre()
.translate(0, 0, -1);
this.frame.getInstance()
.setTransformNoCopy(ms);
updateLight();
}
@Override
public void remove() {
frame.delete();
}
@Override
public void updateLight() {
int block = world.getLightLevel(LightType.BLOCK, pos);
int sky = world.getLightLevel(LightType.SKY, pos);
frame.getInstance().setBlockLight(block).setSkyLight(sky);
}
}

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper;
@ -21,6 +22,9 @@ public class EngineRenderer<T extends EngineTileEntity> extends SafeTileEntityRe
@Override
protected void renderSafe(T te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light,
int overlay) {
if (FastRenderDispatcher.available(te.getWorld())) return;
Block block = te.getBlockState()
.getBlock();
if (block instanceof EngineBlock) {

View file

@ -3,8 +3,10 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock;
import com.simibubi.create.content.contraptions.components.flywheel.FlywheelTileEntity;
import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -16,8 +18,10 @@ import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import org.apache.http.client.CredentialsProvider;
public class EngineTileEntity extends SmartTileEntity {
public class EngineTileEntity extends SmartTileEntity implements IInstanceRendered {
public float appliedCapacity;
public float appliedSpeed;
@ -100,4 +104,16 @@ public class EngineTileEntity extends SmartTileEntity {
poweredWheel.setRotation(appliedSpeed, appliedCapacity);
}
@Override
public void onChunkLightUpdate() {
CreateClient.kineticRenderer.onLightUpdate(this);
}
@Override
public void initialize() {
super.initialize();
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.add(this));
}
}

View file

@ -31,22 +31,23 @@ public class MechanicalMixerRenderer extends KineticTileEntityRenderer {
@Override
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
int light, int overlay) {
if (FastRenderDispatcher.available(te.getWorld())) return;
BlockState blockState = te.getBlockState();
MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) te;
BlockPos pos = te.getPos();
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
if (!FastRenderDispatcher.available(te.getWorld())) {
SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState);
standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb);
}
SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState);
standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb);
int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, pos);
float renderedHeadOffset = mixer.getRenderedHeadOffset(partialTicks);
float speed = mixer.getRenderedHeadRotationSpeed(partialTicks);
float time = AnimationTickHolder.getRenderTime();
float angle = (float) (((time * speed * 6 / 10f) % 360) / 180 * (float) Math.PI);
float time = AnimationTickHolder.getRenderTime(te.getWorld());
float angle = ((time * speed * 6 / 10f) % 360) / 180 * (float) Math.PI;
SuperByteBuffer poleRender = AllBlockPartials.MECHANICAL_MIXER_POLE.renderOn(blockState);
poleRender.translate(0, -renderedHeadOffset, 0)

View file

@ -0,0 +1,115 @@
package com.simibubi.create.content.contraptions.components.mixer;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.RotatingData;
import com.simibubi.create.content.contraptions.base.ShaftlessCogInstance;
import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.*;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.client.renderer.Vector3d;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.LightType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
public class MixerInstance extends ShaftlessCogInstance implements ITickableInstance {
public static void register(TileEntityType<? extends KineticTileEntity> type) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
InstancedTileRenderRegistry.instance.register(type, MixerInstance::new));
}
private InstanceKey<RotatingData> mixerHead;
private InstanceKey<ModelData> mixerPole;
public MixerInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
super(dispatcher, tile);
}
@Override
protected void init() {
super.init();
mixerHead = rotatingMaterial().getModel(AllBlockPartials.MECHANICAL_MIXER_HEAD, lastState)
.createInstance();
mixerHead.getInstance()
.setRotationAxis(Direction.Axis.Y);
mixerPole = modelManager.getMaterial(RenderMaterials.MODELS)
.getModel(AllBlockPartials.MECHANICAL_MIXER_POLE, lastState)
.createInstance();
MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tile;
float renderedHeadOffset = getRenderedHeadOffset(mixer);
transformPole(renderedHeadOffset);
transformHead(mixer, renderedHeadOffset);
updateLight();
}
@Override
public void tick() {
MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tile;
float renderedHeadOffset = getRenderedHeadOffset(mixer);
if (mixer.running) {
transformPole(renderedHeadOffset);
}
transformHead(mixer, renderedHeadOffset);
}
private void transformHead(MechanicalMixerTileEntity mixer, float renderedHeadOffset) {
float speed = mixer.getRenderedHeadRotationSpeed(AnimationTickHolder.getPartialTicks());
mixerHead.getInstance()
.setPosition(pos)
.nudge(0, -renderedHeadOffset, 0)
.setRotationalSpeed(speed * 2);
}
private void transformPole(float renderedHeadOffset) {
MatrixStack ms = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(ms);
msr.translate(getFloatingPos());
msr.translate(0, -renderedHeadOffset, 0);
mixerPole.getInstance().setTransformNoCopy(ms);
}
private float getRenderedHeadOffset(MechanicalMixerTileEntity mixer) {
return mixer.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks());
}
@Override
public void updateLight() {
super.updateLight();
BlockPos down = pos.down();
mixerHead.getInstance()
.setBlockLight(world.getLightLevel(LightType.BLOCK, down))
.setSkyLight(world.getLightLevel(LightType.SKY, down));
mixerPole.getInstance()
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
}
@Override
public void remove() {
super.remove();
mixerHead.delete();
mixerPole.delete();
}
}

View file

@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.RenderType;
@ -29,13 +30,17 @@ public class MechanicalPressRenderer extends KineticTileEntityRenderer {
int light, int overlay) {
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
if (FastRenderDispatcher.available(te.getWorld())) return;
BlockPos pos = te.getPos();
BlockState blockState = te.getBlockState();
int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, pos);
float renderedHeadOffset = ((MechanicalPressTileEntity) te).getRenderedHeadOffset(partialTicks);
SuperByteBuffer headRender = AllBlockPartials.MECHANICAL_PRESS_HEAD.renderOnHorizontal(blockState);
headRender.translate(0, -renderedHeadOffset, 0).light(packedLightmapCoords).renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
headRender.translate(0, -renderedHeadOffset, 0)
.light(packedLightmapCoords)
.renderInto(ms, buffer.getBuffer(RenderType.getSolid()));
}
@Override

View file

@ -0,0 +1,84 @@
package com.simibubi.create.content.contraptions.components.press;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance;
import com.simibubi.create.foundation.render.backend.instancing.InstanceKey;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.world.LightType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
public class PressInstance extends ShaftInstance implements ITickableInstance {
public static void register(TileEntityType<? extends KineticTileEntity> type) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
InstancedTileRenderRegistry.instance.register(type, PressInstance::new));
}
private InstanceKey<ModelData> pressHead;
public PressInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
super(dispatcher, tile);
}
@Override
protected void init() {
super.init();
pressHead = modelManager.getMaterial(RenderMaterials.MODELS)
.getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, lastState)
.createInstance();
updateLight();
transformModels((MechanicalPressTileEntity) tile);
}
@Override
public void tick() {
MechanicalPressTileEntity press = (MechanicalPressTileEntity) tile;
if (!press.running)
return;
transformModels(press);
}
private void transformModels(MechanicalPressTileEntity press) {
float renderedHeadOffset = getRenderedHeadOffset(press);
MatrixStack ms = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(ms);
msr.translate(getFloatingPos());
msr.translate(0, -renderedHeadOffset, 0);
pressHead.getInstance()
.setTransformNoCopy(ms);
}
private float getRenderedHeadOffset(MechanicalPressTileEntity press) {
return press.getRenderedHeadOffset(AnimationTickHolder.getPartialTicks());
}
@Override
public void updateLight() {
super.updateLight();
pressHead.getInstance()
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
}
@Override
public void remove() {
super.remove();
pressHead.delete();
}
}

View file

@ -20,6 +20,9 @@ import java.util.stream.Collectors;
import javax.annotation.Nullable;
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
import com.simibubi.create.foundation.render.backend.light.GridAlignedBB;
import com.simibubi.create.foundation.utility.*;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
@ -53,12 +56,6 @@ import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.fluid.CombinedTankWrapper;
import com.simibubi.create.foundation.render.backend.light.EmptyLighter;
import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.UniqueLinkedList;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.block.AbstractButtonBlock;
@ -85,7 +82,6 @@ import net.minecraft.state.properties.PistonType;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
@ -853,16 +849,7 @@ public abstract class Contraption {
TileEntity te = TileEntity.create(tag);
if (te == null)
return;
te.setLocation(new WrappedWorld(world) {
@Override
public BlockState getBlockState(BlockPos pos) {
if (!pos.equals(te.getPos()))
return Blocks.AIR.getDefaultState();
return info.state;
}
}, te.getPos());
te.setLocation(new ContraptionTileWorld(world, te, info), te.getPos());
if (te instanceof KineticTileEntity)
((KineticTileEntity) te).setSpeed(0);
te.getBlockState();
@ -1091,27 +1078,25 @@ public abstract class Contraption {
}
public void expandBoundsAroundAxis(Axis axis) {
AxisAlignedBB bb = bounds;
double maxXDiff = Math.max(bb.maxX - 1, -bb.minX);
double maxYDiff = Math.max(bb.maxY - 1, -bb.minY);
double maxZDiff = Math.max(bb.maxZ - 1, -bb.minZ);
double maxDiff = 0;
Set<BlockPos> blocks = getBlocks().keySet();
if (axis == Axis.X)
maxDiff = Math.max(maxZDiff, maxYDiff);
if (axis == Axis.Y)
maxDiff = Math.max(maxZDiff, maxXDiff);
if (axis == Axis.Z)
maxDiff = Math.max(maxXDiff, maxYDiff);
int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis))));
Vec3d vec = new Vec3d(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis)
.getDirectionVec());
Vec3d planeByNormal = VecHelper.axisAlingedPlaneOf(vec);
Vec3d min = vec.mul(bb.minX, bb.minY, bb.minZ)
.add(planeByNormal.scale(-maxDiff));
Vec3d max = vec.mul(bb.maxX, bb.maxY, bb.maxZ)
.add(planeByNormal.scale(maxDiff + 1));
bounds = new AxisAlignedBB(min, max);
GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius);
GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(bounds);
if (axis == Direction.Axis.X) {
betterBounds.maxX = contraptionBounds.maxX;
betterBounds.minX = contraptionBounds.minX;
} else if (axis == Direction.Axis.Y) {
betterBounds.maxY = contraptionBounds.maxY;
betterBounds.minY = contraptionBounds.minY;
} else if (axis == Direction.Axis.Z) {
betterBounds.maxZ = contraptionBounds.maxZ;
betterBounds.minZ = contraptionBounds.minZ;
}
bounds = betterBounds.toAABB();
}
public void addExtraInventories(Entity entity) {}
@ -1163,4 +1148,51 @@ public abstract class Contraption {
return new EmptyLighter(this);
}
public static float getRadius(Set<BlockPos> blocks, Direction.Axis axis) {
switch (axis) {
case X:
return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ);
case Y:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ);
case Z:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY);
}
throw new IllegalStateException("Impossible axis");
}
public static float getMaxDistSqr(Set<BlockPos> blocks, Coordinate one, Coordinate other) {
float maxDistSq = -1;
for (BlockPos pos : blocks) {
float a = one.get(pos);
float b = other.get(pos);
float distSq = a * a + b * b;
if (distSq > maxDistSq) maxDistSq = distSq;
}
return maxDistSq;
}
private static class ContraptionTileWorld extends WrappedWorld implements IFlywheelWorld {
private final TileEntity te;
private final BlockInfo info;
public ContraptionTileWorld(World world, TileEntity te, BlockInfo info) {
super(world);
this.te = te;
this.info = info;
}
@Override
public BlockState getBlockState(BlockPos pos) {
if (!pos.equals(te.getPos()))
return Blocks.AIR.getDefaultState();
return info.state;
}
}
}

View file

@ -0,0 +1,19 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
import com.simibubi.create.foundation.render.backend.light.GridAlignedBB;
public class AnchoredLighter extends ContraptionLighter<Contraption> {
public AnchoredLighter(Contraption contraption) {
super(contraption);
}
@Override
public GridAlignedBB getContraptionBounds() {
GridAlignedBB bb = GridAlignedBB.fromAABB(contraption.bounds);
bb.translate(contraption.anchor);
return bb;
}
}

View file

@ -97,6 +97,6 @@ public class BearingContraption extends Contraption {
@OnlyIn(Dist.CLIENT)
@Override
public ContraptionLighter<?> makeLighter() {
return new BearingLighter(this);
return new AnchoredLighter(this);
}
}

View file

@ -1,75 +0,0 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import java.util.Set;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
import com.simibubi.create.foundation.render.backend.light.GridAlignedBB;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public class BearingLighter extends ContraptionLighter<BearingContraption> {
public BearingLighter(BearingContraption contraption) {
super(contraption);
}
@Override
public GridAlignedBB getContraptionBounds() {
Set<BlockPos> blocks = contraption.getBlocks().keySet();
Direction orientation = contraption.facing;
Direction.Axis axis = orientation.getAxis();
int radius = (int) (Math.ceil(Math.sqrt(getRadius(blocks, axis))));
GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius);
GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(contraption.bounds);
if (axis == Direction.Axis.X) {
betterBounds.maxX = contraptionBounds.maxX;
betterBounds.minX = contraptionBounds.minX;
} else if (axis == Direction.Axis.Y) {
betterBounds.maxY = contraptionBounds.maxY;
betterBounds.minY = contraptionBounds.minY;
} else if (axis == Direction.Axis.Z) {
betterBounds.maxZ = contraptionBounds.maxZ;
betterBounds.minZ = contraptionBounds.minZ;
}
betterBounds.translate(contraption.anchor);
return betterBounds;
}
private static float getRadius(Set<BlockPos> blocks, Direction.Axis axis) {
switch (axis) {
case X:
return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ);
case Y:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ);
case Z:
return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY);
}
throw new IllegalStateException("Impossible axis");
}
private static float getMaxDistSqr(Set<BlockPos> blocks, Coordinate one, Coordinate other) {
float maxDistSq = -1;
for (BlockPos pos : blocks) {
float a = one.get(pos);
float b = other.get(pos);
float distSq = a * a + b * b;
if (distSq > maxDistSq) maxDistSq = distSq;
}
return maxDistSq;
}
private interface Coordinate {
float get(BlockPos from);
}
}

View file

@ -28,7 +28,8 @@ import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions {
public class ClockworkBearingTileEntity extends KineticTileEntity
implements IBearingTileEntity, IDisplayAssemblyExceptions {
protected ControlledContraptionEntity hourHand;
protected ControlledContraptionEntity minuteHand;
@ -40,9 +41,10 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
protected boolean running;
protected boolean assembleNextTick;
protected AssemblyException lastException;
protected ScrollOptionBehaviour<ClockHands> operationMode;
private float prevForcedAngle;
public ClockworkBearingTileEntity(TileEntityType<? extends ClockworkBearingTileEntity> type) {
super(type);
setLazyTickRate(3);
@ -67,6 +69,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
super.tick();
if (world.isRemote) {
prevForcedAngle = hourAngle;
clientMinuteAngleDiff /= 2;
clientHourAngleDiff /= 2;
}
@ -341,6 +344,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
@Override
public float getInterpolatedAngle(float partialTicks) {
if (isVirtual())
return MathHelper.lerp(partialTicks, prevForcedAngle, hourAngle);
if (hourHand == null || hourHand.isStalled())
partialTicks = 0;
return MathHelper.lerp(partialTicks, hourAngle, hourAngle + getHourArmSpeed());
@ -414,4 +419,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
public boolean shouldRenderAsTE() {
return true;
}
public void setAngle(float forcedAngle) {
hourAngle = forcedAngle;
}
}

View file

@ -4,6 +4,7 @@ import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
@ -129,4 +130,8 @@ public class ClockworkContraption extends Contraption {
HOUR, MINUTE
}
@Override
public ContraptionLighter<?> makeLighter() {
return new AnchoredLighter(this);
}
}

View file

@ -20,5 +20,7 @@ public interface IBearingTileEntity extends IControlContraption {
return bearingAxis != axis;
});
}
void setAngle(float forcedAngle);
}

View file

@ -4,12 +4,11 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.*;
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformData;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.world.LightType;
@ -24,7 +23,7 @@ public class StickerInstance extends TileEntityInstance<StickerTileEntity> imple
float lastOffset = Float.NaN;
private InstanceKey<TransformData> head;
private InstanceKey<ModelData> head;
public StickerInstance(InstancedTileRenderer<?> modelManager, StickerTileEntity tile) {
super(modelManager, tile);
@ -61,7 +60,7 @@ public class StickerInstance extends TileEntityInstance<StickerTileEntity> imple
.translate(0, (offset * offset) * 4 / 16f, 0);
head.getInstance()
.setTransform(stack);
.setTransformNoCopy(stack);
lastOffset = offset;
}
@ -69,8 +68,8 @@ public class StickerInstance extends TileEntityInstance<StickerTileEntity> imple
@Override
public void updateLight() {
head.getInstance()
.setBlockLight((byte) (world.getLightLevel(LightType.BLOCK, pos) << 4))
.setSkyLight((byte) (world.getLightLevel(LightType.SKY, pos) << 4));
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
}
@Override

View file

@ -10,7 +10,7 @@ import com.simibubi.create.foundation.render.backend.instancing.ITickableInstanc
import com.simibubi.create.foundation.render.backend.instancing.InstanceKey;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformData;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.MatrixStacker;
@ -28,7 +28,7 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn
InstancedTileRenderRegistry.instance.register(type, GantryCarriageInstance::new));
}
private InstanceKey<TransformData> gantryCogs;
private InstanceKey<ModelData> gantryCogs;
public GantryCarriageInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
super(dispatcher, tile);
@ -47,7 +47,7 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn
@Override
public void tick() {
lastState = world.getBlockState(pos);
lastState = tile.getBlockState();
Direction facing = lastState.get(GantryCarriageBlock.FACING);
Boolean alongFirst = lastState.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE);
Direction.Axis rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile);
@ -80,14 +80,14 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn
.translate(0, 9 / 16f, 0)
.unCentre();
gantryCogs.getInstance().setTransform(ms);
gantryCogs.getInstance().setTransformNoCopy(ms);
}
@Override
public void updateLight() {
gantryCogs.getInstance()
.setBlockLight((byte) (world.getLightLevel(LightType.BLOCK, pos) << 4))
.setSkyLight((byte) (world.getLightLevel(LightType.SKY, pos) << 4));
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
}
@Override

View file

@ -72,7 +72,7 @@ public class GantryCarriageRenderer extends KineticTileEntityRenderer {
}
public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) {
float time = AnimationTickHolder.getRenderTime();
float time = AnimationTickHolder.getRenderTime(te.getWorld());
float offset = getRotationOffsetForPosition(te, pos, axis);
return ((time * te.getSpeed() * 3f / 20 + offset) % 360) / 180 * (float) Math.PI;
}

View file

@ -41,9 +41,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer {
@Override
protected float getOffset(KineticTileEntity te, float partialTicks) {
PulleyTileEntity pulley = (PulleyTileEntity) te;
boolean running = pulley.running;
boolean moving = running && (pulley.movedContraption == null || !pulley.movedContraption.isStalled());
float offset = pulley.getInterpolatedOffset(moving ? partialTicks : 0.5f);
float offset = pulley.getInterpolatedOffset(partialTicks);
if (pulley.movedContraption != null) {
AbstractContraptionEntity e = pulley.movedContraption;
@ -57,7 +55,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer {
@Override
protected boolean isRunning(KineticTileEntity te) {
return ((PulleyTileEntity) te).running;
return ((PulleyTileEntity) te).running || te.isVirtual();
}
}

View file

@ -27,6 +27,7 @@ import net.minecraft.util.math.Vec3d;
public class PulleyTileEntity extends LinearActuatorTileEntity {
protected int initialOffset;
private float prevAnimatedOffset;
public PulleyTileEntity(TileEntityType<? extends PulleyTileEntity> type) {
super(type);
@ -41,6 +42,13 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
public double getMaxRenderDistanceSquared() {
return super.getMaxRenderDistanceSquared() + offset * offset;
}
@Override
public void tick() {
super.tick();
if (isVirtual())
prevAnimatedOffset = offset;
}
@Override
protected void assemble() throws AssemblyException {
@ -219,4 +227,16 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP);
}
@Override
public float getInterpolatedOffset(float partialTicks) {
if (isVirtual())
return MathHelper.lerp(partialTicks, prevAnimatedOffset, offset);
boolean moving = running && (movedContraption == null || !movedContraption.isStalled());
return super.getInterpolatedOffset(moving ? partialTicks : 0.5f);
}
public void animateOffset(float forcedOffset) {
offset = forcedOffset;
}
}

View file

@ -10,14 +10,14 @@ import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial;
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedInstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.impl.BasicInstancedModel;
import net.minecraft.util.math.BlockPos;
public class ContraptionKineticRenderer extends InstancedTileRenderer<ContraptionProgram> {
@Override
public void registerMaterials() {
materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, TransformedInstancedModel::new));
materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, BasicInstancedModel::new));
materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.C_BELT, BeltInstancedModel::new));
materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.C_ROTATING, RotatingInstancedModel::new));

View file

@ -67,7 +67,7 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle {
}
public void move(double x, double y, double z) {
float time = AnimationTickHolder.getTicks();
float time = AnimationTickHolder.getTicks(world);
float angle = (float) ((time * speed) % 360) - (speed / 2 * age * (((float) age) / maxAge));
if (speed < 0 && axis.isVertical())
angle += 180;

View file

@ -72,8 +72,9 @@ public class BasinRenderer extends SmartTileEntityRenderer<BasinTileEntity> {
if (fluidLevel > 0) {
ms.translate(0,
(MathHelper.sin(AnimationTickHolder.getRenderTime() / 12f + anglePartition * itemCount) + 1.5f) * 1
/ 32f,
(MathHelper.sin(
AnimationTickHolder.getRenderTime(basin.getWorld()) / 12f + anglePartition * itemCount) + 1.5f)
* 1 / 32f,
0);
}

View file

@ -27,7 +27,7 @@ public class BlazeBurnerRenderer extends SafeTileEntityRenderer<BlazeBurnerTileE
if (heatLevel == HeatLevel.NONE)
return;
float renderTick = AnimationTickHolder.getRenderTime() + (te.hashCode() % 13) * 16f;
float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()) + (te.hashCode() % 13) * 16f;
float offset = (MathHelper.sin((float) ((renderTick / 16f) % (2 * Math.PI))) + .5f) / 16f;
AllBlockPartials blazeModel = AllBlockPartials.BLAZES.get(heatLevel);

View file

@ -74,7 +74,7 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
MatrixStack localTransforms = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(localTransforms);
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
float renderTick = AnimationTickHolder.getRenderTime();
float renderTick = AnimationTickHolder.getRenderTime(te.getWorld());
msr.centre();
msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0));

View file

@ -32,7 +32,7 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer {
Block block = te.getBlockState().getBlock();
final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState());
final BlockPos pos = te.getPos();
float time = AnimationTickHolder.getRenderTime();
float time = AnimationTickHolder.getRenderTime(te.getWorld());
for (Direction direction : Iterate.directions) {
Axis axis = direction.getAxis();

View file

@ -30,7 +30,7 @@ public class GearboxRenderer extends KineticTileEntityRenderer {
final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS);
final BlockPos pos = te.getPos();
float time = AnimationTickHolder.getRenderTime();
float time = AnimationTickHolder.getRenderTime(te.getWorld());
for (Direction direction : Iterate.directions) {
final Axis axis = direction.getAxis();

View file

@ -1,29 +1,178 @@
package com.simibubi.create.content.logistics.block.mechanicalArm;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.RotatingData;
import com.simibubi.create.content.contraptions.base.SingleRotatingInstance;
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.gui.widgets.InterpolatedValue;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.*;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.LightType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
public class ArmInstance extends SingleRotatingInstance {
import java.util.ArrayList;
import java.util.stream.Stream;
public class ArmInstance extends SingleRotatingInstance implements ITickableInstance {
public static void register(TileEntityType<? extends KineticTileEntity> type) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
InstancedTileRenderRegistry.instance.register(type, ArmInstance::new));
}
private InstanceKey<ModelData> base;
private InstanceKey<ModelData> lowerBody;
private InstanceKey<ModelData> upperBody;
private InstanceKey<ModelData> head;
private InstanceKey<ModelData> claw;
private ArrayList<InstanceKey<ModelData>> clawGrips;
private ArrayList<InstanceKey<ModelData>> models;
private boolean firstTick = true;
public ArmInstance(InstancedTileRenderer<?> modelManager, KineticTileEntity tile) {
super(modelManager, tile);
}
@Override
protected void init() {
super.init();
RenderMaterial<?, InstancedModel<ModelData>> mat = modelManager.getMaterial(RenderMaterials.MODELS);
base = mat.getModel(AllBlockPartials.ARM_BASE, lastState).createInstance();
lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, lastState).createInstance();
upperBody = mat.getModel(AllBlockPartials.ARM_UPPER_BODY, lastState).createInstance();
head = mat.getModel(AllBlockPartials.ARM_HEAD, lastState).createInstance();
claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE, lastState).createInstance();
InstancedModel<ModelData> clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, lastState);
InstanceKey<ModelData> clawGrip1 = clawHalfModel.createInstance();
InstanceKey<ModelData> clawGrip2 = clawHalfModel.createInstance();
clawGrips = Lists.newArrayList(clawGrip1, clawGrip2);
models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2);
tick();
updateLight();
}
@Override
public void tick() {
ArmTileEntity arm = (ArmTileEntity) tile;
boolean settled = Stream.of(arm.baseAngle, arm.lowerArmAngle, arm.upperArmAngle, arm.headAngle).allMatch(InterpolatedValue::settled);
boolean rave = arm.phase == ArmTileEntity.Phase.DANCING;
if (!settled || rave || firstTick)
transformModels(arm, rave);
if (settled)
firstTick = false;
}
private void transformModels(ArmTileEntity arm, boolean rave) {
float pt = AnimationTickHolder.getPartialTicks();
int color = 0xFFFFFF;
float baseAngle = arm.baseAngle.get(pt);
float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135;
float upperArmAngle = arm.upperArmAngle.get(pt) - 90;
float headAngle = arm.headAngle.get(pt);
if (rave) {
float renderTick = AnimationTickHolder.getRenderTime(arm.getWorld()) + (tile.hashCode() % 64);
baseAngle = (renderTick * 10) % 360;
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95);
headAngle = -lowerArmAngle;
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
}
MatrixStack msLocal = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(msLocal);
msr.translate(getFloatingPos());
msr.centre();
if (lastState.get(ArmBlock.CEILING))
msr.rotateX(180);
ArmRenderer.transformBase(msr, baseAngle);
base.getInstance()
.setTransform(msLocal);
ArmRenderer.transformLowerArm(msr, lowerArmAngle);
lowerBody.getInstance()
.setColor(color)
.setTransform(msLocal);
ArmRenderer.transformUpperArm(msr, upperArmAngle);
upperBody.getInstance()
.setColor(color)
.setTransform(msLocal);
ArmRenderer.transformHead(msr, headAngle);
head.getInstance()
.setTransform(msLocal);
ArmRenderer.transformClaw(msr);
claw.getInstance()
.setTransform(msLocal);
ItemStack item = arm.heldItem;
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
boolean hasItem = !item.isEmpty();
boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem)
&& itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null)
.isGui3d();
for (int index : Iterate.zeroAndOne) {
msLocal.push();
int flip = index * 2 - 1;
ArmRenderer.transformClawHalf(msr, hasItem, isBlockItem, flip);
clawGrips.get(index)
.getInstance()
.setTransform(msLocal);
msLocal.pop();
}
}
@Override
public void updateLight() {
super.updateLight();
int block = world.getLightLevel(LightType.BLOCK, pos);
int sky = world.getLightLevel(LightType.SKY, pos);
models.stream()
.map(InstanceKey::getInstance)
.forEach(data -> data.setSkyLight(sky).setBlockLight(block));
}
@Override
protected InstancedModel<RotatingData> getModel() {
return AllBlockPartials.ARM_COG.renderOnRotating(modelManager, tile.getBlockState());
}
@Override
public void remove() {
super.remove();
models.forEach(InstanceKey::delete);
}
}

View file

@ -7,6 +7,8 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.Backend;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Iterate;
@ -39,6 +41,21 @@ public class ArmRenderer extends KineticTileEntityRenderer {
int overlay) {
super.renderSafe(te, pt, ms, buffer, light, overlay);
ArmTileEntity arm = (ArmTileEntity) te;
boolean usingFlywheel = FastRenderDispatcher.available(te.getWorld());
ItemStack item = arm.heldItem;
boolean hasItem = !item.isEmpty();
if (usingFlywheel && !hasItem) return;
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem)
&& itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null)
.isGui3d();
IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid());
BlockState blockState = te.getBlockState();
@ -52,7 +69,7 @@ public class ArmRenderer extends KineticTileEntityRenderer {
float headAngle = arm.headAngle.get(pt);
boolean rave = arm.phase == Phase.DANCING;
float renderTick = AnimationTickHolder.getRenderTime() + (te.hashCode() % 64);
float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()) + (te.hashCode() % 64);
if (rave) {
baseAngle = (renderTick * 10) % 360;
lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15);
@ -61,59 +78,15 @@ public class ArmRenderer extends KineticTileEntityRenderer {
color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100);
}
SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState).light(light);
SuperByteBuffer lowerBody = AllBlockPartials.ARM_LOWER_BODY.renderOn(blockState).light(light);
SuperByteBuffer upperBody = AllBlockPartials.ARM_UPPER_BODY.renderOn(blockState).light(light);
SuperByteBuffer head = AllBlockPartials.ARM_HEAD.renderOn(blockState).light(light);
SuperByteBuffer claw = AllBlockPartials.ARM_CLAW_BASE.renderOn(blockState).light(light);
SuperByteBuffer clawGrip = AllBlockPartials.ARM_CLAW_GRIP.renderOn(blockState);
msr.centre();
if (blockState.get(ArmBlock.CEILING))
msr.rotateX(180);
msLocal.translate(0, 4 / 16d, 0);
msr.rotateY(baseAngle);
base.transform(msLocal)
.renderInto(ms, builder);
msLocal.translate(0, 1 / 16d, -2 / 16d);
msr.rotateX(lowerArmAngle);
msLocal.translate(0, -1 / 16d, 0);
lowerBody.color(color)
.transform(msLocal)
.renderInto(ms, builder);
msLocal.translate(0, 12 / 16d, 12 / 16d);
msr.rotateX(upperArmAngle);
upperBody.color(color)
.transform(msLocal)
.renderInto(ms, builder);
msLocal.translate(0, 11 / 16d, -11 / 16d);
msr.rotateX(headAngle);
head.transform(msLocal)
.renderInto(ms, builder);
msLocal.translate(0, 0, -4 / 16d);
claw.transform(msLocal)
.renderInto(ms, builder);
ItemStack item = arm.heldItem;
ItemRenderer itemRenderer = Minecraft.getInstance()
.getItemRenderer();
boolean hasItem = !item.isEmpty();
boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem)
&& itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null)
.isGui3d();
for (int flip : Iterate.positiveAndNegative) {
msLocal.push();
msLocal.translate(0, flip * 3 / 16d, -1 / 16d);
msr.rotateX(flip * (hasItem ? isBlockItem ? 0 : -35 : 0));
clawGrip.light(light).transform(msLocal).renderInto(ms, builder);
msLocal.pop();
}
if (usingFlywheel)
doItemTransforms(msr, baseAngle, lowerArmAngle, upperArmAngle, headAngle);
else
renderArm(builder, ms, msLocal, msr, blockState, color, baseAngle, lowerArmAngle, upperArmAngle, headAngle, hasItem, isBlockItem, light);
if (hasItem) {
ms.push();
@ -131,6 +104,83 @@ public class ArmRenderer extends KineticTileEntityRenderer {
}
private void renderArm(IVertexBuilder builder, MatrixStack ms, MatrixStack msLocal, MatrixStacker msr, BlockState blockState, int color, float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle, boolean hasItem, boolean isBlockItem, int light) {
SuperByteBuffer base = AllBlockPartials.ARM_BASE.renderOn(blockState).light(light);
SuperByteBuffer lowerBody = AllBlockPartials.ARM_LOWER_BODY.renderOn(blockState).light(light);
SuperByteBuffer upperBody = AllBlockPartials.ARM_UPPER_BODY.renderOn(blockState).light(light);
SuperByteBuffer head = AllBlockPartials.ARM_HEAD.renderOn(blockState).light(light);
SuperByteBuffer claw = AllBlockPartials.ARM_CLAW_BASE.renderOn(blockState).light(light);
SuperByteBuffer clawGrip = AllBlockPartials.ARM_CLAW_GRIP.renderOn(blockState);
transformBase(msr, baseAngle);
base.transform(msLocal)
.renderInto(ms, builder);
transformLowerArm(msr, lowerArmAngle);
lowerBody.color(color)
.transform(msLocal)
.renderInto(ms, builder);
transformUpperArm(msr, upperArmAngle);
upperBody.color(color)
.transform(msLocal)
.renderInto(ms, builder);
transformHead(msr, headAngle);
head.transform(msLocal)
.renderInto(ms, builder);
transformClaw(msr);
claw.transform(msLocal)
.renderInto(ms, builder);
for (int flip : Iterate.positiveAndNegative) {
msLocal.push();
transformClawHalf(msr, hasItem, isBlockItem, flip);
clawGrip.light(light).transform(msLocal).renderInto(ms, builder);
msLocal.pop();
}
}
private void doItemTransforms(MatrixStacker msr, float baseAngle, float lowerArmAngle, float upperArmAngle, float headAngle) {
transformBase(msr, baseAngle);
transformLowerArm(msr, lowerArmAngle);
transformUpperArm(msr, upperArmAngle);
transformHead(msr, headAngle);
transformClaw(msr);
}
public static void transformClawHalf(MatrixStacker msr, boolean hasItem, boolean isBlockItem, int flip) {
msr.translate(0, flip * 3 / 16d, -1 / 16d);
msr.rotateX(flip * (hasItem ? isBlockItem ? 0 : -35 : 0));
}
public static void transformClaw(MatrixStacker msr) {
msr.translate(0, 0, -4 / 16d);
}
public static void transformHead(MatrixStacker msr, float headAngle) {
msr.translate(0, 11 / 16d, -11 / 16d);
msr.rotateX(headAngle);
}
public static void transformUpperArm(MatrixStacker msr, float upperArmAngle) {
msr.translate(0, 12 / 16d, 12 / 16d);
msr.rotateX(upperArmAngle);
}
public static void transformLowerArm(MatrixStacker msr, float lowerArmAngle) {
msr.translate(0, 1 / 16d, -2 / 16d);
msr.rotateX(lowerArmAngle);
msr.translate(0, -1 / 16d, 0);
}
public static void transformBase(MatrixStacker msr, float baseAngle) {
msr.translate(0, 4 / 16d, 0);
msr.rotateY(baseAngle);
}
@Override
protected SuperByteBuffer getRotatedModel(KineticTileEntity te) {
return AllBlockPartials.ARM_COG.renderOn(te.getBlockState());

View file

@ -0,0 +1,99 @@
package com.simibubi.create.content.schematics.block;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance;
import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.RenderMaterials;
import com.simibubi.create.foundation.render.backend.instancing.*;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
public class SchematicannonInstance extends TileEntityInstance<SchematicannonTileEntity> implements ITickableInstance {
public static void register(TileEntityType<? extends SchematicannonTileEntity> type) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
InstancedTileRenderRegistry.instance.register(type, SchematicannonInstance::new));
}
private InstanceKey<ModelData> connector;
private InstanceKey<ModelData> pipe;
public SchematicannonInstance(InstancedTileRenderer<?> modelManager, SchematicannonTileEntity tile) {
super(modelManager, tile);
}
@Override
protected void init() {
RenderMaterial<?, InstancedModel<ModelData>> mat = modelManager.getMaterial(RenderMaterials.MODELS);
connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, lastState).createInstance();
pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, lastState).createInstance();
updateLight();
}
@Override
public void tick() {
float partialTicks = AnimationTickHolder.getPartialTicks();
double[] cannonAngles = SchematicannonRenderer.getCannonAngles(tile, pos, partialTicks);
double pitch = cannonAngles[0];
double yaw = cannonAngles[1];
double recoil = SchematicannonRenderer.getRecoil(tile, partialTicks);
MatrixStack ms = new MatrixStack();
MatrixStacker msr = MatrixStacker.of(ms);
msr.translate(getFloatingPos());
ms.push();
msr.centre();
msr.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI));
msr.unCentre();
connector.getInstance().setTransform(ms);
ms.pop();
msr.translate(.5f, 15 / 16f, .5f);
msr.rotate(Direction.UP, (float) ((yaw + 90) / 180 * Math.PI));
msr.rotate(Direction.SOUTH, (float) (pitch / 180 * Math.PI));
msr.translate(-.5f, -15 / 16f, -.5f);
msr.translate(0, -recoil / 100, 0);
pipe.getInstance().setTransformNoCopy(ms);
}
@Override
public void remove() {
connector.delete();
pipe.delete();
}
@Override
public void updateLight() {
int block = world.getLightLevel(LightType.BLOCK, pos);
int sky = world.getLightLevel(LightType.SKY, pos);
connector.getInstance()
.setBlockLight(block)
.setSkyLight(sky);
pipe.getInstance()
.setBlockLight(block)
.setSkyLight(sky);
}
}

View file

@ -8,6 +8,7 @@ import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.schematics.block.LaunchedItem.ForBlockState;
import com.simibubi.create.content.schematics.block.LaunchedItem.ForEntity;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import net.minecraft.block.BlockState;
@ -40,33 +41,20 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
protected void renderSafe(SchematicannonTileEntity tileEntityIn, float partialTicks, MatrixStack ms,
IRenderTypeBuffer buffer, int light, int overlay) {
double yaw = 0;
double pitch = 40;
boolean blocksLaunching = !tileEntityIn.flyingBlocks.isEmpty();
if (blocksLaunching)
renderLaunchedBlocks(tileEntityIn, partialTicks, ms, buffer, light, overlay);
if (FastRenderDispatcher.available(tileEntityIn.getWorld())) return;
BlockPos pos = tileEntityIn.getPos();
if (tileEntityIn.target != null) {
// Calculate Angle of Cannon
Vec3d diff = new Vec3d(tileEntityIn.target.subtract(pos));
if (tileEntityIn.previousTarget != null) {
diff = (new Vec3d(tileEntityIn.previousTarget)
.add(new Vec3d(tileEntityIn.target.subtract(tileEntityIn.previousTarget)).scale(partialTicks)))
.subtract(new Vec3d(pos));
}
double[] cannonAngles = getCannonAngles(tileEntityIn, pos, partialTicks);
double diffX = diff.getX();
double diffZ = diff.getZ();
yaw = MathHelper.atan2(diffX, diffZ);
yaw = yaw / Math.PI * 180;
double pitch = cannonAngles[0];
double yaw = cannonAngles[1];
float distance = MathHelper.sqrt(diffX * diffX + diffZ * diffZ);
double yOffset = 0 + distance * 2f;
pitch = MathHelper.atan2(distance, diff.getY() * 3 + yOffset);
pitch = pitch / Math.PI * 180 + 10;
}
double recoil = !tileEntityIn.flyingBlocks.isEmpty() ? getRecoil(tileEntityIn, partialTicks, ms, buffer, light, overlay) : 0;
double recoil = getRecoil(tileEntityIn, partialTicks);
ms.push();
BlockState state = tileEntityIn.getBlockState();
@ -91,9 +79,51 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
ms.pop();
}
private double getRecoil(SchematicannonTileEntity tileEntityIn, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) {
public static double[] getCannonAngles(SchematicannonTileEntity tile, BlockPos pos, float partialTicks) {
double yaw = 0;
double pitch = 40;
if (tile.target != null) {
// Calculate Angle of Cannon
Vec3d diff = new Vec3d(tile.target.subtract(pos));
if (tile.previousTarget != null) {
diff = (new Vec3d(tile.previousTarget)
.add(new Vec3d(tile.target.subtract(tile.previousTarget)).scale(partialTicks)))
.subtract(new Vec3d(pos));
}
double diffX = diff.getX();
double diffZ = diff.getZ();
yaw = MathHelper.atan2(diffX, diffZ);
yaw = yaw / Math.PI * 180;
float distance = MathHelper.sqrt(diffX * diffX + diffZ * diffZ);
double yOffset = 0 + distance * 2f;
pitch = MathHelper.atan2(distance, diff.getY() * 3 + yOffset);
pitch = pitch / Math.PI * 180 + 10;
}
return new double[] { pitch, yaw };
}
public static double getRecoil(SchematicannonTileEntity tileEntityIn, float partialTicks) {
double recoil = 0;
for (LaunchedItem launched : tileEntityIn.flyingBlocks) {
if (launched.ticksRemaining == 0) continue;
// Apply Recoil if block was just launched
if ((launched.ticksRemaining + 1 - partialTicks) > launched.totalTicks - 10)
recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10);
}
return recoil;
}
private static void renderLaunchedBlocks(SchematicannonTileEntity tileEntityIn, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) {
for (LaunchedItem launched : tileEntityIn.flyingBlocks) {
if (launched.ticksRemaining == 0)
@ -141,10 +171,6 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
ms.pop();
// Apply Recoil if block was just launched
if ((launched.ticksRemaining + 1 - partialTicks) > launched.totalTicks - 10)
recoil = Math.max(recoil, (launched.ticksRemaining + 1 - partialTicks) - launched.totalTicks + 10);
// Render particles for launch
if (launched.ticksRemaining == launched.totalTicks && tileEntityIn.firstRenderTick) {
tileEntityIn.firstRenderTick = false;
@ -162,8 +188,6 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
}
}
return recoil;
}
}

View file

@ -9,6 +9,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
@ -23,6 +24,7 @@ import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.config.CSchematics;
import com.simibubi.create.foundation.item.ItemHelper;
import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode;
import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.BlockHelper;
@ -63,11 +65,12 @@ import net.minecraft.world.gen.feature.template.Template;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public class SchematicannonTileEntity extends SmartTileEntity implements INamedContainerProvider {
public class SchematicannonTileEntity extends SmartTileEntity implements INamedContainerProvider, IInstanceRendered {
public static final int NEIGHBOUR_CHECKING = 100;
public static final int MAX_ANCHOR_DISTANCE = 256;
@ -934,4 +937,20 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
findInventories();
}
@Override
public void initialize() {
super.initialize();
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.add(this));
}
@Override
public void onChunkLightUpdate() {
CreateClient.kineticRenderer.onLightUpdate(this);
}
@Override
public boolean shouldRenderAsTE() {
return true;
}
}

View file

@ -122,7 +122,8 @@ public class AllIcons implements IScreenRenderable {
I_MTD_CLOSE = next(),
I_MTD_RIGHT = next(),
I_MTD_SCAN = next(),
I_MTD_REPLAY = next();
I_MTD_REPLAY = next(),
I_MTD_USER_MODE = next();
public AllIcons(int x, int y) {
iconX = x * 16;

View file

@ -16,5 +16,9 @@ public class InterpolatedValue {
public float get(float partialTicks) {
return MathHelper.lerp(partialTicks, lastValue, value);
}
public boolean settled() {
return Math.abs(value - lastValue) < 1e-3;
}
}

View file

@ -76,10 +76,13 @@ public class PonderScene {
WorldSectionElement baseWorldSection;
Entity renderViewEntity;
int offsetX;
int offsetZ;
int size;
int basePlateOffsetX;
int basePlateOffsetZ;
int basePlateSize;
float scaleFactor;
float yOffset;
boolean stoppedCounting;
int totalTime;
int currentTime;
@ -97,10 +100,12 @@ public class PonderScene {
schedule = new ArrayList<>();
activeSchedule = new ArrayList<>();
transform = new SceneTransform();
size = getBounds().getXSize();
basePlateSize = getBounds().getXSize();
info = new SceneRenderInfo();
baseWorldSection = new WorldSectionElement();
renderViewEntity = new ArmorStandEntity(world, 0, 0, 0);
scaleFactor = 1;
yOffset = 0;
setPointOfInterest(new Vec3d(0, 4, 0));
}
@ -135,11 +140,12 @@ public class PonderScene {
BlockPos selectedPos = nearestHit.getValue()
.getSecond();
BlockPos origin = new BlockPos(offsetX, 0, offsetZ);
BlockPos origin = new BlockPos(basePlateOffsetX, 0, basePlateOffsetZ);
if (!world.getBounds()
.isVecInside(selectedPos))
return Pair.of(ItemStack.EMPTY, null);
if (new MutableBoundingBox(origin, origin.add(new Vec3i(size - 1, 0, size - 1))).isVecInside(selectedPos)) {
if (new MutableBoundingBox(origin, origin.add(new Vec3i(basePlateSize - 1, 0, basePlateSize - 1)))
.isVecInside(selectedPos)) {
if (PonderIndex.EDITOR_MODE)
nearestHit.getValue()
.getFirst()
@ -189,6 +195,7 @@ public class PonderScene {
elements.add(baseWorldSection);
totalTime = 0;
stoppedCounting = false;
activeSchedule.addAll(schedule);
activeSchedule.forEach(i -> i.onScheduled(this));
}
@ -269,7 +276,12 @@ public class PonderScene {
}
public void addToSceneTime(int time) {
totalTime += time;
if (!stoppedCounting)
totalTime += time;
}
public void stopCounting() {
stoppedCounting = true;
}
public void addElement(PonderElement e) {
@ -376,11 +388,11 @@ public class PonderScene {
}
public MatrixStack apply(MatrixStack ms) {
return apply(ms, AnimationTickHolder.getPartialTicks());
return apply(ms, AnimationTickHolder.getPartialTicks(world));
}
public MatrixStack apply(MatrixStack ms, float pt) {
ms.translate(width / 2, height / 2, 200);
ms.translate(width / 2, height / 2, 200 + offset);
MatrixStacker.of(ms)
.rotateX(-35)
@ -389,12 +401,15 @@ public class PonderScene {
MatrixStacker.of(ms)
.rotateY(-55)
.rotateX(35);
MatrixStacker.of(ms)
.rotateX(xRotation.getValue(pt))
.rotateY(yRotation.getValue(pt));
ms.scale(30, -30, 30);
ms.translate((size + offsetX) / -2f, -1f, (size + offsetZ) / -2f);
float f = 30 * scaleFactor;
ms.scale(f, -f, f);
ms.translate((basePlateSize + basePlateOffsetX) / -2f, -1f + yOffset,
(basePlateSize + basePlateOffsetZ) / -2f);
return ms;
}
@ -409,7 +424,7 @@ public class PonderScene {
float pt = AnimationTickHolder.getPartialTicks();
Vec3d vec = new Vec3d(x, y, depth);
vec = vec.subtract(width / 2, height / 2, 200);
vec = vec.subtract(width / 2, height / 2, 200 + offset);
vec = VecHelper.rotate(vec, 35, Axis.X);
vec = VecHelper.rotate(vec, -55, Axis.Y);
vec = vec.subtract(offset, 0, 0);
@ -417,8 +432,12 @@ public class PonderScene {
vec = VecHelper.rotate(vec, -35, Axis.X);
vec = VecHelper.rotate(vec, -xRotation.getValue(pt), Axis.X);
vec = VecHelper.rotate(vec, -yRotation.getValue(pt), Axis.Y);
vec = vec.mul(1f / 30, 1f / -30, 1f / 30);
vec = vec.subtract((size + offsetX) / -2f, -1f, (size + offsetZ) / -2f);
float f = 1f / (30 * scaleFactor);
vec = vec.mul(f, -f, f);
vec = vec.subtract((basePlateSize + basePlateOffsetX) / -2f, -1f + yOffset,
(basePlateSize + basePlateOffsetZ) / -2f);
return vec;
}

View file

@ -95,7 +95,8 @@ public class PonderTooltipHandler {
}
public static void addToTooltip(List<ITextComponent> toolTip, ItemStack stack) {
float renderPartialTicks = AnimationTickHolder.getPartialTicks();
float renderPartialTicks = Minecraft.getInstance()
.getRenderPartialTicks();
if (lastHoveredStack != stack)
return;
ITextComponent component = subject ? Lang.createTranslationTextComponent(SUBJECT)

View file

@ -24,7 +24,6 @@ import com.simibubi.create.foundation.ponder.content.PonderTag;
import com.simibubi.create.foundation.ponder.content.PonderTagScreen;
import com.simibubi.create.foundation.ponder.ui.PonderButton;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -38,6 +37,7 @@ import net.minecraft.client.GameSettings;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
@ -55,6 +55,9 @@ import net.minecraftforge.registries.ForgeRegistries;
public class PonderUI extends AbstractSimiScreen {
public static int ponderTicks;
public static float ponderPartialTicksPaused;
public static final String PONDERING = PonderLocalization.LANG_PREFIX + "pondering";
public static final String IDENTIFY_MODE = PonderLocalization.LANG_PREFIX + "identify_mode";
public static final String IN_CHAPTER = PonderLocalization.LANG_PREFIX + "in_chapter";
@ -68,6 +71,7 @@ public class PonderUI extends AbstractSimiScreen {
ItemStack stack;
PonderChapter chapter = null;
private boolean userViewMode;
private boolean identifyMode;
private ItemStack hoveredTooltipItem;
private BlockPos hoveredBlockPos;
@ -79,7 +83,7 @@ public class PonderUI extends AbstractSimiScreen {
private int index = 0;
private PonderTag referredToByTag;
private PonderButton left, right, scan, chap;
private PonderButton left, right, scan, chap, userMode;
public static PonderUI of(ItemStack item) {
return new PonderUI(PonderRegistry.compile(item.getItem()
@ -134,7 +138,7 @@ public class PonderUI extends AbstractSimiScreen {
tags.forEach(t -> {
int i = tagButtons.size();
int x = 31;
int y = 71 + i * 30;
int y = 81 + i * 30;
PonderButton b = new PonderButton(x, y, (mouseX, mouseY) -> {
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(new PonderTagScreen(t));
@ -165,10 +169,19 @@ public class PonderUI extends AbstractSimiScreen {
if (!identifyMode)
scenes.get(index)
.deselect();
else
ponderPartialTicksPaused = minecraft.getRenderPartialTicks();
}).showing(AllIcons.I_MTD_SCAN)
.shortcut(bindings.keyBindDrop)
.fade(0, -1));
if (PonderIndex.EDITOR_MODE) {
widgets.add(userMode = new PonderButton(31, bY, () -> {
userViewMode = !userViewMode;
}).showing(AllIcons.I_MTD_USER_MODE)
.fade(0, -1));
}
bX += 50 + spacing;
widgets.add(left = new PonderButton(bX, bY, () -> this.scroll(false)).showing(AllIcons.I_MTD_LEFT)
.shortcut(bindings.keyBindLeft)
@ -215,8 +228,10 @@ public class PonderUI extends AbstractSimiScreen {
}
PonderScene activeScene = scenes.get(index);
if (!identifyMode)
if (!identifyMode) {
ponderTicks++;
activeScene.tick();
}
sceneProgress.chase(activeScene.getSceneProgress(), .5f, Chaser.EXP);
lazyIndex.tickChaser();
fadeIn.tickChaser();
@ -295,8 +310,13 @@ public class PonderUI extends AbstractSimiScreen {
@Override
protected void renderWindow(int mouseX, int mouseY, float partialTicks) {
RenderSystem.enableBlend();
renderVisibleScenes(mouseX, mouseY, identifyMode ? 0 : partialTicks);
renderWidgets(mouseX, mouseY, identifyMode ? 0 : partialTicks);
renderVisibleScenes(mouseX, mouseY, identifyMode ? ponderPartialTicksPaused : partialTicks);
renderWidgets(mouseX, mouseY, identifyMode ? ponderPartialTicksPaused : partialTicks);
}
@Override
public void renderBackground() {
super.renderBackground();
}
protected void renderVisibleScenes(int mouseX, int mouseY, float partialTicks) {
@ -310,7 +330,7 @@ public class PonderUI extends AbstractSimiScreen {
SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance();
PonderScene story = scenes.get(i);
MatrixStack ms = new MatrixStack();
double value = lazyIndex.getValue(AnimationTickHolder.getPartialTicks());
double value = lazyIndex.getValue(minecraft.getRenderPartialTicks());
double diff = i - value;
double slide = MathHelper.lerp(diff * diff, 200, 600) * diff;
@ -325,15 +345,36 @@ public class PonderUI extends AbstractSimiScreen {
story.renderScene(buffer, ms, partialTicks);
buffer.draw();
// coords for debug
if (PonderIndex.EDITOR_MODE) {
MutableBoundingBox bounds = story.getBounds();
MutableBoundingBox bounds = story.getBounds();
RenderSystem.pushMatrix();
RenderSystem.multMatrix(ms.peek()
.getModel());
// kool shadow fx
{
RenderSystem.enableCull();
RenderSystem.enableDepthTest();
RenderSystem.pushMatrix();
RenderSystem.multMatrix(ms.peek()
.getModel());
RenderSystem.translated(story.basePlateOffsetX, 0, story.basePlateOffsetZ);
RenderSystem.scaled(1, -1, 1);
for (int f = 0; f < 4; f++) {
RenderSystem.translated(story.basePlateSize, 0, 0);
RenderSystem.pushMatrix();
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);
}
RenderSystem.popMatrix();
RenderSystem.disableCull();
RenderSystem.disableDepthTest();
}
RenderSystem.scaled(-1 / 16d, -1 / 16d, 1 / 16d);
// coords for debug
if (PonderIndex.EDITOR_MODE && !userViewMode) {
RenderSystem.scaled(-1, -1, 1);
RenderSystem.scaled(1 / 16d, 1 / 16d, 1 / 16d);
RenderSystem.translated(1, -8, -1 / 64f);
// X AXIS
@ -373,11 +414,11 @@ public class PonderUI extends AbstractSimiScreen {
RenderSystem.popMatrix();
}
RenderSystem.popMatrix();
buffer.draw();
RenderSystem.popMatrix();
}
RenderSystem.popMatrix();
ms.pop();
}
@ -388,6 +429,10 @@ public class PonderUI extends AbstractSimiScreen {
PonderScene activeScene = scenes.get(index);
int textColor = 0xeeeeee;
boolean noWidgetsHovered = true;
for (Widget widget : widgets)
noWidgetsHovered &= !widget.isMouseOver(mouseX, mouseY);
{
// Chapter title
RenderSystem.pushMatrix();
@ -396,7 +441,7 @@ public class PonderUI extends AbstractSimiScreen {
int y = 31;
String title = activeScene.getTitle();
int wordWrappedHeight = font.getWordWrappedHeight(title, left.x);
int wordWrappedHeight = font.getWordWrappedHeight(title, left.x - 51);
int streakHeight = 35 - 9 + wordWrappedHeight;
UIRenderHelper.streak(0, x - 4, y - 12 + streakHeight / 2, streakHeight, (int) (150 * fade), 0x101010);
@ -415,7 +460,7 @@ public class PonderUI extends AbstractSimiScreen {
RenderSystem.translated(x, y, 0);
RenderSystem.rotatef(indexDiff * -75, 1, 0, 0);
RenderSystem.translated(0, 0, 5);
font.drawSplitString(title, 0, 0, left.x, ColorHelper.applyAlpha(textColor, 1 - indexDiff));
font.drawSplitString(title, 0, 0, left.x - 51, ColorHelper.applyAlpha(textColor, 1 - indexDiff));
RenderSystem.popMatrix();
if (chapter != null) {
@ -433,34 +478,42 @@ public class PonderUI extends AbstractSimiScreen {
}
if (identifyMode) {
RenderSystem.pushMatrix();
RenderSystem.translated(mouseX, mouseY, 100);
if (hoveredTooltipItem.isEmpty()) {
String tooltip = Lang
.createTranslationTextComponent(IDENTIFY_MODE,
new StringTextComponent(minecraft.gameSettings.keyBindDrop.getKeyBinding()
.getLocalizedName()).applyTextStyle(TextFormatting.WHITE))
.applyTextStyle(TextFormatting.GRAY)
.getFormattedText();
renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0);
} else
renderTooltip(hoveredTooltipItem, 0, 0);
if (hoveredBlockPos != null && PonderIndex.EDITOR_MODE) {
RenderSystem.translated(0, -15, 0);
boolean copied = copiedBlockPos != null && hoveredBlockPos.equals(copiedBlockPos);
String coords = new StringTextComponent(
hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ())
.applyTextStyles(copied ? TextFormatting.GREEN : TextFormatting.GOLD)
if (noWidgetsHovered) {
RenderSystem.pushMatrix();
RenderSystem.translated(mouseX, mouseY, 100);
if (hoveredTooltipItem.isEmpty()) {
String tooltip = Lang
.createTranslationTextComponent(IDENTIFY_MODE,
new StringTextComponent(minecraft.gameSettings.keyBindDrop.getKeyBinding()
.getLocalizedName()).applyTextStyle(TextFormatting.WHITE))
.applyTextStyle(TextFormatting.GRAY)
.getFormattedText();
renderTooltip(coords, 0, 0);
renderTooltip(font.listFormattedStringToWidth(tooltip, width / 3), 0, 0);
} else
renderTooltip(hoveredTooltipItem, 0, 0);
if (hoveredBlockPos != null && PonderIndex.EDITOR_MODE && !userViewMode) {
RenderSystem.translated(0, -15, 0);
boolean copied = copiedBlockPos != null && hoveredBlockPos.equals(copiedBlockPos);
String coords = new StringTextComponent(
hoveredBlockPos.getX() + ", " + hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ())
.applyTextStyles(copied ? TextFormatting.GREEN : TextFormatting.GOLD)
.getFormattedText();
renderTooltip(coords, 0, 0);
}
RenderSystem.popMatrix();
}
RenderSystem.popMatrix();
scan.flash();
} else {
scan.dim();
}
if (PonderIndex.EDITOR_MODE) {
if (userViewMode)
userMode.flash();
else
userMode.dim();
}
{
// Scene overlay
RenderSystem.pushMatrix();
@ -494,11 +547,16 @@ public class PonderUI extends AbstractSimiScreen {
int x = (width / 2) - 110;
int y = right.y + right.getHeight() + 4;
int w = width - 2 * x;
RenderSystem.pushMatrix();
RenderSystem.translated(0, 0, 400);
renderBox(x, y, w, 1, false);
RenderSystem.popMatrix();
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);
GuiUtils.drawGradientRect(500, 0, 3, 1, 4, 0x60ffeedd, 0x60ffeedd);
RenderSystem.popMatrix();
}
@ -602,8 +660,12 @@ public class PonderUI extends AbstractSimiScreen {
return true;
}
clipboardHelper.setClipboardString(handle, "util.grid.at(" + hoveredBlockPos.getX() + ", "
+ hoveredBlockPos.getY() + ", " + hoveredBlockPos.getZ() + ")");
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;
return true;
}
@ -773,8 +835,25 @@ public class PonderUI extends AbstractSimiScreen {
@Override
public void shareContextWith(AbstractSimiScreen other) {
if (other instanceof PonderUI)
((PonderUI) other).referredToByTag = referredToByTag;
if (other instanceof PonderUI) {
PonderUI ponderUI = (PonderUI) other;
ponderUI.referredToByTag = referredToByTag;
}
}
public static float getPartialTicks() {
if (Minecraft.getInstance().currentScreen instanceof PonderUI) {
PonderUI ui = (PonderUI) Minecraft.getInstance().currentScreen;
if (ui.identifyMode)
return ponderPartialTicksPaused;
}
return Minecraft.getInstance()
.getRenderPartialTicks();
}
@Override
public boolean isPauseScreen() {
return true;
}
}

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;
@ -140,9 +141,29 @@ public class SceneBuilder {
* assumes it to be square
*/
public void configureBasePlate(int xOffset, int zOffset, int basePlateSize) {
scene.offsetX = xOffset;
scene.offsetZ = zOffset;
scene.size = basePlateSize;
scene.basePlateOffsetX = xOffset;
scene.basePlateOffsetZ = zOffset;
scene.basePlateSize = basePlateSize;
}
/**
* Use this in case you are not happy with the scale of the scene relative to
* the overlay
*
* @param factor >1 will make the scene appear larger, smaller otherwise
*/
public void scaleSceneView(float factor) {
scene.scaleFactor = factor;
}
/**
* Use this in case you are not happy with the vertical alignment of the scene
* relative to the overlay
*
* @param yOffset >0 moves the scene up, down otherwise
*/
public void setSceneOffsetY(float yOffset) {
scene.yOffset = yOffset;
}
/**
@ -150,8 +171,10 @@ public class SceneBuilder {
* of the schematic's structure. Makes for a nice opener
*/
public void showBasePlate() {
world.showSection(scene.getSceneBuildingUtil().select.cuboid(new BlockPos(scene.offsetX, 0, scene.offsetZ),
new Vec3i(scene.size, 0, scene.size)), Direction.UP);
world.showSection(
scene.getSceneBuildingUtil().select.cuboid(new BlockPos(scene.basePlateOffsetX, 0, scene.basePlateOffsetZ),
new Vec3i(scene.basePlateSize, 0, scene.basePlateSize)),
Direction.UP);
}
/**
@ -284,6 +307,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 +382,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 +443,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));
}
@ -504,7 +547,7 @@ public class SceneBuilder {
return;
behaviour.handleInsertion(stack, insertionSide.getOpposite(), false);
});
flapFunnels(scene.getSceneBuildingUtil().select.position(location.up()), true);
flapFunnel(location.up(), true);
}
public ElementLink<BeltItemElement> createItemOnBelt(BlockPos beltLocation, Direction insertionSide,
@ -532,9 +575,8 @@ public class SceneBuilder {
scene.linkElement(tracker, link);
return TransportedResult.doNothing();
});
});
flapFunnels(scene.getSceneBuildingUtil().select.position(beltLocation.up()), true);
flapFunnel(beltLocation.up(), true);
return link;
}
@ -596,8 +638,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))
@ -613,11 +654,8 @@ public class SceneBuilder {
}, reDrawBlocks));
}
public void flapFunnels(Selection selection, boolean outward) {
addInstruction(new TileEntityDataInstruction(selection, FunnelTileEntity.class, nbt -> {
nbt.putInt("Flap", outward ? -1 : 1);
return nbt;
}, false));
public void flapFunnel(BlockPos position, boolean outward) {
modifyTileEntity(position, FunnelTileEntity.class, funnel -> funnel.flap(!outward));
}
}

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;
@ -22,6 +21,9 @@ public class BearingScenes {
public static void windmillsAsSource(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("windmill_source", "Generating Rotational Force using Windmill Bearings");
scene.configureBasePlate(1, 1, 5);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.fromTo(1, 0, 1, 5, 0, 5), Direction.UP);
scene.world.setBlock(util.grid.at(2, -1, 0), AllBlocks.SAIL.getDefaultState()
.with(SailBlock.FACING, Direction.NORTH), false);
@ -102,7 +104,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 +115,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);
@ -150,6 +147,8 @@ public class BearingScenes {
public static void windmillsAnyStructure(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("windmill_structure", "Windmill Contraptions");
scene.configureBasePlate(1, 1, 5);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
@ -186,13 +185,380 @@ 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.configureBasePlate(1, 1, 5);
scene.setSceneOffsetY(-1);
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");
scene.configureBasePlate(1, 1, 6);
scene.setSceneOffsetY(-1);
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()
.sharedText("behaviour_modify_wrench");
scene.idle(70);
scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f);
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))
.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");
scene.configureBasePlate(1, 1, 5);
scene.setSceneOffsetY(-1);
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);
}
public static void clockwork(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("clockwork_bearing", "Animating Structures using Clockwork Bearings");
Selection kinetics = util.select.fromTo(3, 3, 4, 3, 1, 6);
Selection largeCog = util.select.position(2, 0, 6);
BlockPos bearingPos = util.grid.at(3, 3, 3);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
scene.world.showSection(kinetics, Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.position(bearingPos), Direction.DOWN);
scene.idle(10);
scene.overlay.showSelectionWithText(util.select.position(bearingPos.north()), 60)
.colored(PonderPalette.GREEN)
.pointAt(util.vector.blockSurface(bearingPos, Direction.WEST))
.placeNearTarget()
.text("Clockwork Bearings attach to blocks in front of them");
scene.idle(50);
ElementLink<WorldSectionElement> plank =
scene.world.showIndependentSection(util.select.position(2, 3, 2), Direction.SOUTH);
scene.world.moveSection(plank, util.vector.of(1, 0, 0), 0);
scene.idle(20);
scene.world.rotateSection(plank, 0, 0, 60, 25);
scene.world.rotateBearing(bearingPos, 60, 25);
scene.world.setKineticSpeed(kinetics, 8);
scene.world.setKineticSpeed(largeCog, -4);
scene.idle(25);
scene.overlay.showText(80)
.pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH))
.placeNearTarget()
.text("Upon receiving Rotational Force, the structure will be rotated according to the hour of the day");
scene.idle(90);
scene.overlay.showText(30)
.pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH))
.placeNearTarget()
.text("3:00");
scene.world.rotateSection(plank, 0, 0, 30, 12);
scene.world.rotateBearing(bearingPos, 30, 12);
scene.idle(42);
scene.overlay.showText(30)
.pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH))
.placeNearTarget()
.text("4:00");
scene.world.rotateSection(plank, 0, 0, 30, 12);
scene.world.rotateBearing(bearingPos, 30, 12);
scene.idle(42);
InputWindowElement clickTheBearing = new InputWindowElement(util.vector.topOf(bearingPos), Pointing.DOWN);
InputWindowElement clickTheBearingSide =
new InputWindowElement(util.vector.blockSurface(bearingPos, Direction.WEST), Pointing.LEFT);
scene.overlay.showControls(clickTheBearing.rightClick(), 60);
scene.idle(7);
scene.world.rotateSection(plank, 0, 0, -120, 0);
scene.world.rotateBearing(bearingPos, -120, 0);
scene.overlay.showText(60)
.pointAt(util.vector.blockSurface(bearingPos, Direction.WEST))
.placeNearTarget()
.text("Right-Click the bearing to start or stop animating the structure");
scene.idle(70);
scene.world.hideIndependentSection(plank, Direction.NORTH);
scene.idle(15);
ElementLink<WorldSectionElement> hourHand =
scene.world.showIndependentSection(util.select.fromTo(3, 3, 1, 3, 5, 2), Direction.SOUTH);
scene.world.configureCenterOfRotation(hourHand, util.vector.centerOf(bearingPos));
scene.idle(15);
scene.overlay.showSelectionWithText(util.select.fromTo(3, 3, 1, 3, 4, 2), 80)
.placeNearTarget()
.sharedText("movement_anchors");
scene.idle(90);
scene.overlay.showControls(clickTheBearingSide.rightClick(), 20);
scene.idle(7);
scene.world.rotateSection(hourHand, 0, 0, 120, 50);
scene.world.rotateBearing(bearingPos, 120, 50);
scene.idle(60);
scene.overlay.showSelectionWithText(util.select.position(bearingPos.north(3)), 80)
.placeNearTarget()
.colored(PonderPalette.BLUE)
.text("In front of the Hour Hand, a second structure can be added");
scene.idle(90);
scene.overlay.showControls(clickTheBearingSide.rightClick(), 20);
scene.idle(7);
scene.world.rotateSection(hourHand, 0, 0, -120, 0);
scene.world.rotateBearing(bearingPos, -120, 0);
scene.idle(10);
ElementLink<WorldSectionElement> minuteHand =
scene.world.showIndependentSection(util.select.fromTo(3, 3, 0, 3, 6, 0), Direction.SOUTH);
scene.world.configureCenterOfRotation(minuteHand, util.vector.centerOf(bearingPos));
scene.idle(30);
scene.overlay.showOutline(PonderPalette.BLUE, minuteHand, util.select.fromTo(3, 3, 0, 3, 6, 0), 85);
scene.overlay.showSelectionWithText(util.select.fromTo(3, 3, 1, 3, 4, 2), 80)
.placeNearTarget()
.colored(PonderPalette.GREEN)
.text("Ensure the two Structures are not attached to each other through super glue or similar");
scene.idle(90);
scene.overlay.showControls(clickTheBearingSide.rightClick(), 20);
scene.idle(7);
scene.world.rotateSection(hourHand, 0, 0, 120, 50);
scene.world.rotateSection(minuteHand, 0, 0, 180, 75);
scene.world.rotateBearing(bearingPos, 120, 50);
scene.idle(90);
scene.world.rotateSection(minuteHand, 0, 0, 6, 3);
scene.overlay.showText(80)
.placeNearTarget()
.pointAt(util.vector.blockSurface(bearingPos.north(3), Direction.NORTH))
.colored(PonderPalette.GREEN)
.text("The Second Structure will now rotate as the Minute Hand");
scene.markAsFinished();
for (int i = 0; i < 40; i++) {
scene.idle(23);
scene.world.rotateSection(minuteHand, 0, 0, 6, 3);
if (i == 29)
scene.world.rotateSection(hourHand, 0, 0, 30, 20);
}
}
}

View file

@ -161,6 +161,7 @@ public class BeltScenes {
public static void directions(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("belt_directions", "Valid Orientations for Mechanical Belts");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.showBasePlate();
scene.idle(5);
@ -305,6 +306,7 @@ public class BeltScenes {
public static void transport(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("belt_transport", "Using Mechanical Belts for Logistics");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -.6f * f);
scene.showBasePlate();
scene.idle(5);
@ -379,6 +381,7 @@ public class BeltScenes {
public static void beltsCanBeEncased(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("belt_casing", "Encasing Belts");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.showBasePlate();
scene.idle(5);
scene.world.showSection(util.select.layersFrom(1), Direction.DOWN);

View file

@ -92,7 +92,8 @@ public class ChainDriveScenes {
public static void adjustableChainGearshift(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("chain_gearshift", "Controlling rotational speed with Chain Gearshifts");
scene.configureBasePlate(0, 0, 7);
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.layer(0), Direction.UP);
BlockPos leverPos = util.grid.at(3, 1, 0);

View file

@ -52,12 +52,11 @@ public class FunnelScenes {
BlockPos entryBeltPos = util.grid.at(3, 1, 2);
BlockPos exitBeltPos = util.grid.at(1, 1, 2);
ItemStack itemStack = AllBlocks.BRASS_BLOCK.asStack();
Selection exitFunnel = util.select.position(exitBeltPos.up());
for (int i = 0; i < 8; i++) {
scene.idle(8);
scene.world.removeItemsFromBelt(exitBeltPos);
scene.world.flapFunnels(exitFunnel, false);
scene.world.flapFunnel(exitBeltPos.up(), false);
if (i == 2)
scene.rotateCameraY(70);
if (i < 6)
@ -94,7 +93,7 @@ public class FunnelScenes {
for (int i = 0; i < 3; i++) {
scene.idle(8);
scene.world.flapFunnels(outputFunnel, false);
scene.world.flapFunnel(util.grid.at(1, 2, 4), false);
scene.world.createItemEntity(sideItemSpawn, util.vector.of(-.05, 0, 0), itemStack);
}
@ -198,7 +197,7 @@ public class FunnelScenes {
scene.idle(20);
scene.world.flapFunnels(sideFunnelSelection, true);
scene.world.flapFunnel(sideFunnel, true);
itemLink = scene.world.createItemEntity(sideCenter.subtract(0, .45, 0), util.vector.of(0, 0, -0.1), itemStack);
scene.idle(60);
scene.world.hideSection(sideFunnelSelection, Direction.UP);
@ -233,7 +232,7 @@ public class FunnelScenes {
scene.idle(35);
scene.world.removeItemsFromBelt(beltPos);
scene.world.flapFunnels(beltFunnelSetup, false);
scene.world.flapFunnel(util.grid.at(2, 2, 2), false);
if (i == 0) {
scene.idle(50);
@ -374,7 +373,7 @@ public class FunnelScenes {
scene.idle(10);
scene.world.createItemOnBeltLike(andesiteFunnel.down()
.north(), Direction.SOUTH, itemStack);
scene.world.flapFunnels(util.select.position(andesiteFunnel), true);
scene.world.flapFunnel(andesiteFunnel, true);
scene.idle(60);
scene.overlay.showText(60)
@ -384,7 +383,7 @@ public class FunnelScenes {
scene.idle(10);
scene.world.createItemOnBeltLike(brassFunnel.down()
.north(), Direction.SOUTH, ItemHandlerHelper.copyStackWithSize(itemStack, 64));
scene.world.flapFunnels(util.select.position(brassFunnel), true);
scene.world.flapFunnel(brassFunnel, true);
scene.idle(60);
AxisAlignedBB filterSlot = new AxisAlignedBB(brassFunnel).grow(-.35, -.35, -.35)
@ -421,7 +420,7 @@ public class FunnelScenes {
if (i > 0 && (i < 3 || i % 3 == 0)) {
scene.world.removeItemsFromBelt(brassFunnel.down());
scene.world.flapFunnels(util.select.position(brassFunnel), false);
scene.world.flapFunnel(brassFunnel, false);
}
scene.world.modifyEntities(ItemEntity.class, e -> {

View file

@ -241,6 +241,7 @@ public class GantryScenes {
public static void subgantry(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("gantry_cascaded", "Cascaded Gantries");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -2 * f);
scene.world.showSection(util.select.layer(0)
.add(util.select.column(5, 3))

View file

@ -279,6 +279,8 @@ public class KineticsScenes {
public static void gearbox(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("gearbox", "Relaying rotational force using Gearboxes");
scene.configureBasePlate(1, 1, 5);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.world.showSection(util.select.fromTo(4, 1, 6, 3, 2, 5), Direction.UP);
scene.idle(10);

View file

@ -22,7 +22,9 @@ public class MovementActorScenes {
public static void psiTransfer(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("portable_storage_interface", "Contraption Storage Exchange");
scene.configureBasePlate(0, 0, 8);
scene.configureBasePlate(0, 0, 6);
scene.scaleSceneView(0.95f);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
@ -112,7 +114,7 @@ public class MovementActorScenes {
scene.world.modifyEntity(entity2, Entity::remove);
scene.overlay
.showControls(new InputWindowElement(util.vector.topOf(6, 3, 2), Pointing.DOWN).withItem(itemStack), 40);
.showControls(new InputWindowElement(util.vector.topOf(5, 3, 2), Pointing.DOWN).withItem(itemStack), 40);
scene.idle(30);
scene.world.hideSection(util.select.position(hopper), Direction.UP);
@ -148,7 +150,8 @@ public class MovementActorScenes {
public static void psiRedstone(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("portable_storage_interface_redstone", "Redstone Control");
scene.configureBasePlate(0, 0, 6);
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
Class<PortableItemInterfaceTileEntity> psiClass = PortableItemInterfaceTileEntity.class;
Selection psis = util.select.fromTo(1, 1, 3, 1, 3, 3);

View file

@ -0,0 +1,279 @@
package com.simibubi.create.foundation.ponder.content;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock;
import com.simibubi.create.foundation.ponder.ElementLink;
import com.simibubi.create.foundation.ponder.SceneBuilder;
import com.simibubi.create.foundation.ponder.SceneBuildingUtil;
import com.simibubi.create.foundation.ponder.Selection;
import com.simibubi.create.foundation.ponder.elements.InputWindowElement;
import com.simibubi.create.foundation.ponder.elements.ParrotElement;
import com.simibubi.create.foundation.ponder.elements.ParrotElement.FaceCursorPose;
import com.simibubi.create.foundation.ponder.elements.WorldSectionElement;
import com.simibubi.create.foundation.utility.Pointing;
import net.minecraft.block.Blocks;
import net.minecraft.block.DoublePlantBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.state.properties.DoubleBlockHalf;
import net.minecraft.state.properties.PistonType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public class PistonScenes {
public static void movement(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("mechanical_piston", "Moving Structures using Mechanical Pistons");
scene.configureBasePlate(0, 0, 5);
scene.world.showSection(util.select.layer(0)
.add(util.select.position(0, 1, 2)), Direction.UP);
Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2);
BlockPos piston = util.grid.at(3, 1, 2);
BlockPos leverPos = util.grid.at(3, 2, 4);
BlockPos shaft = util.grid.at(3, 1, 3);
scene.idle(5);
scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.position(piston), Direction.DOWN);
ElementLink<WorldSectionElement> contraption =
scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN);
scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0);
scene.idle(20);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.east()), Direction.DOWN, contraption);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.east(2)), Direction.DOWN, contraption);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.west()), Direction.DOWN, contraption);
scene.idle(15);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40);
scene.overlay.showText(55)
.pointAt(util.vector.topOf(piston))
.placeNearTarget()
.text("Mechanical Pistons can move blocks in front of them");
scene.idle(65);
scene.overlay.showText(45)
.pointAt(util.vector.blockSurface(shaft, Direction.SOUTH))
.placeNearTarget()
.text("Speed and direction of movement depend on the Rotational Input");
scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false);
scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.OAK_PLANKS.getDefaultState(), false);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40);
scene.idle(60);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(piston, Direction.WEST), Pointing.DOWN).rightClick()
.withItem(new ItemStack(Items.SLIME_BALL)),
30);
scene.idle(7);
scene.world.modifyBlock(piston.north(), s -> s.with(MechanicalPistonHeadBlock.TYPE, PistonType.STICKY), false);
scene.effects.superGlue(piston, Direction.WEST, true);
scene.idle(33);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40);
scene.idle(25);
scene.overlay.showText(60)
.pointAt(util.vector.topOf(piston))
.placeNearTarget()
.text("Sticky Mechanical Pistons can pull the attached blocks back");
scene.idle(20);
scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.OAK_PLANKS.getDefaultState(), false);
scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.AIR.getDefaultState(), false);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40);
scene.idle(50);
scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false);
ElementLink<WorldSectionElement> chassis =
scene.world.showIndependentSection(util.select.fromTo(2, 2, 0, 2, 3, 2), Direction.DOWN);
scene.world.moveSection(chassis, util.vector.of(0, -1, 1), 0);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(1, 2, 0), Direction.EAST, chassis);
scene.idle(15);
scene.effects.superGlue(piston.west()
.north(), Direction.WEST, true);
scene.overlay.showText(80)
.pointAt(util.vector.topOf(piston.west()))
.placeNearTarget()
.sharedText("movement_anchors");
scene.idle(90);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40);
scene.world.moveSection(chassis, util.vector.of(-2, 0, 0), 40);
}
public static void poles(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("piston_pole", "Piston Extension Poles");
scene.configureBasePlate(0, 0, 5);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f);
Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2);
BlockPos piston = util.grid.at(3, 1, 2);
scene.idle(5);
scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.position(piston), Direction.DOWN);
ElementLink<WorldSectionElement> contraption =
scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN);
scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0);
scene.idle(20);
BlockPos leverPos = util.grid.at(3, 2, 4);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.setKineticSpeed(kinetics, 16);
scene.idle(10);
scene.overlay.showSelectionWithText(util.select.position(piston), 50)
.colored(PonderPalette.RED)
.placeNearTarget()
.text("Without attached Poles, a Mechanical Piston cannot move");
scene.idle(60);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.setKineticSpeed(kinetics, 0);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.east()), Direction.DOWN, contraption);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.east(2)), Direction.DOWN, contraption);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.RED, new Object(), util.select.fromTo(piston.east(), piston.east(2)),
100);
scene.overlay.showSelectionWithText(util.select.fromTo(piston.west(), piston.west(2)), 100)
.text("The Length of pole added at its back determines the Extension Range")
.placeNearTarget()
.colored(PonderPalette.GREEN);
scene.idle(110);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.west()), Direction.EAST, contraption);
scene.idle(10);
ElementLink<ParrotElement> birb =
scene.special.createBirb(util.vector.topOf(piston.west()), FaceCursorPose::new);
scene.idle(15);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.setKineticSpeed(kinetics, 16);
scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40);
scene.special.moveParrot(birb, util.vector.of(-2, 0, 0), 40);
}
public static void movementModes(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("mechanical_piston_modes", "Movement Modes of the Mechanical Piston");
scene.configureBasePlate(0, 0, 5);
Selection rose = util.select.fromTo(0, 2, 2, 0, 1, 2);
scene.world.showSection(util.select.layer(0)
.add(rose), Direction.UP);
Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2);
BlockPos piston = util.grid.at(3, 1, 2);
BlockPos leverPos = util.grid.at(3, 2, 4);
BlockPos shaft = util.grid.at(3, 1, 3);
scene.idle(5);
scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.position(piston), Direction.DOWN);
ElementLink<WorldSectionElement> contraption =
scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN);
scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0);
scene.idle(20);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.east()), Direction.DOWN, contraption);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.east(2)), Direction.DOWN, contraption);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.west()), Direction.DOWN, contraption);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(piston.north()
.west()
.up()), Direction.DOWN, contraption);
scene.idle(15);
scene.effects.superGlue(piston.west(), Direction.UP, true);
scene.idle(10);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40);
scene.idle(40);
scene.world.destroyBlock(util.grid.at(0, 1, 2));
scene.world.destroyBlock(util.grid.at(0, 2, 2));
scene.idle(10);
scene.overlay.showSelectionWithText(rose, 70)
.text("Whenever Pistons stop moving, the moved structure reverts to blocks")
.colored(PonderPalette.RED);
scene.idle(80);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40);
scene.world.hideSection(rose, Direction.UP);
scene.idle(50);
scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.ROSE_BUSH.getDefaultState(), false);
scene.world.setBlock(util.grid.at(0, 2, 2), Blocks.ROSE_BUSH.getDefaultState()
.with(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER), false);
scene.world.showIndependentSection(rose, Direction.DOWN);
scene.overlay.showCenteredScrollInput(piston, Direction.UP, 60);
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(piston), Pointing.DOWN).scroll()
.withWrench(), 60);
scene.overlay.showText(70)
.pointAt(util.vector.topOf(piston))
.placeNearTarget()
.sharedText("behaviour_modify_wrench");
scene.idle(80);
scene.effects.indicateRedstone(leverPos);
scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down()));
scene.world.modifyKineticSpeed(kinetics, f -> -f);
scene.effects.rotationDirectionIndicator(shaft);
scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40);
scene.idle(50);
scene.overlay.showText(120)
.colored(PonderPalette.GREEN)
.pointAt(util.vector.blockSurface(util.grid.at(0, 1, 2), Direction.WEST))
.placeNearTarget()
.text("It can be configured never to revert to solid blocks, or only at the location it started at");
}
}

View file

@ -77,12 +77,42 @@ public class PonderIndex {
.addStoryBoard("funnels/transposer", FunnelScenes::transposer);
PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass);
// Mechanical Piston
PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON)
.addStoryBoard("mechanical_piston/anchor", PistonScenes::movement, PonderTag.KINETIC_APPLIANCES,
PonderTag.MOVEMENT_ANCHOR);
PonderRegistry
.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON,
AllBlocks.PISTON_EXTENSION_POLE)
.addStoryBoard("mechanical_piston/piston_pole", PistonScenes::poles);
PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON)
.addStoryBoard("mechanical_piston/modes", PistonScenes::movementModes);
// Windmill Bearing
PonderRegistry.forComponents(AllBlocks.ROPE_PULLEY)
.addStoryBoard("rope_pulley/anchor", PulleyScenes::movement, PonderTag.KINETIC_APPLIANCES,
PonderTag.MOVEMENT_ANCHOR)
.addStoryBoard("rope_pulley/modes", PulleyScenes::movementModes)
.addStoryBoard("rope_pulley/attachment", PulleyScenes::attachment);
// Windmill Bearing
PonderRegistry.forComponents(AllBlocks.WINDMILL_BEARING)
.addStoryBoard("windmill_bearing/source", BearingScenes::windmillsAsSource, PonderTag.KINETIC_SOURCES)
.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);
// Clockwork Bearing
PonderRegistry.addStoryBoard(AllBlocks.CLOCKWORK_BEARING, "clockwork_bearing", BearingScenes::clockwork,
PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR);
// Gantries
PonderRegistry.addStoryBoard(AllBlocks.GANTRY_SHAFT, "gantry/intro", GantryScenes::introForShaft,
PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR);

View file

@ -49,43 +49,39 @@ public class PonderIndexScreen extends AbstractSimiScreen {
protected void init() {
super.init();
//populate lists
// populate lists
widgets.clear();
chapters.clear();
//chapters.addAll(PonderRegistry.chapters.getAllChapters());
// chapters.addAll(PonderRegistry.chapters.getAllChapters());
items.clear();
PonderRegistry.all.keySet()
.stream()
.map(key -> {
Item item = ForgeRegistries.ITEMS.getValue(key);
if (item == null) {
Block b = ForgeRegistries.BLOCKS.getValue(key);
if (b != null)
item = b.asItem();
}
return item;
})
.filter(Objects::nonNull)
.filter(PonderIndexScreen::exclusions)
.forEach(items::add);
.stream()
.map(key -> {
Item item = ForgeRegistries.ITEMS.getValue(key);
if (item == null) {
Block b = ForgeRegistries.BLOCKS.getValue(key);
if (b != null)
item = b.asItem();
}
return item;
})
.filter(Objects::nonNull)
.filter(PonderIndexScreen::exclusions)
.forEach(items::add);
boolean hasChapters = !chapters.isEmpty();
//setup chapters
LayoutHelper layout = LayoutHelper.centeredHorizontal(
chapters.size(),
MathHelper.clamp((int) Math.ceil(chapters.size() / 4f), 1, 4),
200,
38,
16
);
// setup chapters
LayoutHelper layout = LayoutHelper.centeredHorizontal(chapters.size(),
MathHelper.clamp((int) Math.ceil(chapters.size() / 4f), 1, 4), 200, 38, 16);
chapterArea = layout.getArea();
int chapterCenterX = (int) (width * chapterXmult);
int chapterCenterY = (int) (height * chapterYmult);
//todo at some point pagination or horizontal scrolling may be needed for chapters/items
// todo at some point pagination or horizontal scrolling may be needed for
// chapters/items
for (PonderChapter chapter : chapters) {
ChapterLabel label = new ChapterLabel(chapter, chapterCenterX + layout.getX(),
chapterCenterY + layout.getY(), (mouseX, mouseY) -> {
@ -97,44 +93,40 @@ public class PonderIndexScreen extends AbstractSimiScreen {
layout.next();
}
//setup items
// setup items
if (!hasChapters) {
itemYmult = 0.5;
}
int maxItemRows = hasChapters ? 4 : 7;
layout = LayoutHelper.centeredHorizontal(
items.size(),
MathHelper.clamp((int) Math.ceil(items.size() / 11f), 1, maxItemRows),
28,
28,
8
);
layout = LayoutHelper.centeredHorizontal(items.size(),
MathHelper.clamp((int) Math.ceil(items.size() / 11f), 1, maxItemRows), 28, 28, 8);
itemArea = layout.getArea();
int itemCenterX = (int) (width * itemXmult);
int itemCenterY = (int) (height * itemYmult);
for (Item item : items) {
PonderButton button = new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return;
PonderButton button =
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (x, y) -> {
if (!PonderRegistry.all.containsKey(item.getRegistryName()))
return;
centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
}).showing(new ItemStack(item));
centerScalingOn(x, y);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(item)));
}).showing(new ItemStack(item));
button.fade(1);
widgets.add(button);
layout.next();
}
}
private static boolean exclusions(Item item) {
if (item instanceof BlockItem) {
Block block = ((BlockItem) item).getBlock();
if (block instanceof ValveHandleBlock && !AllBlocks.COPPER_VALVE_HANDLE.is(item)) return false;
if (block instanceof ValveHandleBlock && !AllBlocks.COPPER_VALVE_HANDLE.is(item))
return false;
}
return true;
@ -143,6 +135,7 @@ public class PonderIndexScreen extends AbstractSimiScreen {
@Override
public void tick() {
super.tick();
PonderUI.ponderTicks++;
hoveredItem = ItemStack.EMPTY;
MainWindow w = minecraft.getWindow();
@ -224,4 +217,9 @@ public class PonderIndexScreen extends AbstractSimiScreen {
public ItemStack getHoveredTooltipItem() {
return hoveredItem;
}
@Override
public boolean isPauseScreen() {
return true;
}
}

View file

@ -77,13 +77,16 @@ public class PonderTagScreen extends AbstractSimiScreen {
int itemCenterY = getItemsY();
for (Item i : items) {
final boolean canClick = PonderRegistry.all.containsKey(i.getRegistryName());
PonderButton button =
new PonderButton(itemCenterX + layout.getX() + 4, itemCenterY + layout.getY() + 4, (mouseX, mouseY) -> {
if (!PonderRegistry.all.containsKey(i.getRegistryName()))
if (!canClick)
return;
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag));
}).showing(new ItemStack(i));
if (!canClick)
button.noClickEvent();
button.fade(1);
widgets.add(button);
@ -92,18 +95,20 @@ public class PonderTagScreen extends AbstractSimiScreen {
if (!tag.getMainItem()
.isEmpty()) {
final boolean canClick = PonderRegistry.all.containsKey(tag.getMainItem()
.getItem()
.getRegistryName());
PonderButton button =
new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10, (mouseX, mouseY) -> {
if (!PonderRegistry.all.containsKey(tag.getMainItem()
.getItem()
.getRegistryName()))
if (!canClick)
return;
centerScalingOn(mouseX, mouseY);
ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag));
}).showing(tag.getMainItem());
if (!canClick)
button.noClickEvent();
button.fade(1);
// button.flash();
widgets.add(button);
}
@ -133,6 +138,7 @@ public class PonderTagScreen extends AbstractSimiScreen {
@Override
public void tick() {
super.tick();
PonderUI.ponderTicks++;
hoveredItem = ItemStack.EMPTY;
MainWindow w = minecraft.getWindow();
@ -291,5 +297,10 @@ public class PonderTagScreen extends AbstractSimiScreen {
return tag == ((PonderTagScreen) other).tag;
return super.isEquivalentTo(other);
}
@Override
public boolean isPauseScreen() {
return true;
}
}

View file

@ -0,0 +1,227 @@
package com.simibubi.create.foundation.ponder.content;
import com.simibubi.create.foundation.ponder.ElementLink;
import com.simibubi.create.foundation.ponder.SceneBuilder;
import com.simibubi.create.foundation.ponder.SceneBuildingUtil;
import com.simibubi.create.foundation.ponder.Selection;
import com.simibubi.create.foundation.ponder.elements.InputWindowElement;
import com.simibubi.create.foundation.ponder.elements.WorldSectionElement;
import com.simibubi.create.foundation.utility.Pointing;
import net.minecraft.block.Blocks;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public class PulleyScenes {
public static void movement(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("rope_pulley", "Moving Structures using Rope Pulleys");
scene.configureBasePlate(0, 0, 5);
scene.scaleSceneView(0.95f);
scene.setSceneOffsetY(-1);
Selection reversable = util.select.fromTo(2, 3, 4, 2, 4, 2);
BlockPos leverPos = util.grid.at(1, 2, 4);
BlockPos pulleyPos = util.grid.at(2, 4, 2);
Selection redstoneStuff = util.select.fromTo(leverPos, leverPos.east());
scene.world.showSection(util.select.layer(0), Direction.UP);
ElementLink<WorldSectionElement> plank =
scene.world.showIndependentSection(util.select.position(2, 1, 2), Direction.UP);
scene.idle(5);
scene.world.showSection(util.select.fromTo(1, 4, 3, 2, 1, 4), Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.position(pulleyPos), Direction.SOUTH);
scene.idle(20);
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, 2, 40);
scene.idle(45);
scene.overlay.showText(60)
.pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST))
.text("Rope Pulleys can move blocks vertically when given Rotational Force")
.placeNearTarget();
scene.idle(70);
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, -2, 40);
scene.world.moveSection(plank, util.vector.of(0, 2, 0), 40);
scene.idle(60);
scene.overlay.showText(60)
.pointAt(util.vector.blockSurface(pulleyPos, Direction.SOUTH))
.text("Direction and Speed of movement depend on the Rotational Input")
.placeNearTarget();
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, 2, 40);
scene.world.moveSection(plank, util.vector.of(0, -2, 0), 40);
scene.idle(50);
scene.world.hideIndependentSection(plank, Direction.NORTH);
scene.idle(15);
ElementLink<WorldSectionElement> chassis =
scene.world.showIndependentSection(util.select.fromTo(2, 1, 1, 0, 2, 1), Direction.SOUTH);
scene.world.moveSection(chassis, util.vector.of(1, 0, 1), 0);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(2, 1, 0), Direction.SOUTH, chassis);
scene.idle(15);
scene.effects.superGlue(util.grid.at(3, 1, 1), Direction.SOUTH, true);
scene.overlay.showText(80)
.pointAt(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.NORTH))
.placeNearTarget()
.sharedText("movement_anchors");
scene.idle(90);
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, -2, 40);
scene.world.moveSection(chassis, util.vector.of(0, 2, 0), 40);
scene.idle(50);
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, 2, 40);
scene.world.moveSection(chassis, util.vector.of(0, -2, 0), 40);
scene.idle(50);
}
public static void movementModes(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("rope_pulley_modes", "Movement Modes of the Rope Pulley");
scene.configureBasePlate(0, 0, 5);
scene.scaleSceneView(0.95f);
scene.setSceneOffsetY(-1);
Selection reversable = util.select.fromTo(2, 3, 4, 2, 4, 2);
BlockPos leverPos = util.grid.at(1, 2, 4);
BlockPos pulleyPos = util.grid.at(2, 4, 2);
Selection redstoneStuff = util.select.fromTo(leverPos, leverPos.east());
BlockPos flowerPos = util.grid.at(2, 1, 2);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.world.showSection(util.select.position(flowerPos), Direction.UP);
scene.idle(5);
scene.world.showSection(util.select.fromTo(1, 4, 3, 2, 1, 4), Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.position(pulleyPos), Direction.SOUTH);
ElementLink<WorldSectionElement> glass =
scene.world.showIndependentSection(util.select.position(pulleyPos.down()), Direction.UP);
scene.idle(20);
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, 2, 40);
scene.world.moveSection(glass, util.vector.of(0, -2, 0), 40);
scene.idle(40);
scene.world.destroyBlock(flowerPos);
scene.idle(10);
scene.overlay.showSelectionWithText(util.select.position(flowerPos), 70)
.text("Whenever Pulleys stop moving, the moved structure reverts to blocks")
.placeNearTarget()
.colored(PonderPalette.RED);
scene.idle(80);
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, -2, 40);
scene.world.moveSection(glass, util.vector.of(0, 2, 0), 40);
scene.world.hideSection(util.select.position(flowerPos), Direction.DOWN);
scene.idle(40);
scene.world.setBlock(flowerPos, Blocks.BLUE_ORCHID.getDefaultState(), false);
scene.world.showSection(util.select.position(flowerPos), Direction.DOWN);
scene.overlay.showCenteredScrollInput(pulleyPos, Direction.UP, 60);
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(pulleyPos), Pointing.DOWN).scroll()
.withWrench(), 60);
scene.overlay.showText(70)
.pointAt(util.vector.topOf(pulleyPos))
.placeNearTarget()
.sharedText("behaviour_modify_wrench");
scene.idle(80);
scene.world.toggleRedstonePower(redstoneStuff);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyKineticSpeed(reversable, f -> -f);
scene.effects.rotationDirectionIndicator(pulleyPos.south());
scene.world.movePulley(pulleyPos, 2, 40);
scene.world.moveSection(glass, util.vector.of(0, -2, 0), 40);
scene.idle(50);
scene.overlay.showText(120)
.colored(PonderPalette.GREEN)
.pointAt(util.vector.blockSurface(flowerPos, Direction.WEST))
.placeNearTarget()
.text("It can be configured never to revert to solid blocks, or only at the location it started at");
}
public static void attachment(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("rope_pulley_attachment", "Moving Pulleys as part of a Contraption");
scene.configureBasePlate(0, 0, 5);
scene.scaleSceneView(0.95f);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
Selection kinetics = util.select.fromTo(4, 3, 2, 4, 1, 5);
Selection largeCog = util.select.position(3, 0, 5);
scene.world.showSection(kinetics, Direction.DOWN);
ElementLink<WorldSectionElement> poles =
scene.world.showIndependentSection(util.select.fromTo(4, 4, 2, 6, 4, 2), Direction.DOWN);
scene.world.moveSection(poles, util.vector.of(0, -1, 0), 0);
scene.idle(10);
BlockPos pulleyPos = util.grid.at(3, 3, 2);
ElementLink<WorldSectionElement> pulley =
scene.world.showIndependentSection(util.select.position(pulleyPos), Direction.EAST);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.fromTo(3, 1, 1, 3, 1, 2)
.add(util.select.position(3, 2, 1)), Direction.SOUTH, pulley);
scene.idle(10);
scene.overlay.showText(50)
.pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST))
.placeNearTarget()
.text("Whenever Pulleys are themselves being moved by a Contraption...");
scene.idle(60);
scene.world.setKineticSpeed(largeCog, -16);
scene.world.setKineticSpeed(kinetics, 32);
scene.effects.rotationDirectionIndicator(util.grid.at(4, 1, 5));
scene.world.moveSection(poles, util.vector.of(-2, 0, 0), 40);
scene.world.moveSection(pulley, util.vector.of(-2, 0, 0), 40);
scene.idle(40);
scene.overlay.showSelectionWithText(util.select.fromTo(1, 1, 1, 1, 1, 2), 50)
.colored(PonderPalette.GREEN)
.placeNearTarget()
.text("...its attached structure will be dragged with it");
scene.idle(60);
scene.overlay.showText(80)
.colored(PonderPalette.RED)
.pointAt(util.vector.topOf(pulleyPos.west(2)))
.placeNearTarget()
.text("Mind that pulleys are only movable while stopped");
}
}

View file

@ -16,6 +16,7 @@ public class SharedText {
add("rpm32", "32 RPM");
add("movement_anchors", "With the help of Chassis or Super Glue, larger structures can be moved.");
add("behaviour_modify_wrench", "This behaviour can be modified using a Wrench");
}

View file

@ -6,9 +6,9 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.PonderUI;
import com.simibubi.create.foundation.ponder.PonderWorld;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.client.MainWindow;
@ -170,7 +170,7 @@ public class ParrotElement extends AnimatedSceneElement {
.length();
entity.onGround = false;
double phase = Math.min(length * 15, 8);
float f = (float) ((AnimationTickHolder.getTicks() % 100) * phase);
float f = (float) ((PonderUI.ponderTicks % 100) * phase);
entity.flapSpeed = MathHelper.sin(f) + 1;
if (length == 0)
entity.flapSpeed = 0;

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);
}
}
}
@ -287,10 +313,9 @@ public class WorldSectionElement extends AnimatedSceneElement {
transformMS(ms, pt);
RenderSystem.disableTexture();
WorldRenderer.drawBox(ms, buffer.getBuffer(RenderType.getLines()), shape.getBoundingBox()
.offset(selectedBlock), 1, 1, 1, 1);
if (buffer instanceof SuperRenderTypeBuffer)
((SuperRenderTypeBuffer) buffer).draw(RenderType.getLines());
RenderSystem.enableTexture();
.offset(selectedBlock), 1, 1, 1, 0.6f);
// if (buffer instanceof SuperRenderTypeBuffer)
// ((SuperRenderTypeBuffer) buffer).draw(RenderType.getLines());
ms.pop();
}

View file

@ -4,7 +4,7 @@ import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Function;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.IBearingTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity;
import com.simibubi.create.foundation.ponder.PonderScene;
import com.simibubi.create.foundation.ponder.PonderWorld;
@ -24,14 +24,14 @@ public class AnimateTileEntityInstruction extends TickingInstruction {
public static AnimateTileEntityInstruction bearing(BlockPos location, float totalDelta, int ticks) {
return new AnimateTileEntityInstruction(location, totalDelta, ticks,
(w, f) -> castIfPresent(w, location, MechanicalBearingTileEntity.class).ifPresent(bte -> bte.setAngle(f)),
(w) -> castIfPresent(w, location, MechanicalBearingTileEntity.class).map(bte -> bte.getInterpolatedAngle(0))
(w, f) -> castIfPresent(w, location, IBearingTileEntity.class).ifPresent(bte -> bte.setAngle(f)),
(w) -> castIfPresent(w, location, IBearingTileEntity.class).map(bte -> bte.getInterpolatedAngle(0))
.orElse(0f));
}
public static AnimateTileEntityInstruction pulley(BlockPos location, float totalDelta, int ticks) {
return new AnimateTileEntityInstruction(location, totalDelta, ticks,
(w, f) -> castIfPresent(w, location, PulleyTileEntity.class).ifPresent(pulley -> pulley.offset = f),
(w, f) -> castIfPresent(w, location, PulleyTileEntity.class).ifPresent(pulley -> pulley.animateOffset(f)),
(w) -> castIfPresent(w, location, PulleyTileEntity.class).map(pulley -> pulley.offset)
.orElse(0f));
}

View file

@ -3,27 +3,40 @@ 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
protected void firstTick(PonderScene scene) {
super.firstTick(scene);
mergeOnto.ifPresent(wse -> element.setAnimatedOffset(wse.get()
.getAnimatedOffset(), true));
element.set(initialSelection);
element.setVisible(true);
}
@ -34,6 +47,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());
}
}

View file

@ -14,5 +14,10 @@ public class MarkAsFinishedInstruction extends PonderInstruction {
public void tick(PonderScene scene) {
scene.setFinished(true);
}
@Override
public void onScheduled(PonderScene scene) {
scene.stopCounting();
}
}

View file

@ -7,7 +7,6 @@ import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.IScreenRenderable;
import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget;
import com.simibubi.create.foundation.ponder.PonderUI;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.LerpedFloat;
@ -26,6 +25,7 @@ public class PonderButton extends AbstractSimiWidget {
private float fade;
private KeyBinding shortcut;
private LerpedFloat flash;
private boolean noClickEvent;
public static final int SIZE = 20;
@ -54,6 +54,11 @@ public class PonderButton extends AbstractSimiWidget {
return this;
}
public PonderButton noClickEvent() {
this.noClickEvent = true;
return this;
}
public PonderButton shortcut(KeyBinding key) {
this.shortcut = key;
return this;
@ -86,7 +91,7 @@ public class PonderButton extends AbstractSimiWidget {
if (fade < .1f)
return;
isHovered = mouseX >= x && mouseY >= y && mouseX < x + width && mouseY < y + height && fade > .75f;
isHovered = isMouseOver(mouseX, mouseY) && fade > .75f;
RenderSystem.pushMatrix();
RenderSystem.disableDepthTest();
@ -95,11 +100,13 @@ public class PonderButton extends AbstractSimiWidget {
float flashValue = flash.getValue(partialTicks);
if (flashValue > .1f)
fade *= 3 * flashValue + Math.sin((AnimationTickHolder.getTicks() + partialTicks) / 6);
fade *= 3 * flashValue + Math.sin((PonderUI.ponderTicks + partialTicks) / 6);
int backgroundColor = ColorHelper.applyAlpha(0xdd000000, fade);
int borderColorStart = ColorHelper.applyAlpha(isHovered ? 0x70ffffff : 0x40aa9999, fade);
int borderColorEnd = ColorHelper.applyAlpha(isHovered ? 0x30ffffff : 0x20aa9999, fade);
int borderColorStart =
ColorHelper.applyAlpha(noClickEvent ? 0x70984500 : isHovered ? 0x70ffffff : 0x40aa9999, fade);
int borderColorEnd =
ColorHelper.applyAlpha(noClickEvent ? 0x70692400 : isHovered ? 0x30ffffff : 0x20aa9999, fade);
PonderUI.renderBox(x, y, width, height, backgroundColor, borderColorStart, borderColorEnd);
RenderSystem.translated(0, 0, 800);
@ -153,4 +160,13 @@ public class PonderButton extends AbstractSimiWidget {
public ItemStack getItem() {
return item;
}
@Override
public boolean isMouseOver(double x, double y) {
double m = 4;
x = Math.floor(x);
y = Math.floor(y);
return active && visible
&& !(x < this.x - m || x > this.x + width + m - 1 || y < this.y - m || y > this.y + height + m - 1);
}
}

View file

@ -12,7 +12,7 @@ import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial;
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedInstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.impl.BasicInstancedModel;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.RenderType;
@ -27,7 +27,7 @@ public class KineticRenderer extends InstancedTileRenderer<BasicProgram> {
@Override
public void registerMaterials() {
materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.MODEL, TransformedInstancedModel::new));
materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.MODEL, BasicInstancedModel::new));
materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.BELT, BeltInstancedModel::new));
materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.ROTATING, RotatingInstancedModel::new));

View file

@ -13,6 +13,8 @@ import com.simibubi.create.foundation.render.backend.gl.GlFog;
import com.simibubi.create.foundation.render.backend.gl.GlFogMode;
import com.simibubi.create.foundation.render.backend.gl.shader.*;
import com.simibubi.create.foundation.render.backend.gl.versioned.GlFeatureCompat;
import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld;
import net.minecraft.world.World;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.opengl.GL;
@ -65,6 +67,10 @@ public class Backend {
return (P) programs.get(spec).get(GlFog.getFogMode());
}
public static boolean isFlywheelWorld(World world) {
return world == Minecraft.getInstance().world || (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel());
}
public static boolean available() {
return canUseVBOs();
}

View file

@ -57,7 +57,7 @@ public class FastRenderDispatcher {
}
public static boolean available(World world) {
return Backend.canUseInstancing() && !(world instanceof SchematicWorld);
return Backend.canUseInstancing() && Backend.isFlywheelWorld(world);
}
public static int getDebugMode() {

View file

@ -1,10 +1,9 @@
package com.simibubi.create.foundation.render.backend;
import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData;
import com.simibubi.create.foundation.render.backend.instancing.MaterialType;
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.impl.TransformData;
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
public class RenderMaterials {
public static final MaterialType<InstancedModel<TransformData>> MODELS = new MaterialType<>();
public static final MaterialType<InstancedModel<ModelData>> MODELS = new MaterialType<>();
}

View file

@ -4,6 +4,7 @@ public enum InstanceVertexAttributes implements IVertexAttrib {
TRANSFORM("aTransform", MatrixAttributes.MAT4),
NORMAL_MAT("aNormalMat", MatrixAttributes.MAT3),
LIGHT("aLight", CommonAttributes.LIGHT),
COLOR("aColor", CommonAttributes.RGBA),
;
private final String name;

View file

@ -6,16 +6,16 @@ import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer;
import net.minecraft.client.renderer.BufferBuilder;
public class TransformedInstancedModel extends InstancedModel<TransformData> {
public class BasicInstancedModel extends InstancedModel<ModelData> {
public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder().addAttributes(InstanceVertexAttributes.class).build();
public TransformedInstancedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
public BasicInstancedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
super(renderer, buf);
}
@Override
protected TransformData newInstance() {
return new TransformData(this);
protected ModelData newInstance() {
return new ModelData(this);
}
@Override

View file

@ -0,0 +1,100 @@
package com.simibubi.create.foundation.render.backend.instancing.impl;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.render.backend.RenderUtil;
import com.simibubi.create.foundation.render.backend.instancing.InstanceData;
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import net.minecraft.client.renderer.Matrix3f;
import net.minecraft.client.renderer.Matrix4f;
import java.nio.ByteBuffer;
public class ModelData extends InstanceData {
private static final Matrix4f IDENT4 = new Matrix4f();
private static final Matrix3f IDENT3 = new Matrix3f();
static {
IDENT4.loadIdentity();
IDENT3.loadIdentity();
}
private Matrix4f modelMat = IDENT4;
private Matrix3f normalMat = IDENT3;
private byte blockLight;
private byte skyLight;
private byte r = (byte) 0xFF;
private byte g = (byte) 0xFF;
private byte b = (byte) 0xFF;
private byte a = (byte) 0xFF;
public ModelData(InstancedModel<?> owner) {
super(owner);
}
public ModelData setModelMat(Matrix4f modelMat) {
this.modelMat = modelMat;
return this;
}
public ModelData setNormalMat(Matrix3f normalMat) {
this.normalMat = normalMat;
return this;
}
public ModelData setTransform(MatrixStack stack) {
this.modelMat = stack.peek().getModel().copy();
this.normalMat = stack.peek().getNormal().copy();
return this;
}
public ModelData setTransformNoCopy(MatrixStack stack) {
this.modelMat = stack.peek().getModel();
this.normalMat = stack.peek().getNormal();
return this;
}
public ModelData setBlockLight(int blockLight) {
this.blockLight = (byte) (blockLight << 4);
return this;
}
public ModelData setSkyLight(int skyLight) {
this.skyLight = (byte) (skyLight << 4);
return this;
}
public ModelData setColor(int color) {
byte a = (byte) ((color >> 24) & 0xFF);
byte r = (byte) ((color >> 16) & 0xFF);
byte g = (byte) ((color >> 8) & 0xFF);
byte b = (byte) (color & 0xFF);
return setColor(r, g, b);
}
public ModelData setColor(int r, int g, int b) {
return setColor((byte) r, (byte) g, (byte) b);
}
public ModelData setColor(byte r, byte g, byte b) {
this.r = r;
this.g = g;
this.b = b;
return this;
}
public ModelData setColor(byte r, byte g, byte b, byte a) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
return this;
}
@Override
public void write(ByteBuffer buf) {
RenderUtil.writeMat4(buf, modelMat);
RenderUtil.writeMat3(buf, normalMat);
buf.put(new byte[] { blockLight, skyLight, r, g, b, a });
}
}

View file

@ -1,56 +0,0 @@
package com.simibubi.create.foundation.render.backend.instancing.impl;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.render.backend.RenderUtil;
import com.simibubi.create.foundation.render.backend.instancing.InstanceData;
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
import net.minecraft.client.renderer.Matrix3f;
import net.minecraft.client.renderer.Matrix4f;
import java.nio.ByteBuffer;
public class TransformData extends InstanceData {
private Matrix4f modelMat;
private Matrix3f normalMat;
private byte blockLight;
private byte skyLight;
public TransformData(InstancedModel<?> owner) {
super(owner);
}
public TransformData setModelMat(Matrix4f modelMat) {
this.modelMat = modelMat;
return this;
}
public TransformData setNormalMat(Matrix3f normalMat) {
this.normalMat = normalMat;
return this;
}
public TransformData setTransform(MatrixStack stack) {
this.modelMat = stack.peek().getModel();
this.normalMat = stack.peek().getNormal();
return this;
}
public TransformData setBlockLight(byte blockLight) {
this.blockLight = blockLight;
return this;
}
public TransformData setSkyLight(byte skyLight) {
this.skyLight = skyLight;
return this;
}
@Override
public void write(ByteBuffer buf) {
RenderUtil.writeMat4(buf, modelMat);
RenderUtil.writeMat3(buf, normalMat);
buf.put(new byte[] { blockLight, skyLight });
}
}

View file

@ -269,6 +269,10 @@ public class GridAlignedBB {
}
}
public AxisAlignedBB toAABB() {
return toAABB(this);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View file

@ -1,6 +1,10 @@
package com.simibubi.create.foundation.utility;
import com.simibubi.create.foundation.ponder.PonderUI;
import com.simibubi.create.foundation.ponder.PonderWorld;
import net.minecraft.client.Minecraft;
import net.minecraft.world.IWorld;
public class AnimationTickHolder {
@ -15,6 +19,10 @@ public class AnimationTickHolder {
ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision
}
}
public static int getTicks() {
return ticks;
}
public static float getRenderTime() {
return getTicks() + getPartialTicks();
@ -24,8 +32,16 @@ public class AnimationTickHolder {
Minecraft mc = Minecraft.getInstance();
return (mc.isGamePaused() ? mc.renderPartialTicksPaused : mc.getRenderPartialTicks());
}
public static int getTicks() {
return ticks;
public static int getTicks(IWorld world) {
return world instanceof PonderWorld ? PonderUI.ponderTicks : getTicks();
}
public static float getRenderTime(IWorld world) {
return getTicks(world) + getPartialTicks(world);
}
public static float getPartialTicks(IWorld world) {
return world instanceof PonderWorld ? PonderUI.getPartialTicks() : getPartialTicks();
}
}

View file

@ -0,0 +1,8 @@
package com.simibubi.create.foundation.utility;
import net.minecraft.util.math.BlockPos;
@FunctionalInterface
public interface Coordinate {
float get(BlockPos from);
}

View file

@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.renderer.Quaternion;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -23,6 +24,14 @@ public class MatrixStacker {
return instance;
}
public MatrixStacker rotate(Direction axis, float radians) {
if (radians == 0)
return this;
ms.multiply(axis.getUnitVector()
.getRadialQuaternion(radians));
return this;
}
public MatrixStacker rotate(double angle, Axis axis) {
Vector3f vec =
axis == Axis.X ? Vector3f.POSITIVE_X : axis == Axis.Y ? Vector3f.POSITIVE_Y : Vector3f.POSITIVE_Z;
@ -75,7 +84,7 @@ public class MatrixStacker {
}
public MatrixStacker nudge(int id) {
long randomBits = (long) id * 493286711L;
long randomBits = (long) id * 31L * 493286711L;
randomBits = randomBits * randomBits * 4392167121L + randomBits * 98761L;
float xNudge = (((float) (randomBits >> 16 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
float yNudge = (((float) (randomBits >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F;
@ -84,7 +93,7 @@ public class MatrixStacker {
return this;
}
private MatrixStacker multiply(Vector3f axis, double angle) {
public MatrixStacker multiply(Vector3f axis, double angle) {
if (angle == 0)
return this;
ms.multiply(axis.getDegreesQuaternion((float) angle));

View file

@ -7,6 +7,7 @@ attribute vec2 aTexCoords;
attribute mat4 aTransform;
attribute mat3 aNormalMat;
attribute vec2 aLight;
attribute vec4 aColor;
varying vec2 TexCoords;
varying vec4 Color;
@ -72,5 +73,5 @@ void main() {
Light = aLight;
gl_Position = uViewProjection * worldPos;
Color = vec4(1.);
Color = aColor;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.