hellfirepvp.astralsorcery.client.gui.journal.GuiProgressionRenderer.java Source code

Java tutorial

Introduction

Here is the source code for hellfirepvp.astralsorcery.client.gui.journal.GuiProgressionRenderer.java

Source

/*******************************************************************************
 * HellFirePvP / Astral Sorcery 2017
 *
 * This project is licensed under GNU GENERAL PUBLIC LICENSE Version 3.
 * The source code is available on github: https://github.com/HellFirePvP/AstralSorcery
 * For further details, see the License file there.
 ******************************************************************************/

package hellfirepvp.astralsorcery.client.gui.journal;

import hellfirepvp.astralsorcery.client.gui.GuiJournalProgression;
import hellfirepvp.astralsorcery.client.util.Blending;
import hellfirepvp.astralsorcery.client.util.TextureHelper;
import hellfirepvp.astralsorcery.client.util.mappings.ClientJournalMapping;
import hellfirepvp.astralsorcery.client.util.resource.AssetLibrary;
import hellfirepvp.astralsorcery.client.util.resource.AssetLoader;
import hellfirepvp.astralsorcery.client.util.resource.BindableResource;
import hellfirepvp.astralsorcery.common.data.research.PlayerProgress;
import hellfirepvp.astralsorcery.common.data.research.ResearchManager;
import hellfirepvp.astralsorcery.common.data.research.ResearchProgression;
import hellfirepvp.astralsorcery.common.util.data.Vector3;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.VertexBuffer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.math.MathHelper;
import org.lwjgl.opengl.GL11;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.Map;

/**
 * This class is part of the Astral Sorcery Mod
 * The complete source code for this mod can be found on github.
 * Class: GuiProgressionRenderer
 * Created by HellFirePvP
 * Date: 12.08.2016 / 17:31
 */
public class GuiProgressionRenderer {

    private static final BindableResource textureResBack = AssetLibrary.loadTexture(AssetLoader.TextureLocation.GUI,
            "guiresbg");
    private static final BindableResource textureResOVL = AssetLibrary.loadTexture(AssetLoader.TextureLocation.GUI,
            "guijresoverlay");
    //private static final BindableResource black = AssetLibrary.loadTexture(AssetLoader.TextureLocation.MISC, "black");

    private GalaxySizeHandler sizeHandler;
    private GuiJournalProgression parentGui;

    //Rendering relevant properties. Those coords represent _unscaled_ exact positions.
    public GuiRenderBoundingBox realRenderBox;
    private int realCoordLowerX, realCoordLowerY;
    private int realRenderWidth, realRenderHeight;

    private ScalingPoint mousePointScaled;
    private ScalingPoint previousMousePointScaled;

    private ResearchProgression focusedClusterZoom = null, focusedClusterMouse = null;
    private GuiProgressionClusterRenderer clusterRenderer = null;

    private boolean hasPrevOffset = false;
    private Map<Rectangle, ResearchProgression> clusterRectMap = new HashMap<>();

    public GuiProgressionRenderer(GuiJournalProgression gui, int guiHeight, int guiWidth) {
        this.parentGui = gui;
        this.sizeHandler = new GalaxySizeHandler(guiHeight, guiWidth);
        refreshSize();
        this.mousePointScaled = ScalingPoint.createPoint(this.sizeHandler.clampX(this.sizeHandler.getMidX()),
                this.sizeHandler.clampY(this.sizeHandler.getMidY()), this.sizeHandler.getScalingFactor(), false);
        this.moveMouse(this.sizeHandler.getTotalWidth() / 2, this.sizeHandler.getTotalHeight() / 2);
        applyMovedMouseOffset();
    }

    public void refreshSize() {
        this.sizeHandler.updateSize();
    }

    public void setBox(int left, int top, int right, int bottom) {
        this.realRenderBox = new GuiRenderBoundingBox(left, top, right, bottom);
        this.realRenderWidth = (int) this.realRenderBox.getWidth();
        this.realRenderHeight = (int) this.realRenderBox.getHeight();
    }

    public void moveMouse(double changedX, double changedY) {
        if (sizeHandler.getScalingFactor() >= 6.1D && clusterRenderer != null) {
            clusterRenderer.moveMouse(changedX, changedY);
        } else {
            if (hasPrevOffset) {
                mousePointScaled.updateScaledPos(
                        sizeHandler.clampX(previousMousePointScaled.getScaledPosX() + changedX),
                        sizeHandler.clampY(previousMousePointScaled.getScaledPosY() + changedY),
                        sizeHandler.getScalingFactor());
            } else {
                mousePointScaled.updateScaledPos(sizeHandler.clampX(changedX), sizeHandler.clampY(changedY),
                        sizeHandler.getScalingFactor());
            }
        }
    }

    public void applyMovedMouseOffset() {
        if (sizeHandler.getScalingFactor() >= 6.1D && clusterRenderer != null) {
            clusterRenderer.applyMovedMouseOffset();
        } else {
            this.previousMousePointScaled = ScalingPoint.createPoint(mousePointScaled.getScaledPosX(),
                    mousePointScaled.getScaledPosY(), sizeHandler.getScalingFactor(), true);
            this.hasPrevOffset = true;
        }
    }

    public void updateOffset(int guiLeft, int guiTop) {
        this.realCoordLowerX = guiLeft;
        this.realCoordLowerY = guiTop;
    }

    public void centerMouse() {
        this.moveMouse(parentGui.getGuiLeft() + this.sizeHandler.getMidX(),
                parentGui.getGuiTop() + this.sizeHandler.getMidY());
    }

    public void updateMouseState() {
        moveMouse(0, 0);
    }

    public void unfocus() {
        focusedClusterZoom = null;
    }

    public void focus(@Nonnull ResearchProgression researchCluster) {
        this.focusedClusterZoom = researchCluster;
        this.clusterRenderer = new GuiProgressionClusterRenderer(researchCluster, realRenderHeight, realRenderWidth,
                realCoordLowerX, realCoordLowerY);
    }

    //Nothing to actually click here, we redirect if we can.
    public void propagateClick(Point p) {
        if (clusterRenderer != null && sizeHandler.getScalingFactor() > 6) {
            clusterRenderer.propagateClick(parentGui, p);
        }
    }

    public void drawMouseHighlight(float zLevel, Point mousePoint) {
        if (clusterRenderer != null && sizeHandler.getScalingFactor() > 6) {
            clusterRenderer.drawMouseHighlight(zLevel, mousePoint);
        }
    }

    public void resetZoom() {
        sizeHandler.resetZoom();
        rescale(sizeHandler.getScalingFactor());
    }

    public void handleZoomOut() {
        this.sizeHandler.handleZoomOut();
        rescale(sizeHandler.getScalingFactor());

        if (this.sizeHandler.getScalingFactor() <= 4.0) {
            unfocus();
        } else if (this.sizeHandler.getScalingFactor() >= 6.0 && this.clusterRenderer != null) {
            clusterRenderer.handleZoomOut();
        }
    }

    /**
     * Thresholds for zooming in:
     * 1.0 - 4.0 don't care.
     * 4.0 - 6.0 has to have focus + centering to center of cluster
     * 6.0 - 10.0 transition (6.0 - 8.0) + cluster rendering + handling (cursor movement)
     */
    public void handleZoomIn() {
        double scale = sizeHandler.getScalingFactor();
        //double nextScale = Math.min(10.0D, scale + 0.2D);
        if (scale >= 4.0D) {
            if (focusedClusterZoom == null) {
                ResearchProgression prog = tryFocusCluster();
                if (prog != null) {
                    focus(prog);
                }
            }
            if (focusedClusterZoom == null) {
                return;
            }
            if (scale < 6.1D) { //Floating point shenanigans
                double vDiv = (2D - (scale - 4.0D)) * 10D;
                Rectangle2D rect = calcBoundingRectangle(focusedClusterZoom);
                Vector3 center = new Vector3(rect.getCenterX(), rect.getCenterY(), 0);
                Vector3 mousePos = new Vector3(mousePointScaled.getScaledPosX(), mousePointScaled.getScaledPosY(),
                        0);
                Vector3 dir = center.subtract(mousePos);
                if (vDiv > 0.05) {
                    dir.divide(vDiv);
                }
                if (!hasPrevOffset) {
                    mousePointScaled.updateScaledPos(sizeHandler.clampX(mousePos.getX() + dir.getX()),
                            sizeHandler.clampY(mousePos.getY() + dir.getY()), sizeHandler.getScalingFactor());
                } else {
                    previousMousePointScaled.updateScaledPos(sizeHandler.clampX(mousePos.getX() + dir.getX()),
                            sizeHandler.clampY(mousePos.getY() + dir.getY()), sizeHandler.getScalingFactor());
                }

                updateMouseState();
            } else if (clusterRenderer != null) {
                clusterRenderer.handleZoomIn();
            }
        }
        this.sizeHandler.handleZoomIn();
        rescale(sizeHandler.getScalingFactor());
    }

    private void rescale(double newScale) {
        this.mousePointScaled.rescale(newScale);
        if (this.previousMousePointScaled != null) {
            this.previousMousePointScaled.rescale(newScale);
        }
        updateMouseState();
    }

    public void drawProgressionPart(float zLevel) {
        drawBaseBackground(zLevel);

        drawClusters(zLevel);

        focusedClusterMouse = tryFocusCluster();

        double scaleX = this.mousePointScaled.getPosX();
        double scaleY = this.mousePointScaled.getPosY();

        if (sizeHandler.getScalingFactor() >= 6.1D && focusedClusterZoom != null && clusterRenderer != null) {
            ClientJournalMapping.JournalCluster cluster = ClientJournalMapping
                    .getClusterMapping(focusedClusterZoom);
            drawClusterBackground(cluster.clusterBackgroundTexture, zLevel);

            clusterRenderer.drawClusterScreen(zLevel);
            scaleX = clusterRenderer.getScaleMouseX();
            scaleY = clusterRenderer.getScaleMouseY();
        }

        if (focusedClusterMouse != null) {
            ClientJournalMapping.JournalCluster cluster = ClientJournalMapping
                    .getClusterMapping(focusedClusterMouse);
            if (cluster != null) {
                double lX = sizeHandler.evRelativePosX(cluster.leftMost);
                double rX = sizeHandler.evRelativePosX(cluster.rightMost);
                double lY = sizeHandler.evRelativePosY(cluster.upperMost);
                double rY = sizeHandler.evRelativePosY(cluster.lowerMost);
                double scaledLeft = this.mousePointScaled.getScaledPosX() - sizeHandler.widthToBorder;
                double scaledTop = this.mousePointScaled.getScaledPosY() - sizeHandler.heightToBorder;
                double xAdd = lX - scaledLeft;
                double yAdd = lY - scaledTop;
                double offsetX = realCoordLowerX + xAdd;
                double offsetY = realCoordLowerY + yAdd;

                double scale = sizeHandler.getScalingFactor();
                float br = 1F;
                if (scale > 8.01) {
                    br = 0F;
                } else if (scale >= 6) {
                    br = (float) (1F - ((scale - 6) / 2));
                }

                String name = focusedClusterMouse.getUnlocalizedName();
                name = I18n.format(name);
                TextureHelper.refreshTextureBindState();
                GL11.glPushMatrix();
                GL11.glTranslated(offsetX + ((rX - lX) / 2), offsetY + ((rY - lY) / 3), 0);
                FontRenderer fr = Minecraft.getMinecraft().fontRenderer;
                int width = fr.getStringWidth(name);
                GL11.glTranslated(-width / 2, 0, 0);
                GL11.glScaled(1.4, 1.4, 1.4);
                int alpha = 0xCC;
                alpha *= br;
                alpha = Math.max(alpha, 5);
                int color = 0x5A28FF | (alpha << 24);
                fr.drawStringWithShadow(name, 0, 0, color);
                GL11.glPopMatrix();
                GlStateManager.color(1F, 1F, 1F, 1F); //Resetting.
                GL11.glColor4f(1F, 1F, 1F, 1F);
                TextureHelper.refreshTextureBindState();
            }
            /*if(clusterText != null && !clusterText.getText().equalsIgnoreCase(name)) {
            clusterText = null;
            }
                
            if(clusterText == null) {
            clusterText = new OverlayText(name, name.length() * 10,
                    new OverlayText.OverlayTextProperties()
                            .setPolicy(OverlayTextPolicy.Policies.WRITING)
                            .setColor(new Color(90, 40, 255))
                            .setAlpha(1F));
            }*/
        } // else {
        /*if(clusterText != null && clusterText.canRemove()) {
            clusterText = null;
        }*/
        //}

        /*if(clusterText != null) {
        Point mouse = parentGui.getCurrentMousePoint();
        GL11.glPushMatrix();
        GL11.glTranslated(mouse.x, mouse.y - 18, 0);
        GL11.glScaled(0.8, 0.8, 0.8);
        clusterText.doRender(null, 0, false);
        GL11.glPopMatrix();
        }*/

        drawBlendedStarfieldLayers(scaleX, scaleY, zLevel);
    }

    /*public void resetOverlayText() {
    clusterText = null;
    }
        
    public void updateTick() {
    if(clusterText != null) {
        clusterText.tick();
        
        if(clusterText.aboutToBeRemoved() && focusedClusterMouse != null) {
            String name = focusedClusterMouse.getUnlocalizedName();
            name = I18n.format(name);
            int time = (name.length() * 10) - 20;
            clusterText.forceTicks(time);
        } else if(focusedClusterMouse == null && !clusterText.aboutToBeRemoved()) {
            clusterText.scheduleDeath();
        }
    }
    }*/

    @Nullable
    private ResearchProgression tryFocusCluster() {
        Point mousePoint = parentGui.getCurrentMousePoint();

        for (Rectangle r : this.clusterRectMap.keySet()) {
            if (r.contains(mousePoint)) {
                return this.clusterRectMap.get(r);
            }
        }
        return null;
    }

    private Rectangle2D calcBoundingRectangle(ResearchProgression progression) {
        ClientJournalMapping.JournalCluster cluster = ClientJournalMapping.getClusterMapping(progression);
        double lX = sizeHandler.evRelativePosX(cluster.leftMost);
        double rX = sizeHandler.evRelativePosX(cluster.rightMost);
        double lY = sizeHandler.evRelativePosY(cluster.upperMost);
        double rY = sizeHandler.evRelativePosY(cluster.lowerMost);
        return new Rectangle2D.Double(lX, lY, rX - lX, rY - lY);
    }

    private void drawClusters(float zLevel) {
        clusterRectMap.clear();
        if (sizeHandler.getScalingFactor() >= 8.01)
            return;

        PlayerProgress thisProgress = ResearchManager.clientProgress;
        for (ResearchProgression progress : thisProgress.getResearchProgression()) {
            ClientJournalMapping.JournalCluster cluster = ClientJournalMapping.getClusterMapping(progress);
            double lX = sizeHandler.evRelativePosX(cluster.leftMost);
            double rX = sizeHandler.evRelativePosX(cluster.rightMost);
            double lY = sizeHandler.evRelativePosY(cluster.upperMost);
            double rY = sizeHandler.evRelativePosY(cluster.lowerMost);
            renderCluster(progress, cluster, lX, lY, rX, rY, zLevel);
        }
    }

    private void renderCluster(ResearchProgression p, ClientJournalMapping.JournalCluster cluster, double lowerPosX,
            double lowerPosY, double higherPosX, double higherPosY, float zLevel) {
        double scaledLeft = this.mousePointScaled.getScaledPosX() - sizeHandler.widthToBorder;
        double scaledTop = this.mousePointScaled.getScaledPosY() - sizeHandler.heightToBorder;
        double xAdd = lowerPosX - scaledLeft;
        double yAdd = lowerPosY - scaledTop;
        double offsetX = realCoordLowerX + xAdd;
        double offsetY = realCoordLowerY + yAdd;

        GL11.glPushMatrix();
        GL11.glTranslated(offsetX, offsetY, 0);

        double width = higherPosX - lowerPosX;
        double height = higherPosY - lowerPosY;

        Rectangle r = new Rectangle(MathHelper.floor(offsetX), MathHelper.floor(offsetY), MathHelper.floor(width),
                MathHelper.floor(height));
        clusterRectMap.put(r, p);

        Tessellator t = Tessellator.getInstance();
        VertexBuffer vb = t.getBuffer();
        cluster.cloudTexture.bind();

        double scale = sizeHandler.getScalingFactor();
        float br = 1F;
        if (scale > 8.01) {
            br = 0F;
        } else if (scale >= 6) {
            br = (float) (1F - ((scale - 6) / 2));
        }
        GL11.glColor4f(br, br, br, br);

        Blending.ADDITIVEDARK.apply();

        vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
        vb.pos(0, height, zLevel).tex(0, 1).endVertex();
        vb.pos(width, height, zLevel).tex(1, 1).endVertex();
        vb.pos(width, 0, zLevel).tex(1, 0).endVertex();
        vb.pos(0, 0, zLevel).tex(0, 0).endVertex();
        t.draw();

        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        GL11.glPopMatrix();
    }

    private void drawBlendedStarfieldLayers(double scalePosX, double scalePosY, float zLevel) {
        drawBlendedStarfieldOverlay(zLevel, scalePosX, scalePosY, 1.5);
        drawBlendedStarfieldOverlay(zLevel, scalePosX, scalePosY, 2.5);
        drawBlendedStarfieldOverlay(zLevel, scalePosX, scalePosY, 3.5);
    }

    private void drawClusterBackground(BindableResource tex, float zLevel) {
        double scale = sizeHandler.getScalingFactor();
        float br = 0F;
        if (scale > 8.01) {
            br = 1F;
        } else if (scale >= 6) {
            br = (float) (((scale - 6) / 2));
        }
        br *= 0.75F;
        GL11.glColor4f(br, br, br, br);
        tex.bind();

        Blending.ADDITIVEDARK.apply();

        VertexBuffer vb = Tessellator.getInstance().getBuffer();
        vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
        vb.pos(realCoordLowerX, realCoordLowerY + realRenderHeight, zLevel).tex(0, 1).endVertex();
        vb.pos(realCoordLowerX + realRenderWidth, realCoordLowerY + realRenderHeight, zLevel).tex(1, 1).endVertex();
        vb.pos(realCoordLowerX + realRenderWidth, realCoordLowerY, zLevel).tex(1, 0).endVertex();
        vb.pos(realCoordLowerX, realCoordLowerY, zLevel).tex(0, 0).endVertex();
        Tessellator.getInstance().draw();

        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        GL11.glColor4f(1F, 1F, 1F, 1F);
    }

    private void drawBaseBackground(float zLevel) {
        float br = 0.5F;
        GL11.glColor4f(br, br, br, 1.0F);
        GL11.glDisable(GL11.GL_BLEND);
        textureResBack.bind();

        /*float lowU = (((float) this.leftOffset) - sizeHandler.widthToBorder) / ((float) sizeHandler.getTotalWidth());
        float highU = lowU + (((float) renderWidth) / ((float) sizeHandler.getTotalWidth()));
        float lowV = (((float) this.topOffset) - sizeHandler.heightToBorder) / ((float) sizeHandler.getTotalHeight());
        float highV = lowV + (((float) renderHeight) / ((float) sizeHandler.getTotalHeight()));*/

        VertexBuffer vb = Tessellator.getInstance().getBuffer();
        vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
        vb.pos(realCoordLowerX, realCoordLowerY + realRenderHeight, zLevel).tex(0, 1).endVertex();
        vb.pos(realCoordLowerX + realRenderWidth, realCoordLowerY + realRenderHeight, zLevel).tex(1, 1).endVertex();
        vb.pos(realCoordLowerX + realRenderWidth, realCoordLowerY, zLevel).tex(1, 0).endVertex();
        vb.pos(realCoordLowerX, realCoordLowerY, zLevel).tex(0, 0).endVertex();
        Tessellator.getInstance().draw();

        GL11.glEnable(GL11.GL_BLEND);
        GL11.glColor4f(1F, 1F, 1F, 1F);
    }

    private void drawBlendedStarfieldOverlay(float zLevel, double scalePosX, double scalePosY, double scaleFactor) {
        GL11.glColor4f(1F, 1F, 1F, 0.15F);
        GL11.glPushMatrix();
        GL11.glScaled(scaleFactor, scaleFactor, scaleFactor);
        textureResOVL.bind();

        double th = sizeHandler.getTotalHeight() / sizeHandler.getScalingFactor();
        double tw = sizeHandler.getTotalWidth() / sizeHandler.getScalingFactor();

        double lowU = (scalePosX - sizeHandler.widthToBorder) / tw;
        double highU = lowU + (((float) realRenderWidth) / tw);
        double lowV = (scalePosY - sizeHandler.heightToBorder) / th;
        double highV = lowV + (((float) realRenderHeight) / th);

        VertexBuffer vb = Tessellator.getInstance().getBuffer();
        vb.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
        vb.pos(0, realRenderHeight, zLevel).tex(lowU, highV).endVertex();
        vb.pos(realRenderWidth, realRenderHeight, zLevel).tex(highU, highV).endVertex();
        vb.pos(realRenderWidth, 0, zLevel).tex(highU, lowV).endVertex();
        vb.pos(0, 0, zLevel).tex(lowU, lowV).endVertex();
        Tessellator.getInstance().draw();
        GL11.glPopMatrix();
        GL11.glColor4f(1F, 1F, 1F, 1F);
    }

}