mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-27 23:47:38 +01:00
Instanced Gauges and Valves, DRY lighting.
This commit is contained in:
parent
8281c5746a
commit
52eed2bab3
29 changed files with 383 additions and 107 deletions
|
@ -77,6 +77,7 @@ import com.simibubi.create.content.contraptions.relays.belt.BeltRenderer;
|
|||
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.*;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.GaugeInstance;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.GaugeRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity;
|
||||
|
@ -260,7 +261,7 @@ public class AllTileEntities {
|
|||
|
||||
public static final TileEntityEntry<FluidValveTileEntity> FLUID_VALVE = Create.registrate()
|
||||
.tileEntity("fluid_valve", FluidValveTileEntity::new)
|
||||
.instance(() -> ShaftInstance::new)
|
||||
.instance(() -> FluidValveInstance::new)
|
||||
.validBlocks(AllBlocks.FLUID_VALVE)
|
||||
.renderer(() -> FluidValveRenderer::new)
|
||||
.register();
|
||||
|
@ -515,14 +516,14 @@ public class AllTileEntities {
|
|||
|
||||
public static final TileEntityEntry<SpeedGaugeTileEntity> SPEEDOMETER = Create.registrate()
|
||||
.tileEntity("speedometer", SpeedGaugeTileEntity::new)
|
||||
.instance(() -> ShaftInstance::new)
|
||||
.instance(() -> GaugeInstance.Speed::new)
|
||||
.validBlocks(AllBlocks.SPEEDOMETER)
|
||||
.renderer(() -> GaugeRenderer::speed)
|
||||
.register();
|
||||
|
||||
public static final TileEntityEntry<StressGaugeTileEntity> STRESSOMETER = Create.registrate()
|
||||
.tileEntity("stressometer", StressGaugeTileEntity::new)
|
||||
.instance(() -> ShaftInstance::new)
|
||||
.instance(() -> GaugeInstance.Stress::new)
|
||||
.validBlocks(AllBlocks.STRESSOMETER)
|
||||
.renderer(() -> GaugeRenderer::stress)
|
||||
.register();
|
||||
|
|
|
@ -4,12 +4,13 @@ import java.nio.ByteBuffer;
|
|||
|
||||
import com.simibubi.create.foundation.render.backend.instancing.InstanceData;
|
||||
import com.simibubi.create.foundation.render.backend.instancing.InstancedModel;
|
||||
import com.simibubi.create.foundation.render.backend.instancing.impl.IFlatLight;
|
||||
import com.simibubi.create.foundation.utility.ColorHelper;
|
||||
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class KineticData<D extends KineticData<D>> extends InstanceData {
|
||||
public class KineticData<D extends KineticData<D>> extends InstanceData implements IFlatLight<D> {
|
||||
private float x;
|
||||
private float y;
|
||||
private float z;
|
||||
|
@ -65,11 +66,13 @@ public class KineticData<D extends KineticData<D>> extends InstanceData {
|
|||
return (D) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public D setBlockLight(int blockLight) {
|
||||
this.blockLight = (byte) ((blockLight & 0xF) << 4);
|
||||
return (D) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public D setSkyLight(int skyLight) {
|
||||
this.skyLight = (byte) ((skyLight & 0xF) << 4);
|
||||
return (D) this;
|
||||
|
|
|
@ -36,12 +36,6 @@ public abstract class KineticTileInstance<T extends KineticTileEntity> extends T
|
|||
return key;
|
||||
}
|
||||
|
||||
protected final void relight(InstanceKey<? extends KineticData<?>> key) {
|
||||
key.getInstance()
|
||||
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
|
||||
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
|
||||
}
|
||||
|
||||
protected float getRotationOffset(final Direction.Axis axis) {
|
||||
float offset = CogWheelBlock.isLargeCog(lastState) ? 11.25f : 0;
|
||||
double d = (((axis == Direction.Axis.X) ? 0 : pos.getX()) + ((axis == Direction.Axis.Y) ? 0 : pos.getY())
|
||||
|
|
|
@ -4,14 +4,10 @@ import static com.simibubi.create.content.contraptions.base.KineticTileEntityRen
|
|||
|
||||
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 net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
public class SingleRotatingInstance extends KineticTileInstance<KineticTileEntity> {
|
||||
|
||||
|
@ -35,7 +31,7 @@ public class SingleRotatingInstance extends KineticTileInstance<KineticTileEntit
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
relight(rotatingModelKey);
|
||||
relight(pos, rotatingModelKey.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -82,19 +82,10 @@ public class FanInstance extends KineticTileInstance<EncasedFanTileEntity> {
|
|||
final Direction direction = lastState.get(FACING);
|
||||
|
||||
BlockPos behind = pos.offset(direction.getOpposite());
|
||||
putLight(shaft, behind);
|
||||
relight(behind, shaft.getInstance());
|
||||
|
||||
BlockPos inFront = pos.offset(direction);
|
||||
putLight(fan, inFront);
|
||||
}
|
||||
|
||||
private void putLight(InstanceKey<RotatingData> key, BlockPos pos) {
|
||||
int blockLight = world.getLightLevel(LightType.BLOCK, pos);
|
||||
int skyLight = world.getLightLevel(LightType.SKY, pos);
|
||||
|
||||
key.getInstance()
|
||||
.setBlockLight(blockLight)
|
||||
.setSkyLight(skyLight);
|
||||
relight(inFront, fan.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -150,20 +150,10 @@ public class FlyWheelInstance extends KineticTileInstance<FlywheelTileEntity> im
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
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);
|
||||
relight(pos, shaft.getInstance(), wheel.getInstance());
|
||||
|
||||
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));
|
||||
relight(this.pos.offset(connection), connectors.stream().map(InstanceKey::getInstance));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,9 +66,6 @@ public class EngineInstance extends TileEntityInstance<EngineTileEntity> {
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
int block = world.getLightLevel(LightType.BLOCK, pos);
|
||||
int sky = world.getLightLevel(LightType.SKY, pos);
|
||||
|
||||
frame.getInstance().setBlockLight(block).setSkyLight(sky);
|
||||
relight(pos, frame.getInstance());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,14 +92,9 @@ public class MixerInstance extends ShaftlessCogInstance implements ITickableInst
|
|||
public void updateLight() {
|
||||
super.updateLight();
|
||||
|
||||
BlockPos down = pos.down();
|
||||
mixerHead.getInstance()
|
||||
.setBlockLight(world.getLightLevel(LightType.BLOCK, down))
|
||||
.setSkyLight(world.getLightLevel(LightType.SKY, down));
|
||||
relight(pos.down(), mixerHead.getInstance());
|
||||
|
||||
mixerPole.getInstance()
|
||||
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
|
||||
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
|
||||
relight(pos, mixerPole.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -67,9 +67,7 @@ public class PressInstance extends ShaftInstance implements ITickableInstance {
|
|||
public void updateLight() {
|
||||
super.updateLight();
|
||||
|
||||
pressHead.getInstance()
|
||||
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
|
||||
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
|
||||
relight(pos, pressHead.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -63,9 +63,7 @@ public class StickerInstance extends TileEntityInstance<StickerTileEntity> imple
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
head.getInstance()
|
||||
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
|
||||
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
|
||||
relight(pos, head.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -81,9 +81,7 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
gantryCogs.getInstance()
|
||||
.setBlockLight(world.getLightLevel(LightType.BLOCK, pos))
|
||||
.setSkyLight(world.getLightLevel(LightType.SKY, pos));
|
||||
relight(pos, gantryCogs.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,6 +25,8 @@ import net.minecraft.world.TickPriority;
|
|||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxisPipe {
|
||||
|
||||
public static final BooleanProperty ENABLED = BooleanProperty.create("enabled");
|
||||
|
@ -60,9 +62,10 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi
|
|||
return AllTileEntities.FLUID_VALVE.create();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static Axis getPipeAxis(BlockState state) {
|
||||
if (!(state.getBlock() instanceof FluidValveBlock))
|
||||
return null;
|
||||
throw new IllegalStateException("Provided BlockState is for a different block.");
|
||||
Direction facing = state.get(FACING);
|
||||
boolean alongFirst = !state.get(AXIS_ALONG_FIRST_COORDINATE);
|
||||
for (Axis axis : Iterate.axes) {
|
||||
|
@ -74,7 +77,7 @@ public class FluidValveBlock extends DirectionalAxisKineticBlock implements IAxi
|
|||
}
|
||||
return axis;
|
||||
}
|
||||
return null;
|
||||
throw new IllegalStateException("Impossible axis.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
package com.simibubi.create.content.contraptions.fluids.pipes;
|
||||
|
||||
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.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
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.InstancedTileRenderer;
|
||||
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.block.BlockState;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public class FluidValveInstance extends ShaftInstance implements ITickableInstance {
|
||||
|
||||
protected InstanceKey<ModelData> pointer;
|
||||
|
||||
protected double xRot;
|
||||
protected double yRot;
|
||||
protected int pointerRotationOffset;
|
||||
|
||||
public FluidValveInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
Direction facing = lastState.get(FluidValveBlock.FACING);
|
||||
|
||||
yRot = AngleHelper.horizontalAngle(facing);
|
||||
xRot = facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90;
|
||||
|
||||
Direction.Axis pipeAxis = FluidValveBlock.getPipeAxis(lastState);
|
||||
Direction.Axis shaftAxis = KineticTileEntityRenderer.getRotationAxisOf(tile);
|
||||
|
||||
pointerRotationOffset = 0;
|
||||
if (pipeAxis.isHorizontal() && shaftAxis == Direction.Axis.Z || pipeAxis.isVertical())
|
||||
pointerRotationOffset = 90;
|
||||
|
||||
pointer = modelManager.basicMaterial().getModel(AllBlockPartials.FLUID_VALVE_POINTER, lastState).createInstance();
|
||||
|
||||
updateLight();
|
||||
transformPointer((FluidValveTileEntity) tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
|
||||
FluidValveTileEntity valve = (FluidValveTileEntity) tile;
|
||||
|
||||
if (valve.pointer.settled()) return;
|
||||
|
||||
transformPointer(valve);
|
||||
}
|
||||
|
||||
private void transformPointer(FluidValveTileEntity valve) {
|
||||
float pointerRotation = MathHelper.lerp(valve.pointer.getValue(AnimationTickHolder.getPartialTicks()), 0, -90);
|
||||
|
||||
MatrixStack ms = new MatrixStack();
|
||||
MatrixStacker.of(ms)
|
||||
.translate(getFloatingPos())
|
||||
.centre()
|
||||
.rotateY(yRot)
|
||||
.rotateX(xRot)
|
||||
.rotateY(pointerRotationOffset + pointerRotation)
|
||||
.unCentre();
|
||||
|
||||
pointer.getInstance().setTransform(ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
super.updateLight();
|
||||
relight(pos, pointer.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
pointer.delete();
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import com.simibubi.create.AllBlockPartials;
|
|||
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 com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
|
||||
|
@ -25,6 +26,9 @@ public class FluidValveRenderer extends KineticTileEntityRenderer {
|
|||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
|
||||
if (FastRenderDispatcher.available(te.getWorld())) return;
|
||||
|
||||
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
||||
BlockState blockState = te.getBlockState();
|
||||
SuperByteBuffer pointer = AllBlockPartials.FLUID_VALVE_POINTER.renderOn(blockState);
|
||||
|
|
|
@ -1,29 +1,24 @@
|
|||
package com.simibubi.create.content.contraptions.relays.belt;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.content.contraptions.base.KineticData;
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileInstance;
|
||||
import com.simibubi.create.content.contraptions.base.RotatingData;
|
||||
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
|
||||
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.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.MatrixStacker;
|
||||
|
||||
import net.minecraft.item.DyeColor;
|
||||
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 BeltInstance extends KineticTileInstance<BeltTileEntity> {
|
||||
|
||||
|
@ -103,9 +98,9 @@ public class BeltInstance extends KineticTileInstance<BeltTileEntity> {
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
keys.forEach(this::relight);
|
||||
relight(pos, keys.stream().map(InstanceKey::getInstance));
|
||||
|
||||
if (pulleyKey != null) relight(pulleyKey);
|
||||
if (pulleyKey != null) relight(pos, pulleyKey.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,19 +4,16 @@ import java.util.ArrayList;
|
|||
|
||||
import com.simibubi.create.AllBlockPartials;
|
||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||
import com.simibubi.create.content.contraptions.base.KineticData;
|
||||
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.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.fml.DistExecutor;
|
||||
|
||||
public class SplitShaftInstance extends KineticTileInstance<SplitShaftTileEntity> {
|
||||
|
||||
|
@ -59,7 +56,7 @@ public class SplitShaftInstance extends KineticTileInstance<SplitShaftTileEntity
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
keys.forEach(this::relight);
|
||||
keys.forEach(key -> relight(pos, ((InstanceKey<? extends KineticData<?>>) key).getInstance()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
package com.simibubi.create.content.contraptions.relays.gauge;
|
||||
|
||||
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.InstancedModel;
|
||||
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.*;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class GaugeInstance extends ShaftInstance implements ITickableInstance {
|
||||
|
||||
protected ArrayList<DialFace> faces;
|
||||
|
||||
protected MatrixStack ms;
|
||||
|
||||
protected GaugeInstance(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
super.init();
|
||||
|
||||
faces = new ArrayList<>(2);
|
||||
|
||||
GaugeTileEntity gaugeTile = (GaugeTileEntity) tile;
|
||||
GaugeBlock gaugeBlock = (GaugeBlock) lastState.getBlock();
|
||||
|
||||
InstancedModel<ModelData> dialModel = modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_DIAL, lastState);
|
||||
InstancedModel<ModelData> headModel = getHeadModel();
|
||||
|
||||
ms = new MatrixStack();
|
||||
MatrixStacker msr = MatrixStacker.of(ms);
|
||||
msr.translate(getFloatingPos());
|
||||
|
||||
float progress = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState);
|
||||
|
||||
for (Direction facing : Iterate.directions) {
|
||||
if (!gaugeBlock.shouldRenderHeadOnFace(world, pos, lastState, facing))
|
||||
continue;
|
||||
|
||||
DialFace face = makeFace(facing, dialModel, headModel);
|
||||
|
||||
faces.add(face);
|
||||
|
||||
face.setupTransform(msr, progress);
|
||||
}
|
||||
|
||||
updateLight();
|
||||
}
|
||||
|
||||
private DialFace makeFace(Direction face, InstancedModel<ModelData> dialModel, InstancedModel<ModelData> headModel) {
|
||||
return new DialFace(face, dialModel.createInstance(), headModel.createInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
GaugeTileEntity gaugeTile = (GaugeTileEntity) tile;
|
||||
|
||||
if (MathHelper.epsilonEquals(gaugeTile.prevDialState, gaugeTile.dialState))
|
||||
return;
|
||||
|
||||
float progress = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState);
|
||||
|
||||
MatrixStacker msr = MatrixStacker.of(ms);
|
||||
|
||||
for (DialFace faceEntry : faces) {
|
||||
faceEntry.updateTransform(msr, progress);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
super.updateLight();
|
||||
|
||||
relight(pos, faces.stream()
|
||||
.flatMap(Couple::stream)
|
||||
.map(InstanceKey::getInstance));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
super.remove();
|
||||
|
||||
faces.forEach(DialFace::delete);
|
||||
}
|
||||
|
||||
protected abstract InstancedModel<ModelData> getHeadModel();
|
||||
|
||||
private class DialFace extends Couple<InstanceKey<ModelData>> {
|
||||
|
||||
Direction face;
|
||||
|
||||
public DialFace(Direction face, InstanceKey<ModelData> first, InstanceKey<ModelData> second) {
|
||||
super(first, second);
|
||||
this.face = face;
|
||||
}
|
||||
|
||||
private void setupTransform(MatrixStacker msr, float progress) {
|
||||
float dialPivot = 5.75f / 16;
|
||||
|
||||
ms.push();
|
||||
rotateToFace(msr);
|
||||
|
||||
getSecond().getInstance().setTransform(ms);
|
||||
|
||||
msr.translate(0, dialPivot, dialPivot)
|
||||
.rotate(Direction.EAST, (float) (Math.PI / 2 * -progress))
|
||||
.translate(0, -dialPivot, -dialPivot);
|
||||
|
||||
getFirst().getInstance().setTransform(ms);
|
||||
|
||||
ms.pop();
|
||||
}
|
||||
|
||||
private void updateTransform(MatrixStacker msr, float progress) {
|
||||
float dialPivot = 5.75f / 16;
|
||||
|
||||
ms.push();
|
||||
|
||||
rotateToFace(msr)
|
||||
.translate(0, dialPivot, dialPivot)
|
||||
.rotate(Direction.EAST, (float) (Math.PI / 2 * -progress))
|
||||
.translate(0, -dialPivot, -dialPivot);
|
||||
|
||||
getFirst().getInstance().setTransform(ms);
|
||||
|
||||
ms.pop();
|
||||
}
|
||||
|
||||
protected MatrixStacker rotateToFace(MatrixStacker msr) {
|
||||
return msr.centre()
|
||||
.rotate(Direction.UP, (float) ((-face.getHorizontalAngle() - 90) / 180 * Math.PI))
|
||||
.unCentre();
|
||||
}
|
||||
|
||||
private void delete() {
|
||||
getFirst().delete();
|
||||
getSecond().delete();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Speed extends GaugeInstance {
|
||||
public Speed(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstancedModel<ModelData> getHeadModel() {
|
||||
return modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_HEAD_SPEED, lastState);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Stress extends GaugeInstance {
|
||||
public Stress(InstancedTileRenderer<?> dispatcher, KineticTileEntity tile) {
|
||||
super(dispatcher, tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstancedModel<ModelData> getHeadModel() {
|
||||
return modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_HEAD_STRESS, lastState);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
|||
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
|
||||
import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock.Type;
|
||||
import com.simibubi.create.foundation.render.SuperByteBuffer;
|
||||
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -37,6 +38,8 @@ public class GaugeRenderer extends KineticTileEntityRenderer {
|
|||
@Override
|
||||
protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer,
|
||||
int light, int overlay) {
|
||||
if (FastRenderDispatcher.available(te.getWorld())) return;
|
||||
|
||||
super.renderSafe(te, partialTicks, ms, buffer, light, overlay);
|
||||
BlockState gaugeState = te.getBlockState();
|
||||
GaugeTileEntity gaugeTE = (GaugeTileEntity) te;
|
||||
|
@ -47,14 +50,14 @@ public class GaugeRenderer extends KineticTileEntityRenderer {
|
|||
.renderOn(gaugeState);
|
||||
SuperByteBuffer dialBuffer = AllBlockPartials.GAUGE_DIAL.renderOn(gaugeState);
|
||||
|
||||
float dialPivot = 5.75f / 16;
|
||||
float progress = MathHelper.lerp(partialTicks, gaugeTE.prevDialState, gaugeTE.dialState);
|
||||
|
||||
for (Direction facing : Iterate.directions) {
|
||||
if (!((GaugeBlock) gaugeState.getBlock()).shouldRenderHeadOnFace(te.getWorld(), te.getPos(), gaugeState,
|
||||
facing))
|
||||
continue;
|
||||
|
||||
float dialPivot = 5.75f / 16;
|
||||
float progress = MathHelper.lerp(partialTicks, gaugeTE.prevDialState, gaugeTE.dialState);
|
||||
|
||||
IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid());
|
||||
rotateBufferTowards(dialBuffer, facing).translate(0, dialPivot, dialPivot)
|
||||
.rotate(Direction.EAST, (float) (Math.PI / 2 * -progress))
|
||||
|
|
|
@ -99,14 +99,7 @@ public class GearboxInstance extends KineticTileInstance<GearboxTileEntity> {
|
|||
|
||||
@Override
|
||||
public void updateLight() {
|
||||
int blockLight = tile.getWorld().getLightLevel(LightType.BLOCK, pos);
|
||||
int skyLight = tile.getWorld().getLightLevel(LightType.SKY, pos);
|
||||
|
||||
for (InstanceKey<RotatingData> key : keys.values()) {
|
||||
key.getInstance()
|
||||
.setBlockLight(blockLight)
|
||||
.setSkyLight(skyLight);
|
||||
}
|
||||
relight(pos, keys.values().stream().map(InstanceKey::getInstance));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -73,7 +73,7 @@ public class ArmInstance extends SingleRotatingInstance implements ITickableInst
|
|||
public void tick() {
|
||||
ArmTileEntity arm = (ArmTileEntity) tile;
|
||||
|
||||
boolean settled = Stream.of(arm.baseAngle, arm.lowerArmAngle, arm.upperArmAngle, arm.headAngle).allMatch(InterpolatedValue::settled);
|
||||
boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled();
|
||||
boolean rave = arm.phase == ArmTileEntity.Phase.DANCING;
|
||||
|
||||
if (!settled || rave || firstTick)
|
||||
|
@ -154,13 +154,8 @@ public class ArmInstance extends SingleRotatingInstance implements ITickableInst
|
|||
@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));
|
||||
relight(pos, models.stream().map(InstanceKey::getInstance));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -81,15 +81,6 @@ public class SchematicannonInstance extends TileEntityInstance<SchematicannonTil
|
|||
|
||||
@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);
|
||||
relight(pos, connector.getInstance(), pipe.getInstance());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
|||
protected int minIndexChanged = -1;
|
||||
protected int maxIndexChanged = -1;
|
||||
|
||||
protected boolean anyToRemove;
|
||||
|
||||
public InstancedModel(InstancedTileRenderer<?> renderer, BufferBuilder buf) {
|
||||
super(buf);
|
||||
this.renderer = renderer;
|
||||
|
@ -73,6 +75,8 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
|||
verifyKey(key);
|
||||
|
||||
key.invalidate();
|
||||
|
||||
anyToRemove = true;
|
||||
}
|
||||
|
||||
public D getInstance(InstanceKey<D> key) {
|
||||
|
@ -161,6 +165,8 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
|||
|
||||
// copied from ArrayList#removeIf
|
||||
protected boolean doRemoval() {
|
||||
if (!anyToRemove) return false;
|
||||
|
||||
// figure out which elements are to be removed
|
||||
// any exception thrown from the filter predicate at this stage
|
||||
// will leave the collection unmodified
|
||||
|
@ -198,6 +204,8 @@ public abstract class InstancedModel<D extends InstanceData> extends BufferedMod
|
|||
maxIndexChanged = newSize - 1;
|
||||
}
|
||||
|
||||
this.anyToRemove = false;
|
||||
|
||||
return anyToRemove;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ import javax.annotation.Nullable;
|
|||
|
||||
import com.simibubi.create.foundation.ponder.PonderWorld;
|
||||
import com.simibubi.create.foundation.render.backend.Backend;
|
||||
import com.simibubi.create.foundation.render.backend.RenderMaterials;
|
||||
import com.simibubi.create.foundation.render.backend.gl.BasicProgram;
|
||||
import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback;
|
||||
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
|
||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
@ -67,6 +69,10 @@ public abstract class InstancedTileRenderer<P extends BasicProgram> {
|
|||
return (RenderMaterial<P, M>) materials.get(materialType);
|
||||
}
|
||||
|
||||
public RenderMaterial<P, InstancedModel<ModelData>> basicMaterial() {
|
||||
return getMaterial(RenderMaterials.MODELS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T extends TileEntity> TileEntityInstance<? super T> getInstance(T tile) {
|
||||
return getInstance(tile, true);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.simibubi.create.foundation.render.backend.instancing;
|
||||
|
||||
import com.simibubi.create.foundation.render.backend.instancing.impl.IFlatLight;
|
||||
import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
@ -7,6 +8,9 @@ import net.minecraft.util.math.BlockPos;
|
|||
import net.minecraft.world.LightType;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class TileEntityInstance<T extends TileEntity> {
|
||||
|
||||
protected final InstancedTileRenderer<?> modelManager;
|
||||
|
@ -60,13 +64,19 @@ public abstract class TileEntityInstance<T extends TileEntity> {
|
|||
return pos.subtract(modelManager.getOriginCoordinate());
|
||||
}
|
||||
|
||||
protected void relight(BlockPos pos, ModelData... models) {
|
||||
protected <L extends IFlatLight<?>> void relight(BlockPos pos, IFlatLight<?>... models) {
|
||||
relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models);
|
||||
}
|
||||
|
||||
protected void relight(int block, int sky, ModelData... models) {
|
||||
for (ModelData model : models) {
|
||||
model.setBlockLight(block).setSkyLight(sky);
|
||||
}
|
||||
protected <L extends IFlatLight<?>> void relight(BlockPos pos, Stream<IFlatLight<?>> models) {
|
||||
relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models);
|
||||
}
|
||||
|
||||
protected <L extends IFlatLight<?>> void relight(int block, int sky, IFlatLight<?>... models) {
|
||||
relight(block, sky, Arrays.stream(models));
|
||||
}
|
||||
|
||||
protected <L extends IFlatLight<?>> void relight(int block, int sky, Stream<IFlatLight<?>> models) {
|
||||
models.forEach(model -> model.setBlockLight(block).setSkyLight(sky));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package com.simibubi.create.foundation.render.backend.instancing.impl;
|
||||
|
||||
import com.simibubi.create.foundation.render.backend.instancing.InstanceData;
|
||||
|
||||
/**
|
||||
* An interface that implementors of {@link InstanceData} should also implement
|
||||
* if they wish to make use of Flywheel's provided light update methods.
|
||||
*
|
||||
* This only covers flat lighting, smooth lighting is still TODO.
|
||||
* @param <D> The name of the class that implements this interface.
|
||||
*/
|
||||
public interface IFlatLight<D extends InstanceData & IFlatLight<D>> {
|
||||
/**
|
||||
* @param blockLight An integer in the range [0, 15] representing the
|
||||
* amount of block light this instance should receive.
|
||||
* @return <code>this</code>
|
||||
*/
|
||||
D setBlockLight(int blockLight);
|
||||
|
||||
/**
|
||||
* @param skyLight An integer in the range [0, 15] representing the
|
||||
* amount of sky light this instance should receive.
|
||||
* @return <code>this</code>
|
||||
*/
|
||||
D setSkyLight(int skyLight);
|
||||
}
|
|
@ -9,7 +9,7 @@ import net.minecraft.client.renderer.Matrix4f;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ModelData extends InstanceData {
|
||||
public class ModelData extends InstanceData implements IFlatLight<ModelData> {
|
||||
private static final Matrix4f IDENT4 = new Matrix4f();
|
||||
private static final Matrix3f IDENT3 = new Matrix3f();
|
||||
static {
|
||||
|
@ -54,11 +54,13 @@ public class ModelData extends InstanceData {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelData setBlockLight(int blockLight) {
|
||||
this.blockLight = (byte) (blockLight << 4);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelData setSkyLight(int skyLight) {
|
||||
this.skyLight = (byte) (skyLight << 4);
|
||||
return this;
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.function.BiConsumer;
|
|||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
@ -104,6 +105,10 @@ public class Couple<T> extends Pair<T, T> implements Iterable<T> {
|
|||
return new Couplerator<>(this);
|
||||
}
|
||||
|
||||
public Stream<T> stream() {
|
||||
return Stream.of(first, second);
|
||||
}
|
||||
|
||||
private static class Couplerator<T> implements Iterator<T> {
|
||||
|
||||
int state;
|
||||
|
|
|
@ -24,6 +24,15 @@ public class MatrixStacker {
|
|||
return instance;
|
||||
}
|
||||
|
||||
public MatrixStacker restoreIdentity() {
|
||||
MatrixStack.Entry entry = ms.peek();
|
||||
|
||||
entry.getModel().loadIdentity();
|
||||
entry.getNormal().loadIdentity();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public MatrixStacker rotate(Direction axis, float radians) {
|
||||
if (radians == 0)
|
||||
return this;
|
||||
|
|
|
@ -81,6 +81,10 @@ public class LerpedFloat {
|
|||
return MathHelper.lerp(partialTicks, previousValue, value);
|
||||
}
|
||||
|
||||
public boolean settled() {
|
||||
return MathHelper.epsilonEquals(previousValue, value);
|
||||
}
|
||||
|
||||
public float getChaseTarget() {
|
||||
return chaseTarget;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue