com.w67clement.openw67render.OpenContext.java Source code

Java tutorial

Introduction

Here is the source code for com.w67clement.openw67render.OpenContext.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;

import com.w67clement.openw67render.events.controllers.ControllerBaseListener.ControllerBaseCallback;
import com.w67clement.openw67render.events.input.KeyListener;
import com.w67clement.openw67render.gui.graphics.Shader;
import com.w67clement.openw67render.gui.screen.OpenOverlay;
import com.w67clement.openw67render.gui.screen.OpenScreen;
import com.w67clement.openw67render.registry.ShaderRegistry;
import com.w67clement.openw67render.registry.TextureRegistry;
import com.w67clement.openw67render.utils.ControllerInputDetectorThread;
import com.w67clement.openw67render.utils.OpenUtils;
import com.w67clement.openw67render.utils.Texture;
import com.w67clement.openw67render.utils.TickThread;
import com.w67clement.openw67render.window.OpenCursor;
import com.w67clement.openw67render.window.OpenWindow;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.opengl.GL;

import static org.lwjgl.glfw.Callbacks.glfwFreeCallbacks;
import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;

/**
 * Created by w67clement on 27/04/2016.
 * <p>
 * Class of project: openw67render
 */
public class OpenContext {
    /* STATIC */
    private static OpenContext instance;

    /* VARIABLES */
    private OpenRunnable runnable;

    // The window handle
    private OpenWindow window;

    private OpenScreen currentScreen;
    private List<OpenOverlay> overlays = new ArrayList<>();

    private List<KeyListener> keyListeners = new ArrayList<>();

    private int frames = 0;
    private int ticks = 0;

    private boolean isRunning = true;

    public OpenContext(OpenRunnable runnable) {
        this.runnable = runnable;
    }

    public static OpenContext createInstance(OpenRunnable runnable) {
        if (instance != null)
            throw new UnsupportedOperationException("Instance already created.");
        instance = new OpenContext(runnable);
        return instance;
    }

    public static OpenContext getInstance() {
        return instance;
    }

    public synchronized OpenScreen getScreen() {
        return currentScreen;
    }

    public synchronized void setScreen(OpenScreen screen) {
        if (!screen.equals(currentScreen)) {
            currentScreen = screen;
        }
    }

    public synchronized void addOverlay(OpenOverlay overlay) {
        if (!hasOverlay(overlay))
            overlays.add(overlay);
    }

    public synchronized boolean hasOverlay(OpenOverlay overlay) {
        return overlays.contains(overlay);
    }

    public synchronized boolean removeOverlay(OpenOverlay overlay) {
        return hasOverlay(overlay) && overlays.remove(overlay);
    }

    public Stream<OpenOverlay> listOverlay() {
        return overlays.stream();
    }

    public void addKeyListener(KeyListener keyListener) {
        if (!hasKeyListener(keyListener))
            keyListeners.add(keyListener);
    }

    public boolean hasKeyListener(KeyListener keyListener) {
        return keyListeners.contains(keyListener);
    }

    public boolean removeKeyListener(KeyListener keyListener) {
        return hasKeyListener(keyListener) && keyListeners.remove(keyListener);
    }

    public Stream<KeyListener> listKeyListeners() {
        return keyListeners.stream();
    }

    /**
     * Check whether the program is running or not.
     *
     * @return True if the program is running else false.
     */
    public boolean isRunning() {
        return isRunning;
    }

    /**
     * Gets the actual FPS of the program.
     *
     * @return Actual FPS of the program.
     */
    public int getFPS() {
        return frames;
    }

    /**
     * Gets the actual Ticks of the program.
     *
     * @return Actual Ticks of the program.
     */
    public int getTicks() {
        return ticks;
    }

    public void run() {
        try {
            OpenUtils.unpackNatives();
        } catch (IOException e) {
            if (e instanceof NoSuchFileException) {
                if (e.getMessage().equalsIgnoreCase("natives\\windows\\lwjgl.dll"))
                    try {
                        OpenUtils.unpackNatives();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
            }
            e.printStackTrace();
            return;
        }
        try {
            File assetsFolder = new File("assets/");
            if (!assetsFolder.exists())
                unpackDefaultShaders(assetsFolder);
            init();
            loop();

            // Destroy all textures.
            TextureRegistry.getInstance().list().forEach(Texture::delete);
            ShaderRegistry.getInstance().list().forEach(Shader::delete);
            // Free the window callbacks and destroy the window
            glfwFreeCallbacks(window.getWindowId());
            glfwDestroyWindow(window.getWindowId());

            runnable.destroy();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // Terminate GLFW and free the error callback
            glfwTerminate();
            glfwSetErrorCallback(null).free();
        }
    }

    private void init() throws Exception {
        // Setup an error callback. The default implementation
        // will print the error message in System.err.
        GLFWErrorCallback.createPrint(System.err).set();

        // Initialize GLFW. Most GLFW functions will not work before doing this.
        if (!glfwInit())
            throw new IllegalStateException("Unable to initialize GLFW");

        // Configure our window
        glfwDefaultWindowHints(); // optional, the current window hints are already the default
        glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); // the window will stay hidden after creation
        glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); // the window will be resizable

        OpenCursor.hello();

        runnable.init();

        window = runnable.createWindow();

        ControllerInputDetectorThread controllerInputDetector = new ControllerInputDetectorThread(this);
        controllerInputDetector.start();

        glfwSetJoystickCallback(new ControllerBaseCallback());
    }

    private void loop() {
        // This line is critical for LWJGL's interoperation with GLFW's
        // OpenGL context, or any context that is managed externally.
        // LWJGL detects the context that is current in the current thread,
        // creates the GLCapabilities instance and makes the OpenGL
        // bindings available for use.
        GL.createCapabilities();

        long timer = System.currentTimeMillis();

        // FPS
        int frames = 0;

        TickThread tickThread = new TickThread(this);
        tickThread.start();

        runnable.postInit(window, this);

        while ((!glfwWindowShouldClose(window.getWindowId()))) {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the framebuffer

            frames++;
            currentScreen.paint(currentScreen.getGraphics());
            overlays.forEach(overlay -> overlay.paint(overlay.getGraphics()));

            if (System.currentTimeMillis() - timer > 1000) {
                timer += 1000;
                this.frames = frames;
                ticks = tickThread.resetTempTicks();
                frames = 0;
            }

            glfwSwapBuffers(window.getWindowId()); // swap the color buffers

            // Poll for window events. The key callback above will only be
            // invoked during this call.
            glfwPollEvents();
        }
        isRunning = false;
    }

    private void unpackDefaultShaders(File assetsFolder) throws IOException {
        if (!assetsFolder.exists())
            Files.createDirectories(assetsFolder.toPath());
        if (!Files.isDirectory(assetsFolder.toPath())) {
            Files.createDirectory(assetsFolder.toPath());
        }
        Files.copy(OpenContext.class.getResourceAsStream("/default.frag"),
                new File(assetsFolder, "default.frag").toPath());
        Files.copy(OpenContext.class.getResourceAsStream("/default.vert"),
                new File(assetsFolder, "default.vert").toPath());
        Files.copy(OpenContext.class.getResourceAsStream("/legacy.frag"),
                new File(assetsFolder, "legacy.frag").toPath());
        Files.copy(OpenContext.class.getResourceAsStream("/legacy.vert"),
                new File(assetsFolder, "legacy.vert").toPath());
    }

    /**
     * Shutdown the program.
     */
    public void shutdown() {
        isRunning = false;
        glfwSetWindowShouldClose(window.getWindowId(), true);
    }
}