com.teambr.bookshelf.client.gui.component.control.GuiComponentSideSelector.java Source code

Java tutorial

Introduction

Here is the source code for com.teambr.bookshelf.client.gui.component.control.GuiComponentSideSelector.java

Source

package com.teambr.bookshelf.client.gui.component.control;

import com.google.common.collect.Lists;
import com.teambr.bookshelf.client.gui.GuiBase;
import com.teambr.bookshelf.client.gui.component.BaseComponent;
import com.teambr.bookshelf.client.gui.misc.SidePicker;
import com.teambr.bookshelf.client.gui.misc.TrackballWrapper;
import com.teambr.bookshelf.util.ClientUtils;
import com.teambr.bookshelf.util.RenderUtils;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.block.model.IBakedModel;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import org.apache.commons.lang3.tuple.Pair;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;

import javax.annotation.Nullable;
import java.awt.Color;
import java.util.List;

/**
 * This file was created for Bookshelf
 *
 * Bookshelf is licensed under the
 * Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License:
 * http://creativecommons.org/licenses/by-nc-sa/4.0/
 *
 * @author Paul Davis - pauljoda
 * @since 2/13/2017
 */
public abstract class GuiComponentSideSelector extends BaseComponent {
    // Variables
    protected double scale;
    protected IBlockState blockState;
    protected TileEntity tile;
    protected boolean highListSelectedSides, renderTile;
    protected int diameter;
    protected boolean isInInitialPosition = false;
    protected TrackballWrapper trackball;
    protected EnumFacing lastSideHovered;

    /**
     * Creates the side selector object
     * @param parent The parent GUI
     * @param x The x pos
     * @param y The y pos
     * @param scaleValue The scale
     * @param state The block state of the block to render
     * @param tileEntity The tile entity of the block to render
     * @param doHighlights Render the highlights when selecting
     * @param doRenderTile Render the tile?
     */
    public GuiComponentSideSelector(GuiBase<?> parent, int x, int y, double scaleValue, @Nullable IBlockState state,
            @Nullable TileEntity tileEntity, boolean doHighlights, boolean doRenderTile) {
        super(parent, x, y);
        this.scale = scaleValue;
        this.blockState = state;
        this.tile = tileEntity;
        this.highListSelectedSides = doHighlights;
        this.renderTile = doRenderTile;

        this.diameter = MathHelper.ceil(scale * Math.sqrt(3));
        trackball = new TrackballWrapper(1, 40);
    }

    /*******************************************************************************************************************
     * Abstract Methods                                                                                                *
     *******************************************************************************************************************/

    /**
     * This is called any time the user presses a side to toggle the mode. You should change your variable
     * here to the next value as well as handle any changes to the Tile or whatever.
     *
     * @param side The side that was selected
     * @param modifier 0 : Normal Click (you should toggle to the next mode)
     *                 1 : Shift Click (you should set to default or disabled)
     *                 2 : Control Click (you should go backward)
     */
    protected abstract void onSideToggled(EnumFacing side, int modifier);

    /**
     * This is used to color the highlight. Use whatever mode you have for each side and get the color that should
     * be displayed.
     * As a general rule:
     *     NULL    : Disabled
     *     BLUE    : Input
     *     ORANGE  : OUTPUT
     *     GREEN   : BOTH
     *
     * However you are free to use your own implementation as you feel needed
     *
     * @param side The side that needs a color
     * @return The color that should be rendered, or null for no color
     */
    @Nullable
    protected abstract Color getColorForMode(EnumFacing side);

    /*******************************************************************************************************************
     * BaseComponent                                                                                                   *
     *******************************************************************************************************************/

    /**
     * Called when the mouse is pressed
     *
     * @param x Mouse X Position
     * @param y Mouse Y Position
     * @param button Mouse Button
     */
    @Override
    public void mouseDown(int x, int y, int button) {
        lastSideHovered = null;
    }

    /**
     * Called when the mouse button is over the component and released
     *
     * @param x Mouse X Position
     * @param y Mouse Y Position
     * @param button Mouse Button
     */
    @Override
    public void mouseUp(int x, int y, int button) {
        if (button == 0 && lastSideHovered != null)
            onSideToggled(lastSideHovered,
                    ClientUtils.isShiftPressed() ? 1 : (ClientUtils.isCtrlPressed() ? 2 : 0));
    }

    /**
     * Called to render the component
     */
    @Override
    public void render(int guiLeft, int guiTop, int mouseX, int mouseY) {
        if (!isInInitialPosition || Mouse.isButtonDown(2)) {
            Entity renderViewEntity = Minecraft.getMinecraft().getRenderViewEntity();
            trackball.setTransform(RenderUtils.createEntityRotateMatrix(renderViewEntity));
            isInInitialPosition = true;
        }

        int width = getWidth();
        int height = getHeight();

        GlStateManager.pushMatrix();
        GlStateManager.translate(xPos + width / 2, yPos + height / 2, (float) diameter);
        GlStateManager.scale(scale, -scale, scale);
        trackball.update(mouseX - width, -(mouseY - height));

        if (blockState != null)
            drawBlock();

        if (tile != null && renderTile)
            TileEntityRendererDispatcher.instance.renderTileEntityAt(tile, -0.5F, -0.5F, -0.5F, 0.0F);

        SidePicker picker = new SidePicker(0.5);

        List<Pair<SidePicker.Side, Color>> selections = Lists.newArrayListWithCapacity(6 + 1);
        SidePicker.HitCoord hitCoord = picker.getNearestHit();
        if (hitCoord != null)
            selections.add(Pair.of(hitCoord.side, getColorForMode(hitCoord.side.toEnumFacing())));

        if (highListSelectedSides) {
            for (EnumFacing dir : EnumFacing.values()) {
                selections.add(Pair.of(SidePicker.Side.fromEnumFacing(dir),
                        getColorForMode(dir) != null ? getColorForMode(dir) : new Color(0, 0, 0, 0)));
            }
        }

        if (selections != null)
            drawHighlights(selections);

        lastSideHovered = hitCoord == null ? null : hitCoord.side.toEnumFacing();

        GlStateManager.popMatrix();
    }

    /**
     * Called after base render, is already translated to guiLeft and guiTop, just move offset
     */
    @Override
    public void renderOverlay(int guiLeft, int guiTop, int mouseX, int mouseY) {
        // No Op
    }

    /**
     * Used to find how wide this is
     *
     * @return How wide the component is
     */
    @Override
    public int getWidth() {
        return diameter;
    }

    /**
     * Used to find how tall this is
     *
     * @return How tall the component is
     */
    @Override
    public int getHeight() {
        return diameter;
    }

    /*******************************************************************************************************************
     * GuiComponentSideSelector                                                                                        *
     *******************************************************************************************************************/

    /**
     * Draws our stored block
     */
    private void drawBlock() {
        Tessellator tessellator = Tessellator.getInstance();
        GlStateManager.pushMatrix();
        GlStateManager.translate(-0.5, -0.5, -0.5);

        BufferBuilder vertexBuffer = tessellator.getBuffer();
        vertexBuffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK);

        BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
        IBakedModel model = dispatcher.getModelForState(blockState);
        dispatcher.getBlockModelRenderer().renderModel(tile.getWorld(), model, blockState, new BlockPos(0, 0, 0),
                vertexBuffer, false);
        vertexBuffer.setTranslation(0.0, 0.0, 0.0);
        tessellator.draw();
        GlStateManager.popMatrix();
    }

    /**
     * Draws the highlights onto the block
     * @param selections The colors to render
     */
    private void drawHighlights(List<Pair<SidePicker.Side, Color>> selections) {
        GlStateManager.disableLighting();
        GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
        GlStateManager.enableBlend();
        GlStateManager.enableAlpha();
        GlStateManager.disableDepth();
        GlStateManager.disableTexture2D();

        GL11.glBegin(GL11.GL_QUADS);
        for (Pair<SidePicker.Side, Color> pair : selections) {
            if (pair.getRight() != null)
                RenderUtils.setColor(pair.getRight());

            switch (pair.getLeft()) {
            case XPos:
                GL11.glVertex3d(0.5, -0.5, -0.5);
                GL11.glVertex3d(0.5, 0.5, -0.5);
                GL11.glVertex3d(0.5, 0.5, 0.5);
                GL11.glVertex3d(0.5, -0.5, 0.5);
                break;
            case YPos:
                GL11.glVertex3d(-0.5, 0.5, -0.5);
                GL11.glVertex3d(-0.5, 0.5, 0.5);
                GL11.glVertex3d(0.5, 0.5, 0.5);
                GL11.glVertex3d(0.5, 0.5, -0.5);
                break;
            case ZPos:
                GL11.glVertex3d(-0.5, -0.5, 0.5);
                GL11.glVertex3d(0.5, -0.5, 0.5);
                GL11.glVertex3d(0.5, 0.5, 0.5);
                GL11.glVertex3d(-0.5, 0.5, 0.5);
                break;
            case XNeg:
                GL11.glVertex3d(-0.5, -0.5, -0.5);
                GL11.glVertex3d(-0.5, -0.5, 0.5);
                GL11.glVertex3d(-0.5, 0.5, 0.5);
                GL11.glVertex3d(-0.5, 0.5, -0.5);
                break;
            case YNeg:
                GL11.glVertex3d(-0.5, -0.5, -0.5);
                GL11.glVertex3d(0.5, -0.5, -0.5);
                GL11.glVertex3d(0.5, -0.5, 0.5);
                GL11.glVertex3d(-0.5, -0.5, 0.5);
                break;
            case ZNeg:
                GL11.glVertex3d(-0.5, -0.5, -0.5);
                GL11.glVertex3d(-0.5, 0.5, -0.5);
                GL11.glVertex3d(0.5, 0.5, -0.5);
                GL11.glVertex3d(0.5, -0.5, -0.5);
                break;
            default:
            }
        }

        GL11.glEnd();

        GlStateManager.disableBlend();
        GlStateManager.enableDepth();
        GlStateManager.enableTexture2D();
    }

    /*******************************************************************************************************************
     * Accessors/Mutators                                                                                              *
     *******************************************************************************************************************/

    public double getScale() {
        return scale;
    }

    public void setScale(double scale) {
        this.scale = scale;
        this.diameter = MathHelper.ceil(scale * Math.sqrt(3));
    }

    public IBlockState getBlockState() {
        return blockState;
    }

    public void setBlockState(IBlockState blockState) {
        this.blockState = blockState;
    }

    public TileEntity getTile() {
        return tile;
    }

    public void setTile(TileEntity tile) {
        this.tile = tile;
    }

    public boolean isHighListSelectedSides() {
        return highListSelectedSides;
    }

    public void setHighListSelectedSides(boolean highListSelectedSides) {
        this.highListSelectedSides = highListSelectedSides;
    }

    public boolean isRenderTile() {
        return renderTile;
    }

    public void setRenderTile(boolean renderTile) {
        this.renderTile = renderTile;
    }
}