package speedytools.clientside.rendering; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderGlobal; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.BlockPos; import net.minecraft.util.Vec3; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.fml.common.eventhandler.Event; import org.lwjgl.opengl.GL11; import speedytools.clientside.ClientSide; import speedytools.common.utilities.Colour; import java.util.ArrayList; import java.util.Collection; /** * User: The Grey Ghost * Date: 14/04/14 * This class is used to render a wireframe around a collection of cubes. * Usage: * (1) Call the constructor, providing a WireframeRenderInfoUpdateLink: * This interface is used to fill the supplied WireframeRenderInfo with the requested information for a render. * (2) When ready to render, call .render. */ public class RendererWireframeSelection implements RendererElement { public RendererWireframeSelection(WireframeRenderInfoUpdateLink i_infoProvider) { infoProvider = i_infoProvider; renderInfo = new WireframeRenderInfo(); } public final int SELECTION_BOX_STYLE = 0; //0 = cube, 1 = cube with cross on each side @Override public Collection<Class<? extends Event>> eventsToReceive() { ArrayList<Class<? extends Event>> retval = new ArrayList<Class<? extends Event>>(); retval.add(RenderWorldLastEvent.class); return retval; } @Override public void render(Event event, float partialTick) { RenderWorldLastEvent fullEvent = (RenderWorldLastEvent)event; RenderGlobal context = fullEvent.context; EntityPlayer player = (EntityPlayer)(Minecraft.getMinecraft().getRenderViewEntity()); renderWorld(player, ClientSide.getGlobalTickCount(), partialTick); } public void renderWorld(EntityPlayer player, int animationTickCount, float partialTick) { boolean shouldIRender = infoProvider.refreshRenderInfo(renderInfo); if (!shouldIRender) return; try { GL11.glPushAttrib(GL11.GL_ENABLE_BIT); GL11.glDepthMask(false); GL11.glPushMatrix(); GL11.glEnable(GL11.GL_BLEND); GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); // just white float cyclePosition = 0.0F; float red = Colour.WHITE_40.R + (Colour.BLACK_40.R - Colour.WHITE_40.R) * cyclePosition; float green = Colour.WHITE_40.R + (Colour.BLACK_40.G - Colour.WHITE_40.G) * cyclePosition; float blue = Colour.WHITE_40.R + (Colour.BLACK_40.B - Colour.WHITE_40.B) * cyclePosition; GL11.glColor4f(red, green, blue, Colour.BLACK_40.A); GL11.glLineWidth(2.0F); GL11.glDisable(GL11.GL_TEXTURE_2D); double expandDistance = 0.002F; Vec3 playerOrigin = player.getPositionEyes(partialTick);//.subtract(0.0, player.getEyeHeight(), 0.0); GlStateManager.translate(0.0F, player.getEyeHeight(), 0.0F); // put [0,0,0] at eye height for (BlockPos block : renderInfo.currentlySelectedBlocks) { if (block != null) { AxisAlignedBB boundingBox = new AxisAlignedBB(block, block.add(1, 1, 1)); boundingBox = boundingBox.expand(expandDistance, expandDistance, expandDistance).offset(-playerOrigin.xCoord, -playerOrigin.yCoord, -playerOrigin.zCoord); switch (SELECTION_BOX_STYLE) { case 0: { SelectionBoxRenderer.drawCube(boundingBox); break; } case 1: { SelectionBoxRenderer.drawFilledCube(boundingBox); break; } } } } } finally { GL11.glPopMatrix(); GL11.glDepthMask(true); GL11.glPopAttrib(); } } /** The WireframeRenderInfoUpdateLink and WireframeRenderInfo are used to retrieve the necessary information for rendering from the current tool * If refreshRenderInfo returns false, no render is performed. */ public interface WireframeRenderInfoUpdateLink { public boolean refreshRenderInfo(WireframeRenderInfo infoToUpdate); } public static class WireframeRenderInfo { public Collection<BlockPos> currentlySelectedBlocks; } WireframeRenderInfoUpdateLink infoProvider; WireframeRenderInfo renderInfo; }