From a48f1e310fbc86d29b2e7d4d37f53a35593bd81f Mon Sep 17 00:00:00 2001 From: SquidDev Date: Thu, 30 May 2019 07:51:35 +0100 Subject: [PATCH] Add a custom renderer for monitor block highlights (#220) This only renders the bounding box on non-screen edges of the monitor, meaning you have an uninterrupted view of the screen when hovering hover. Closes #219 --- ...Cable.java => CableHighlightRenderer.java} | 4 +- .../render/MonitorHighlightRenderer.java | 118 ++++++++++++++++++ .../peripheral/monitor/TileMonitor.java | 2 +- 3 files changed, 121 insertions(+), 3 deletions(-) rename src/main/java/dan200/computercraft/client/render/{RenderOverlayCable.java => CableHighlightRenderer.java} (99%) create mode 100644 src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java diff --git a/src/main/java/dan200/computercraft/client/render/RenderOverlayCable.java b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java similarity index 99% rename from src/main/java/dan200/computercraft/client/render/RenderOverlayCable.java rename to src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java index 0d06d30b9..225e177bf 100644 --- a/src/main/java/dan200/computercraft/client/render/RenderOverlayCable.java +++ b/src/main/java/dan200/computercraft/client/render/CableHighlightRenderer.java @@ -29,13 +29,13 @@ import net.minecraftforge.fml.relauncher.Side; import org.lwjgl.opengl.GL11; @Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT ) -public final class RenderOverlayCable +public final class CableHighlightRenderer { private static final float EXPAND = 0.002f; private static final double MIN = CableBounds.MIN - EXPAND; private static final double MAX = CableBounds.MAX + EXPAND; - private RenderOverlayCable() + private CableHighlightRenderer() { } diff --git a/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java new file mode 100644 index 000000000..fea1d335a --- /dev/null +++ b/src/main/java/dan200/computercraft/client/render/MonitorHighlightRenderer.java @@ -0,0 +1,118 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ + +package dan200.computercraft.client.render; + +import dan200.computercraft.ComputerCraft; +import dan200.computercraft.shared.peripheral.monitor.TileMonitor; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.World; +import net.minecraftforge.client.event.DrawBlockHighlightEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import org.lwjgl.opengl.GL11; + +import java.util.EnumSet; + +import static net.minecraft.util.EnumFacing.*; + +@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Side.CLIENT ) +public final class MonitorHighlightRenderer +{ + private static final float EXPAND = 0.002f; + + private MonitorHighlightRenderer() + { + } + + @SubscribeEvent + public static void drawHighlight( DrawBlockHighlightEvent event ) + { + if( event.getTarget().typeOfHit != RayTraceResult.Type.BLOCK || event.getPlayer().isSneaking() ) return; + + World world = event.getPlayer().getEntityWorld(); + BlockPos pos = event.getTarget().getBlockPos(); + + if( world.getBlockState( pos ).getBlock() != ComputerCraft.Blocks.peripheral ) return; + + TileEntity tile = world.getTileEntity( pos ); + if( !(tile instanceof TileMonitor) ) return; + + TileMonitor monitor = (TileMonitor) tile; + event.setCanceled( true ); + + // Determine which sides are part of the external faces of the monitor, and so which need to be rendered. + EnumSet faces = EnumSet.allOf( EnumFacing.class ); + EnumFacing front = monitor.getFront(); + faces.remove( front ); + if( monitor.getXIndex() != 0 ) faces.remove( monitor.getRight().getOpposite() ); + if( monitor.getXIndex() != monitor.getWidth() - 1 ) faces.remove( monitor.getRight() ); + if( monitor.getYIndex() != 0 ) faces.remove( monitor.getDown().getOpposite() ); + if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() ); + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate( GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO ); + GL11.glLineWidth( 2.0F ); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask( false ); + GlStateManager.pushMatrix(); + + EntityPlayer player = event.getPlayer(); + double x = player.lastTickPosX + (player.posX - player.lastTickPosX) * event.getPartialTicks(); + double y = player.lastTickPosY + (player.posY - player.lastTickPosY) * event.getPartialTicks(); + double z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * event.getPartialTicks(); + + GlStateManager.translate( -x + pos.getX(), -y + pos.getY(), -z + pos.getZ() ); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin( GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR ); + + // I wish I could think of a better way to do this + if( faces.contains( NORTH ) || faces.contains( WEST ) ) line( buffer, 0, 0, 0, UP ); + if( faces.contains( SOUTH ) || faces.contains( WEST ) ) line( buffer, 0, 0, 1, UP ); + if( faces.contains( NORTH ) || faces.contains( EAST ) ) line( buffer, 1, 0, 0, UP ); + if( faces.contains( SOUTH ) || faces.contains( EAST ) ) line( buffer, 1, 0, 1, UP ); + if( faces.contains( NORTH ) || faces.contains( DOWN ) ) line( buffer, 0, 0, 0, EAST ); + if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) line( buffer, 0, 0, 1, EAST ); + if( faces.contains( NORTH ) || faces.contains( UP ) ) line( buffer, 0, 1, 0, EAST ); + if( faces.contains( SOUTH ) || faces.contains( UP ) ) line( buffer, 0, 1, 1, EAST ); + if( faces.contains( WEST ) || faces.contains( DOWN ) ) line( buffer, 0, 0, 0, SOUTH ); + if( faces.contains( EAST ) || faces.contains( DOWN ) ) line( buffer, 1, 0, 0, SOUTH ); + if( faces.contains( WEST ) || faces.contains( UP ) ) line( buffer, 0, 1, 0, SOUTH ); + if( faces.contains( EAST ) || faces.contains( UP ) ) line( buffer, 1, 1, 0, SOUTH ); + + tessellator.draw(); + + GlStateManager.popMatrix(); + GlStateManager.depthMask( true ); + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + } + + private static void line( BufferBuilder buffer, int x, int y, int z, EnumFacing direction ) + { + double minX = x == 0 ? -EXPAND : 1 + EXPAND; + double minY = y == 0 ? -EXPAND : 1 + EXPAND; + double minZ = z == 0 ? -EXPAND : 1 + EXPAND; + + buffer.pos( minX, minY, minZ ).color( 0, 0, 0, 0.4f ).endVertex(); + buffer.pos( + minX + direction.getXOffset() * (1 + EXPAND * 2), + minY + direction.getYOffset() * (1 + EXPAND * 2), + minZ + direction.getZOffset() * (1 + EXPAND * 2) + ).color( 0, 0, 0, 0.4f ).endVertex(); + } +} diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java index 88b48e9f4..7e02de778 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java @@ -339,7 +339,7 @@ public class TileMonitor extends TileGeneric implements ITilePeripheral, IPeriph return EnumFacing.WEST; } - private EnumFacing getDown() + public EnumFacing getDown() { int dir = getDir(); if( dir <= 5 ) return EnumFacing.UP;