net.malisis.core.client.gui.GuiRenderer.java Source code

Java tutorial

Introduction

Here is the source code for net.malisis.core.client.gui.GuiRenderer.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 PaleoCrafter, Ordinastie
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package net.malisis.core.client.gui;

import java.util.ArrayList;
import java.util.List;

import net.malisis.core.client.gui.component.UIComponent;
import net.malisis.core.client.gui.component.container.UIContainer;
import net.malisis.core.client.gui.component.decoration.UITooltip;
import net.malisis.core.client.gui.element.GuiShape;
import net.malisis.core.client.gui.icon.GuiIcon;
import net.malisis.core.renderer.MalisisRenderer;
import net.malisis.core.renderer.RenderParameters;
import net.malisis.core.renderer.RenderType;
import net.malisis.core.renderer.element.Face;
import net.malisis.core.renderer.element.Shape;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;

import org.apache.commons.lang3.StringUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;

/**
 * Renderer to use for {@link MalisisGui}.
 *
 * @author Ordinastie
 *
 */
public class GuiRenderer extends MalisisRenderer {
    /** RenderItem used to draw itemStacks. */
    public static RenderItem itemRenderer = new RenderItem();
    /** Font height. */
    public static int FONT_HEIGHT = MalisisRenderer.getFontRenderer().FONT_HEIGHT;
    /** Current component being drawn. */
    public UIComponent currentComponent;
    /** Width of the Minecraft window. */
    private int displayWidth;
    /** Height of the Minecraft window. */
    private int displayHeight;
    /** Multiplying factor between GUI size and pixel size. */
    private int scaleFactor;
    /** Should the rendering be done according to scaleFactor. */
    private boolean ignoreScale = false;
    /** Scale to use when drawing fonts. */
    private float fontScale = 1F;
    /** Current X position of the mouse. */
    public int mouseX;
    /** Current Y position of the mouse. */
    public int mouseY;
    /** Default {@link GuiTexture} to use for current {@link MalisisGui}. */
    private GuiTexture defaultGuiTexture;
    /** Currently used {@link GuiTexture} */
    private GuiTexture currentTexture;

    /**
     * Instantiates a new {@link GuiRenderer}.
     */
    public GuiRenderer() {
        defaultGuiTexture = new GuiTexture(new ResourceLocation("malisiscore", "textures/gui/gui.png"), 300, 100);
        updateGuiScale();
    }

    /**
     * Gets the default {@link GuiTexture}.
     *
     * @return the defaultGuiTexture
     */
    public GuiTexture getDefaultTexture() {
        return defaultGuiTexture;
    }

    public void setDefaultTexture(GuiTexture texture) {
        this.defaultGuiTexture = texture;
    }

    /**
     * Sets whether to ignore default Minecraft GUI scale factor.<br>
     * If set to true, 1 pixel size will be equal to 1 pixel on screen.
     *
     * @param ignore the new ignore scale
     */
    public void setIgnoreScale(boolean ignore) {
        ignoreScale = ignore;
    }

    /**
     * Checks if Minecraft GUI scale is ignored
     *
     * @return true if ignored
     */
    public boolean isIgnoreScale() {
        return ignoreScale;
    }

    /**
     * Sets a custom font scale factor.
     *
     * @param scale the new font scale
     */
    public void setFontScale(float scale) {
        fontScale = scale;
    }

    /**
     * Sets the width, height and scale factor for this {@link GuiRenderer}.
     *
     * @return the the scale factor calculated
     */
    public int updateGuiScale() {
        Minecraft mc = Minecraft.getMinecraft();
        displayWidth = mc.displayWidth;
        displayHeight = mc.displayHeight;
        calcScaleFactor(mc.gameSettings.guiScale);
        return scaleFactor;
    }

    /**
     * Sets the mouse position and the partial tick.
     *
     * @param mouseX the mouse x
     * @param mouseY the mouse y
     * @param partialTicks the partial ticks
     */
    public void set(int mouseX, int mouseY, float partialTicks) {
        this.mouseX = mouseX;
        this.mouseY = mouseY;
        this.partialTick = partialTicks;
    }

    @Override
    public void prepare(RenderType renderType, double... data) {
        _initialize();
        this.renderType = renderType;

        currentTexture = null;
        bindDefaultTexture();

        if (ignoreScale) {
            GL11.glPushMatrix();
            GL11.glScalef(1F / scaleFactor, 1F / scaleFactor, 1);
        }

        enableBlending();

        startDrawing();
    }

    @Override
    public void clean() {
        draw();

        if (ignoreScale)
            GL11.glPopMatrix();

        reset();
    }

    /**
     * Draws the component to the screen.
     *
     * @param container the container
     * @param mouseX the mouse x
     * @param mouseY the mouse y
     * @param partialTick the partial tick
     */
    public void drawScreen(UIContainer container, int mouseX, int mouseY, float partialTick) {
        if (container == null)
            return;

        set(mouseX, mouseY, partialTick);
        prepare(RenderType.GUI);

        container.draw(this, mouseX, mouseY, partialTick);

        clean();
    }

    /**
     * Draws a {@link UITooltip} to the screen.
     *
     * @param tooltip the tooltip
     */
    public void drawTooltip(UITooltip tooltip) {
        if (tooltip != null) {
            t.startDrawingQuads();
            tooltip.draw(this, mouseX, mouseY, partialTick);
            t.draw();
        }
    }

    /**
     * Draws a {@link Shape} to the GUI with the specified {@link RenderParameters}.
     *
     * @param s the s
     * @param params the params
     */
    public void drawShape(GuiShape s, RenderParameters params) {
        if (s == null)
            return;

        shape = s;
        rp = params != null ? params : new RenderParameters();

        // move the shape at the right coord on screen
        shape.translate(currentComponent.screenX(), currentComponent.screenY(), currentComponent.getZIndex());
        shape.applyMatrix();

        applyTexture(shape, rp);

        for (Face face : s.getFaces())
            drawFace(face, face.getParameters());
    }

    /**
     * Applies the texture the {@link Shape}.
     *
     * @param shape the shape
     * @param parameters the parameters
     */
    @Override
    public void applyTexture(Shape shape, RenderParameters parameters) {
        if (parameters.icon.get() == null)
            return;

        Face[] faces = shape.getFaces();
        IIcon icon = parameters.icon.get();
        boolean isGuiIcon = icon instanceof GuiIcon;

        for (int i = 0; i < faces.length; i++)
            faces[i].setTexture(isGuiIcon ? ((GuiIcon) icon).getIcon(i) : icon, false, false, false);
    }

    /**
     * Clips a string to fit in the specified width. The string is translated before clipping.
     *
     * @param text the text
     * @param width the width
     * @return the string
     */
    public String clipString(String text, int width) {
        text = StatCollector.translateToLocal(text);
        StringBuilder ret = new StringBuilder();
        int strWidth = 0;
        int index = 0;
        while (index < text.length()) {
            char c = text.charAt(index);
            strWidth += getCharWidth(c);
            if (strWidth < width)
                ret.append(c);
            else
                return ret.toString();
            index++;
        }

        return ret.toString();
    }

    /**
     * Splits the string in multiple lines to fit in the specified maxWidth.
     *
     * @param text the text
     * @param maxWidth the max width
     * @return list of lines that won't exceed maxWidth limit
     */
    public static List<String> wrapText(String text, int maxWidth) {
        return wrapText(text, maxWidth, 1);
    }

    /**
     * Splits the string in multiple lines to fit in the specified maxWidth using the specified fontScale.
     *
     * @param text the text
     * @param maxWidth the max width
     * @param fontScale the font scale
     * @return list of lines that won't exceed maxWidth limit
     */
    public static List<String> wrapText(String text, int maxWidth, float fontScale) {
        List<String> lines = new ArrayList<>();
        StringBuilder line = new StringBuilder();
        StringBuilder word = new StringBuilder();

        int lineWidth = 0;
        int wordWidth = 0;
        int index = 0;
        while (index < text.length()) {
            char c = text.charAt(index);
            int w = getCharWidth(c, fontScale);
            lineWidth += w;
            wordWidth += w;
            word.append(c);
            if (c == ' ' || c == '-' || c == '.') {
                line.append(word);
                word.setLength(0);
                wordWidth = 0;
            }
            if (lineWidth >= maxWidth) {
                if (line.length() == 0) {
                    line.append(word);
                    word.setLength(0);
                    wordWidth = 0;
                }
                lines.add(line.toString());
                line.setLength(0);
                lineWidth = wordWidth;
            }
            index++;
        }

        line.append(word);
        lines.add(line.toString());

        return lines;
    }

    /**
     * Draws a white text on the GUI without shadow.
     *
     * @param text the text
     */
    public void drawText(String text) {
        drawText(text, 0, 0, 0, 0xFFFFFF, false);
    }

    /**
     * Draws a text on the GUI with specified color and shadow.
     *
     * @param text the text
     * @param color the color
     * @param shadow the shadow
     */
    public void drawText(String text, int color, boolean shadow) {
        drawText(text, 0, 0, 0, color, shadow);
    }

    /**
     * Draws a text on the GUI at the specified coordinates, relative to its parent container, with color and shadow.
     *
     * @param text the text
     * @param x the x
     * @param y the y
     * @param color the color
     * @param shadow the shadow
     */
    public void drawText(String text, int x, int y, int color, boolean shadow) {
        drawText(text, x, y, 0, color, shadow);
    }

    /**
     * Draws a text on the GUI at the specified coordinates, relative to its parent container, with zIndex, color and shadow.
     *
     * @param text the text
     * @param x the x
     * @param y the y
     * @param zIndex the z index
     * @param color the color
     * @param shadow the shadow
     */
    public void drawText(String text, int x, int y, int zIndex, int color, boolean shadow) {
        drawString(text, currentComponent.screenX() + x, currentComponent.screenY() + y,
                currentComponent.getZIndex() + zIndex, color, shadow);
    }

    /**
     * Draws a string at the specified coordinates, with color and shadow. The string gets translated. Uses FontRenderer.drawString().
     *
     * @param text the text
     * @param x the x
     * @param y the y
     * @param z the z
     * @param color the color
     * @param shadow the shadow
     */
    public void drawString(String text, int x, int y, int z, int color, boolean shadow) {
        if (MalisisRenderer.getFontRenderer() == null)
            return;

        text = StatCollector.translateToLocal(text);
        text = text.replaceAll("\r", "");
        GL11.glPushMatrix();
        GL11.glTranslatef(x * (1 - fontScale), y * (1 - fontScale), 0);
        GL11.glScalef(fontScale, fontScale, 1);
        GL11.glTranslatef(0, 0, z);
        // GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glDisable(GL12.GL_RESCALE_NORMAL);

        MalisisRenderer.getFontRenderer().drawString(text, x, y, color, shadow);

        GL11.glPopMatrix();
        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
        // GL11.glEnable(GL11.GL_DEPTH_TEST);
        currentTexture = null;
        bindDefaultTexture();
    }

    /**
     * Draws an itemStack to the GUI. Uses RenderItem.renderItemAndEffectIntoGUI() and RenderItem.renderItemOverlayIntoGUI();
     *
     * @param itemStack the item stack
     * @param x the x
     * @param y the y
     */
    public void drawItemStack(ItemStack itemStack, int x, int y) {
        drawItemStack(itemStack, x, y, null);
    }

    /**
     * Draws itemStack to the GUI. Uses RenderItem.renderItemAndEffectIntoGUI() and RenderItem.renderItemOverlayIntoGUI(); TODO: use
     * currrentComponent position
     *
     * @param itemStack the item stack
     * @param x the x
     * @param y the y
     * @param format the format
     */
    public void drawItemStack(ItemStack itemStack, int x, int y, EnumChatFormatting format) {
        if (itemStack == null)
            return;

        FontRenderer fontRenderer = itemStack.getItem().getFontRenderer(itemStack);
        if (fontRenderer == null)
            fontRenderer = MalisisRenderer.getFontRenderer();

        String s = null;
        if (format != null)
            s = format + Integer.toString(itemStack.stackSize);

        t.draw();
        RenderHelper.enableGUIStandardItemLighting();
        GL11.glEnable(GL12.GL_RESCALE_NORMAL);

        itemRenderer.renderItemAndEffectIntoGUI(fontRenderer, Minecraft.getMinecraft().getTextureManager(),
                itemStack, x, y);
        itemRenderer.renderItemOverlayIntoGUI(fontRenderer, Minecraft.getMinecraft().getTextureManager(), itemStack,
                x, y, s);

        RenderHelper.disableStandardItemLighting();
        GL11.glColor4f(1, 1, 1, 1);
        //   GL11.glDisable(GL11.GL_ALPHA_TEST);

        currentTexture = null;
        bindDefaultTexture();
        t.startDrawingQuads();
    }

    /**
     * Starts clipping an area to prevent drawing outside of it.
     *
     * @param area the area
     */
    public void startClipping(ClipArea area) {
        if (area.noClip || area.width() <= 0 || area.height() <= 0)
            return;

        GL11.glPushAttrib(GL11.GL_SCISSOR_BIT);
        GL11.glEnable(GL11.GL_SCISSOR_TEST);

        int f = ignoreScale ? 1 : scaleFactor;
        int x = area.x * f;
        int y = displayHeight - (area.y + area.height()) * f;
        int w = area.width() * f;
        int h = area.height() * f;
        ;
        GL11.glScissor(x, y, w, h);
    }

    /**
     * Ends the clipping.
     *
     * @param area the area
     */
    public void endClipping(ClipArea area) {
        if (area.noClip || area.width() <= 0 || area.height() <= 0)
            return;

        GL11.glDisable(GL11.GL_SCISSOR_TEST);
        GL11.glPopAttrib();
    }

    /**
     * Calculates GUI scale factor.
     *
     * @param guiScale the gui scale
     */
    private void calcScaleFactor(int guiScale) {
        this.scaleFactor = 1;
        if (guiScale == 0)
            guiScale = 1000;

        while (this.scaleFactor < guiScale && this.displayWidth / (this.scaleFactor + 1) >= 320
                && this.displayHeight / (this.scaleFactor + 1) >= 240)
            ++this.scaleFactor;
    }

    /**
     * Render the picked up itemStack at the cursor position.
     *
     * @param itemStack the item stack
     */
    public void renderPickedItemStack(ItemStack itemStack) {
        if (itemStack == null)
            return;

        itemRenderer.zLevel = 100;
        t.startDrawingQuads();
        drawItemStack(itemStack, mouseX - 8, mouseY - 8,
                itemStack.stackSize == 0 ? EnumChatFormatting.YELLOW : null);
        t.draw();
        itemRenderer.zLevel = 0;
    }

    /**
     * Gets rendering width of a string.
     *
     * @param str the str
     * @return the string width
     */
    public static int getStringWidth(String str) {
        return getStringWidth(str, 1);
    }

    /**
     * Gets rendering width of a string according to fontScale.
     *
     * @param str the str
     * @param fontScale the font scale
     * @return the string width
     */
    public static int getStringWidth(String str, float fontScale) {
        if (StringUtils.isEmpty(str))
            return 0;

        str = StatCollector.translateToLocal(str);
        str = str.replaceAll("\r", "");
        return (int) Math.ceil(MalisisRenderer.getFontRenderer().getStringWidth(str) * fontScale);
    }

    /**
     * Gets the rendering height of strings.
     *
     * @return the string height
     */
    public static int getStringHeight() {
        return getStringHeight(1);
    }

    /**
     * Gets the rendering height of strings according to fontscale.
     *
     * @param fontScale the font scale
     * @return the string height
     */
    public static int getStringHeight(float fontScale) {
        return (int) Math.ceil(FONT_HEIGHT * fontScale);
    }

    /**
     * Gets the max string width.
     *
     * @param strings the strings
     * @return the max string width
     */
    public static int getMaxStringWidth(List<String> strings) {
        return getMaxStringWidth(strings, 1);
    }

    /**
     * Gets max rendering width of an array of string.
     *
     * @param strings the strings
     * @param fontScale the font scale
     * @return the max string width
     */
    public static int getMaxStringWidth(List<String> strings, float fontScale) {
        int width = 0;
        for (String str : strings)
            width = Math.max(width, getStringWidth(str, fontScale));
        return width;
    }

    /**
     * Gets the rendering width of a char.
     *
     * @param c the c
     * @return the char width
     */
    public static int getCharWidth(char c) {
        if (c == '\r')
            return 0;
        return getCharWidth(c, 1);
    }

    /**
     * Gets the rendering width of a char with the specified fontScale.
     *
     * @param c the c
     * @param fontScale the font scale
     * @return the char width
     */
    public static int getCharWidth(char c, float fontScale) {
        return (int) Math.ceil(MalisisRenderer.getFontRenderer().getCharWidth(c) * fontScale);
    }

    /**
     * Bind a new texture for rendering.
     *
     * @param texture the texture
     */
    public void bindTexture(GuiTexture texture) {
        if (texture == null || texture == currentTexture)
            return;

        Minecraft.getMinecraft().getTextureManager().bindTexture(texture.getResourceLocation());
        currentTexture = texture;
    }

    /**
     * Reset the texture to its {@link #defaultGuiTexture}.
     */
    public void bindDefaultTexture() {
        bindTexture(defaultGuiTexture);
    }

    /**
     * Next.
     */
    @Override
    public void next() {
        super.next();
        bindDefaultTexture();
    }
}