com.w67clement.openw67render.gui.graphics.OpenGraphics.java Source code

Java tutorial

Introduction

Here is the source code for com.w67clement.openw67render.gui.graphics.OpenGraphics.java

Source

/*
 * Copyright  2016 Clment "w67clement" Wagner
 *
 * This file is part of OpenW67Render.
 *
 * OpenW67Render is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * OpenW67Render is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with OpenW67Render.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.w67clement.openw67render.gui.graphics;

import com.w67clement.openw67render.gui.components.OpenComponent;
import com.w67clement.openw67render.gui.graphics.fonts.EasyFont;
import com.w67clement.openw67render.gui.graphics.fonts.Font;
import com.w67clement.openw67render.utils.Texture;
import com.w67clement.openw67render.utils.TextureRegion;
import com.w67clement.openw67render.window.OpenWindow;
import java.awt.Color;
import org.lwjgl.opengl.GL11;

import static org.lwjgl.opengl.GL11.*;

/**
 * Created by w67clement on 27/04/2016.
 * <p>
 * Class of project: openw67render
 */
public class OpenGraphics {
    private float complementX = 0;
    private float complementY = 0;
    private Color currentColor = Color.BLACK;
    private OpenWindow window;
    private boolean drawing = false;

    public OpenGraphics(OpenWindow window) {
        this.window = window;
        complementX = 0;
        complementY = 0;
    }

    public OpenGraphics(OpenWindow window, float complementX, float complementY) {
        this.window = window;
        this.complementX = complementX;
        this.complementY = complementY;
    }

    public OpenGraphics(OpenWindow window, OpenComponent component) {
        this.window = window;
        float tempComplementX;
        float tempComplementY;
        if (component.hasParent()) {
            tempComplementX = component.getX();
            tempComplementY = component.getY();
            OpenComponent last = component;
            while (last.hasParent()) {
                last = last.getParent();
                tempComplementX = tempComplementX + last.getX();
                tempComplementY = tempComplementY + last.getY();
            }
        } else {
            tempComplementX = component.getX();
            tempComplementY = component.getY();
        }
        complementX = tempComplementX;
        complementY = tempComplementY;
    }

    /**
     * Preserve the OpenGL settings that will be affected when we draw in ortho
     * mode over the scene. For example if we're drawing an interface layer,
     * buttons, popup menus, cursor, text, etc. we need to turn off lighting,
     * turn on blending, set color to white and turn off depth test.
     * <p>
     * call pushAttribOverlay(), enable settings that you need, when done call
     * popAttrib()
     */
    public static void pushAttribOrtho() {
        glPushAttrib(
                GL11.GL_COLOR_BUFFER_BIT | GL11.GL_TEXTURE_BIT | GL11.GL_LIGHTING_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    }

    /**
     * <p><a href="http://www.opengl.org/sdk/docs/man/html/glViewport.xhtml">OpenGL SDK Reference</a></p>
     * <p>
     * Specifies the viewport transformation parameters for all viewports.
     *
     * @param x      The left viewport coordinate.
     * @param y      The bottom viewport coordinate.
     * @param width  The viewport width.
     * @param height The viewport height.
     */
    public static void setViewport(int x, int y, int width, int height) {
        glViewport(x, y, width, height);
    }

    public OpenWindow getWindow() {
        return window;
    }

    /**
     * Sets the current color.
     *
     * @param color Color.
     */
    public void setColor(Color color) {
        currentColor = color;
        glColor4f((float) color.getRed() / 255f, (float) color.getGreen() / 255f, (float) color.getBlue() / 255f,
                (float) color.getAlpha() / 255f);
    }

    /**
     * Gets the current color.
     *
     * @return AWT color object.
     */
    public Color getCurrentColor() {
        return currentColor;
    }

    /**
     * Enables the transparency.
     */
    public void enableTransparency() {
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    }

    /**
     * Disable the transparency.
     */
    public void disableTransparency() {
        glDisable(GL_BLEND);
    }

    public void view2D() {

    }

    /**
     * Set OpenGL to render in flat 2D (no perspective) on top of current scene.
     * Preserve current projection and model views, and disable depth testing.
     * Ortho world size will be same as viewport size, so any ortho drawing
     * (drawQuad(), drawImageFullscreen(), etc.) will be scaled to fit viewport.
     * <p>
     * NOTE: if the viewport is the same size as the window (by default it is),
     * then setOrtho() will make the world coordinates exactly match the screen
     * pixel positions. This is convenient for mouse interaction, but be warned:
     * if you setViewport() to something other than fullscreen, then you need to
     * use getWorldCoordsAtScreen() to convert screen xy to world xy.
     * <p>
     * Once Ortho is on, glTranslate() will take pixel coords as arguments, with
     * the lower left corner 0,0 and the upper right corner 1024,768 (or
     * whatever your screen size is). !!!
     */
    public void setOrthoOn() {
        int[] size = window.getSize();
        int width = size[0];
        int height = size[1];
        // prepare projection matrix to render in 2D
        glMatrixMode(GL11.GL_PROJECTION);
        glPushMatrix(); // preserve perspective view
        glLoadIdentity(); // clear the perspective matrix
        glOrtho( // turn on 2D mode
                //// viewportX,viewportX+viewportW, // left, right
                //// viewportY,viewportY+viewportH, // bottom, top !!!
                0, width, // left, right
                height, 0, // bottom, top
                -500, 500); // Zfar, Znear
        // clear the modelview matrix
        glMatrixMode(GL11.GL_MODELVIEW);
        glPushMatrix(); // Preserve the Modelview Matrix
        glLoadIdentity(); // clear the Modelview Matrix
        // disable depth test so further drawing will go over the current scene
        glDisable(GL11.GL_DEPTH_TEST);
    }

    /**
     * Turn 2D mode off. Return the projection and model views to their
     * preserved state that was saved when setOrthoOn() was called, and
     * re-enable depth testing.
     */
    public void setOrthoOff() {
        // restore the original positions and views
        glMatrixMode(GL11.GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL11.GL_MODELVIEW);
        glPopMatrix();
        // turn Depth Testing back on
        glEnable(GL11.GL_DEPTH_TEST);
    }

    /**
     * Return to the OpenGL settings that were preserved by the previous
     * pushAttrib() call.
     */
    public void popAttrib() {
        glPopAttrib();
    }

    /**
     * Flush with glFlush() function.
     */
    public void flush() {
        glFlush();
    }

    /**
     * Applies the given 2D or 3D translation to the current matrix.
     *
     * @param x The amount of pixels to translate on X axis.
     * @param y The amount of pixels to translate on Y axis.
     * @param z The amount of pixels to translate on Z axis.
     */
    public void translate(float x, float y, float z) {
        glTranslatef(x, y, z);
    }

    /**
     * Applies the given 2D or 3D scale to the current matrix.
     *
     * @param x The amount of pixels to scale on X axis.
     * @param y The amount of pixels to scale on Y axis.
     * @param z The amount of pixels to scale on Z axis.
     */
    public void scale(float x, float y, float z) {
        glScalef(x, y, z);
    }

    /**
     * Pushes the current matrix stack down by one, duplicating the current matrix in both the top of the stack and the entry below it.
     */
    public void glPushMatrix() {
        GL11.glPushMatrix();
    }

    /**
     * Pops the top entry off the current matrix stack, replacing the current matrix with the matrix that was the second entry in the stack.
     */
    public void glPopMatrix() {
        GL11.glPopMatrix();
    }

    /**
     * Defines a GL scissor box. All outside pixels cannot modified.
     *
     * @param x      X of start of the box.
     * @param y      Y of start of the box.
     * @param width  Width of the box.
     * @param height Height of the box.
     *
     * @see #resetScissor()
     */
    public void useScissor(float x, float y, float width, float height) {
        int[] size = window.getSize();
        float yScissor;
        if (complementY == 0)
            yScissor = size[1];
        else
            yScissor = size[1] - (complementY + y + height);
        glScissor((int) (complementX + x), (int) yScissor, (int) width, (int) height);
        glEnable(GL_SCISSOR_TEST);
    }

    /**
     * Defines the default GL scissor box. All outside pixels cannot modified.
     *
     * @see #useScissor(float, float, float, float)
     * @see #resetScissor()
     */
    public void useDefaultScissor() {
        int[] size = window.getSize();
        glScissor(0, 0, size[0], size[1]);
        glEnable(GL_SCISSOR_TEST);
    }

    /**
     * Resets the GL scissor box defined by {@link #useScissor(float, float, float, float)}.
     *
     * @see #useScissor(float, float, float, float)
     * @see #resetScissor(boolean)
     */
    public void resetScissor() {
        resetScissor(false);
    }

    /**
     * Resets the GL scissor box defined by {@link #useScissor(float, float, float, float)}.
     *
     * @param disable Disable the GL scissor box.
     *
     * @see #useScissor(float, float, float, float)
     */
    public void resetScissor(boolean disable) {
        if (disable)
            glDisable(GL_SCISSOR_TEST);
        int[] size = window.getSize();
        glScissor(0, 0, size[0], size[1]);
    }

    /**
     * Gets complement X.
     * <p>
     * It's for coordinates of drawing things.
     * </p>
     *
     * @return Complement X.
     */
    public float getComplementX() {
        return complementX;
    }

    /**
     * Gets complement Y.
     * <p>
     * It's for coordinates of drawing things.
     * </p>
     *
     * @return Complement Y.
     */
    public float getComplementY() {
        return complementY;
    }

    /* DRAW */

    /**
     * Begins to draw.
     *
     * @param type The thing to draw.
     */
    public void beginDraw(DrawType type) {
        if (drawing)
            throw new RuntimeException();
        glBegin(type.getId());
        drawing = true;
    }

    /**
     * Ends to draw.
     */
    public void endDraw() {
        if (!drawing)
            throw new RuntimeException("Not drawing, cannot endDraw.");
        glEnd();
        drawing = false;
    }

    /**
     * <p><a href="http://www.opengl.org/sdk/docs/man2/html/glVertex2f.xhtml">OpenGL SDK Reference</a> - <em>This function is deprecated and unavailable in the Core profile</em></p>
     * <p>
     * Specifies a single vertex between {@link #beginDraw(DrawType)}  Begin} and {@link #endDraw()}  End} by giving its coordinates in two dimensions.
     * The Z coordinate is implicitly set to zero and the W coordinate to one.
     *
     * @param x The vertex X coordinate.
     * @param y The vertex Y coordinate.
     */
    public void setVertex2f(float x, float y) {
        glVertex2f(x, y);
    }

    /**
     * Draw a line.
     *
     * @param x  X position of the first point.
     * @param y  Y position of the first point.
     * @param x2 X position of the second point.
     * @param y2 Y position of the second point.
     */
    public void drawLine(float x, float y, float x2, float y2) {
        x = x + complementX;
        y = y + complementY;
        x2 = x2 + complementX;
        y2 = y2 + complementY;
        beginDraw(DrawType.LINES);
        setVertex2f(x, y);
        setVertex2f(x2, y2);
        endDraw();
    }

    /**
     * Draws a simple rectangle.
     *
     * @param x      X position of the rectangle.
     * @param y      Y position of the rectangle.
     * @param width  The width of the rectangle.
     * @param height The height of the rectangle.
     */
    public void drawRectangle(float x, float y, float width, float height) {
        drawRectangle(x, y, width, height, null);
    }

    /**
     * Draws a simple colored rectangle.
     *
     * @param x      X position of the rectangle.
     * @param y      Y position of the rectangle.
     * @param width  The width of the rectangle.
     * @param height The height of the rectangle.
     * @param color  Color of the rectangle.
     */
    public void drawRectangle(float x, float y, float width, float height, Color color) {
        x = x + complementX;
        y = y + complementY;
        if (color != null)
            setColor(color);
        beginDraw(DrawType.QUADS);
        setVertex2f(x, y);
        setVertex2f(x, y + height);
        setVertex2f(x + width, y + height);
        setVertex2f(x + width, y);
        endDraw();
    }

    /**
     * Draws a simple colored rectangle.
     *
     * @param x                X position of the rectangle.
     * @param y                Y position of the rectangle.
     * @param width            The width of the rectangle.
     * @param height           The height of the rectangle.
     * @param leftTopColor     The color of the left top corner of the rectangle.
     * @param leftBottomColor  The color of the left bottom corner of the rectangle.
     * @param rightBottomColor The color of the right bottom corner of the rectangle.
     * @param rightTopColor    The color of the right top corner of the rectangle.
     */
    public void drawRectangle(float x, float y, float width, float height, Color leftTopColor,
            Color leftBottomColor, Color rightBottomColor, Color rightTopColor) {
        x = x + complementX;
        y = y + complementY;
        beginDraw(DrawType.QUADS);
        setColor(leftTopColor);
        setVertex2f(x, y);
        setColor(leftBottomColor);
        setVertex2f(x, y + height);
        setColor(rightBottomColor);
        setVertex2f(x + width, y + height);
        setColor(rightTopColor);
        setVertex2f(x + width, y);
        endDraw();
    }

    /**
     * Enable the texture 2D.
     */
    public void enableTexture2D() {
        glEnable(GL_TEXTURE_2D);
    }

    /**
     * Draws an 2D image with a defined texture.
     *
     * @param texture The defined texture to draw.
     * @param x       X position of the image.
     * @param y       Y position of the image.
     * @param width   Width of the image.
     * @param height  Height of the image.
     *
     * @see #drawImage(Texture, float, float, float, float, TextureRegion)
     */
    public void drawImage(Texture texture, float x, float y, float width, float height) {
        drawImage(texture, x, y, width, height, TextureRegion.BASE);
    }

    /**
     * Draws an 2D image with a defined part texture.
     *
     * @param texture The defined texture to draw.
     * @param x       X position of the image.
     * @param y       Y position of the image.
     * @param width   Width of the image.
     * @param height  Height of the image.
     * @param region  Part of the texture to draw.
     */
    public void drawImage(Texture texture, float x, float y, float width, float height, TextureRegion region) {
        x = x + complementX;
        y = y + complementY;

        texture.bind();
        beginDraw(DrawType.QUADS);
        glTexCoord2f(region.getMinX(), region.getMinY());
        setVertex2f(x, y + height);
        glTexCoord2f(region.getMinX(), region.getMaxY());
        setVertex2f(x, y);
        glTexCoord2f(region.getMaxX(), region.getMaxY());
        setVertex2f(x + width, y);
        glTexCoord2f(region.getMaxX(), region.getMinY());
        setVertex2f(x + width, y + height);
        endDraw();
        texture.unbind();
    }

    /**
     * <p>Draws simple ASCII text with STB.</p>
     *
     * @param text Text to draw.
     * @param x    X start of the text.
     * @param y    Y start of the text.
     */
    public void drawSTBEasyText(String text, float x, float y) {
        x = x + complementX;
        y = y + complementY;
        drawText(EasyFont.INSTANCE, text, x, y);
    }

    /**
     * Draws a text.
     *
     * @param font Font used for the text.
     * @param text Text to draw.
     * @param x    X start of the text.
     * @param y    Y start of the text.
     */
    public void drawText(Font font, String text, float x, float y) {
        x = x + complementX;
        y = y + complementY;

        font.draw(this, text, x, y);
    }
}