com.badlogic.gdx.backends.jglfw.JglfwApplication.java Source code

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.backends.jglfw.JglfwApplication.java

Source

/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.badlogic.gdx.backends.jglfw;

import static com.badlogic.gdx.utils.SharedLibraryLoader.*;
import static com.badlogic.jglfw.Glfw.*;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Audio;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.LifecycleListener;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard;
import com.badlogic.gdx.utils.GdxNativesLoader;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.jglfw.GlfwCallbackAdapter;
import com.badlogic.jglfw.GlfwCallbacks;

import java.awt.EventQueue;
import java.util.HashMap;
import java.util.Map;

/** An OpenGL surface fullscreen or in a lightweight window using GLFW.
 * @author mzechner
 * @author Nathan Sweet */
public class JglfwApplication implements Application {
    JglfwGraphics graphics;
    JglfwFiles files;
    JglfwInput input;
    JglfwNet net;
    final ApplicationListener listener;
    private final Array<Runnable> runnables = new Array();
    private final Array<Runnable> executedRunnables = new Array();
    private final Array<LifecycleListener> lifecycleListeners = new Array();
    private final Map<String, Preferences> preferences = new HashMap();
    private final JglfwClipboard clipboard = new JglfwClipboard();
    private final GlfwCallbacks callbacks = new GlfwCallbacks();
    private int logLevel = LOG_INFO;
    volatile boolean running = true;
    boolean isPaused;
    protected String preferencesdir;

    private boolean forceExit, runOnEDT;
    private int foregroundFPS, backgroundFPS, hiddenFPS;

    public JglfwApplication(ApplicationListener listener) {
        this(listener, listener.getClass().getSimpleName(), 640, 480);
    }

    public JglfwApplication(ApplicationListener listener, String title, int width, int height) {
        this(listener, createConfig(title, width, height));
    }

    static private JglfwApplicationConfiguration createConfig(String title, int width, int height) {
        JglfwApplicationConfiguration config = new JglfwApplicationConfiguration();
        config.title = title;
        config.width = width;
        config.height = height;
        return config;
    }

    public JglfwApplication(final ApplicationListener listener, final JglfwApplicationConfiguration config) {
        if (listener == null)
            throw new IllegalArgumentException("listener cannot be null.");
        if (config == null)
            throw new IllegalArgumentException("config cannot be null.");

        this.listener = listener;

        Runnable runnable = new Runnable() {
            public void run() {
                try {
                    initialize(config);
                } catch (Throwable ex) {
                    exception(ex);
                }
            }
        };
        if (config.runOnEDT)
            EventQueue.invokeLater(runnable);
        else
            new Thread(runnable, "MainLoop").start();
    }

    /** Called when an uncaught exception happens in the game loop. Default implementation prints the exception and calls
     * System.exit(0). */
    protected void exception(Throwable ex) {
        ex.printStackTrace();
        System.exit(0);
    }

    void initialize(JglfwApplicationConfiguration config) {
        forceExit = config.forceExit;
        runOnEDT = config.runOnEDT;
        foregroundFPS = config.foregroundFPS;
        backgroundFPS = config.backgroundFPS;
        hiddenFPS = config.hiddenFPS;
        preferencesdir = config.preferencesLocation;

        final Thread glThread = Thread.currentThread();

        GdxNativesLoader.load();

        boolean inputCallbacksOnAppKitThread = isMac;
        if (inputCallbacksOnAppKitThread)
            java.awt.Toolkit.getDefaultToolkit(); // Ensure AWT is initialized before GLFW.

        if (!glfwInit())
            throw new GdxRuntimeException("Unable to initialize GLFW.");

        Gdx.app = this;
        Gdx.graphics = graphics = new JglfwGraphics(config);
        Gdx.files = files = new JglfwFiles();
        Gdx.input = input = new JglfwInput(this, inputCallbacksOnAppKitThread);
        Gdx.net = net = new JglfwNet();

        callbacks.add(new GlfwCallbackAdapter() {
            public void windowSize(long window, final int width, final int height) {
                Runnable runnable = new Runnable() {
                    public void run() {
                        graphics.sizeChanged(width, height);
                    }
                };
                if (Thread.currentThread() != glThread)
                    postRunnable(runnable);
                else
                    runnable.run();
            }

            public void windowPos(long window, final int x, final int y) {
                Runnable runnable = new Runnable() {
                    public void run() {
                        graphics.positionChanged(x, y);
                    }
                };
                if (Thread.currentThread() != glThread)
                    postRunnable(runnable);
                else
                    runnable.run();
            }

            public void windowRefresh(long window) {
                if (Thread.currentThread() == glThread)
                    render(System.nanoTime());
            }

            public void windowFocus(long window, boolean focused) {
                graphics.foreground = focused;
            }

            public void windowIconify(long window, boolean iconified) {
                graphics.minimized = iconified;
            }

            public boolean windowClose(long window) {
                if (shouldExit())
                    exit();
                return false;
            }

            public void error(int error, String description) {
                throw new GdxRuntimeException("GLFW error " + error + ": " + description);
            }
        });
        glfwSetCallback(callbacks);

        start();
    }

    /** Starts the game loop after the application internals have been initialized. */
    protected void start() {
        listener.create();
        listener.resize(graphics.getWidth(), graphics.getHeight());

        if (runOnEDT) {
            new Runnable() {
                public void run() {
                    frame();
                    if (running)
                        EventQueue.invokeLater(this);
                    else
                        end();
                }
            }.run();
        } else {
            while (running)
                frame();
            end();
        }
    }

    /** Handles posted runnables, input, and rendering for each frame. */
    protected void frame() {
        if (!running)
            return;

        if (executeRunnables())
            graphics.requestRendering();

        if (!running)
            return;

        input.update();

        long frameStartTime = System.nanoTime();
        int targetFPS = (graphics.isHidden() || graphics.isMinimized()) ? hiddenFPS : //
                (graphics.isForeground() ? foregroundFPS : backgroundFPS);

        if (targetFPS == -1) { // Rendering is paused.
            if (!isPaused)
                listener.pause();
            isPaused = true;
        } else {
            if (isPaused)
                listener.resume();
            isPaused = false;
            if (graphics.shouldRender())
                render(frameStartTime);
        }

        if (targetFPS != 0) {
            if (targetFPS == -1)
                sleep(100);
            else
                Sync.sync(targetFPS);
        }
    }

    public boolean executeRunnables() {
        synchronized (runnables) {
            executedRunnables.addAll(runnables);
            runnables.clear();
        }
        if (executedRunnables.size == 0)
            return false;
        for (int i = 0; i < executedRunnables.size; i++)
            executedRunnables.get(i).run();
        executedRunnables.clear();
        return true;
    }

    void sleep(int millis) {
        try {
            if (millis > 0)
                Thread.sleep(millis);
        } catch (InterruptedException ignored) {
        }
    }

    void render(long time) {
        graphics.frameStart(time);
        listener.render();
        glfwSwapBuffers(graphics.window);
    }

    /** Called when the game loop has exited. */
    protected void end() {
        synchronized (lifecycleListeners) {
            for (LifecycleListener listener : lifecycleListeners) {
                listener.pause();
                listener.dispose();
            }
        }
        listener.pause();
        listener.dispose();
        glfwTerminate();
        if (forceExit)
            System.exit(-1);
    }

    public ApplicationListener getApplicationListener() {
        return listener;
    }

    public JglfwGraphics getGraphics() {
        return graphics;
    }

    public Audio getAudio() {
        return null;
    }

    public JglfwInput getInput() {
        return input;
    }

    public JglfwFiles getFiles() {
        return files;
    }

    public JglfwNet getNet() {
        return net;
    }

    public ApplicationType getType() {
        return ApplicationType.Desktop;
    }

    public int getVersion() {
        return 0;
    }

    public long getJavaHeap() {
        return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
    }

    public long getNativeHeap() {
        return getJavaHeap();
    }

    public Preferences getPreferences(String name) {
        if (preferences.containsKey(name))
            return preferences.get(name);
        else {
            Preferences prefs = new JglfwPreferences(name, this.preferencesdir);
            preferences.put(name, prefs);
            return prefs;
        }
    }

    public Clipboard getClipboard() {
        return clipboard;
    }

    public void postRunnable(Runnable runnable) {
        synchronized (runnables) {
            runnables.add(runnable);
            graphics.requestRendering();
        }
    }

    public boolean isPaused() {
        return isPaused;
    }

    public void setForegroundFPS(int foregroundFPS) {
        this.foregroundFPS = foregroundFPS;
    }

    public void setBackgroundFPS(int backgroundFPS) {
        this.backgroundFPS = backgroundFPS;
    }

    public void setHiddenFPS(int hiddenFPS) {
        this.hiddenFPS = hiddenFPS;
    }

    protected boolean shouldExit() {
        return true;
    }

    public void exit() {
        running = false;
    }

    public void setLogLevel(int logLevel) {
        this.logLevel = logLevel;
    }

    @Override
    public int getLogLevel() {
        return logLevel;
    }

    public void debug(String tag, String message) {
        if (logLevel >= LOG_DEBUG) {
            System.out.println(tag + ": " + message);
        }
    }

    public void debug(String tag, String message, Throwable exception) {
        if (logLevel >= LOG_DEBUG) {
            System.out.println(tag + ": " + message);
            exception.printStackTrace(System.out);
        }
    }

    public void log(String tag, String message) {
        if (logLevel >= LOG_INFO) {
            System.out.println(tag + ": " + message);
        }
    }

    public void log(String tag, String message, Throwable exception) {
        if (logLevel >= LOG_INFO) {
            System.out.println(tag + ": " + message);
            exception.printStackTrace(System.out);
        }
    }

    public void error(String tag, String message) {
        if (logLevel >= LOG_ERROR) {
            System.err.println(tag + ": " + message);
        }
    }

    public void error(String tag, String message, Throwable exception) {
        if (logLevel >= LOG_ERROR) {
            System.err.println(tag + ": " + message);
            exception.printStackTrace(System.err);
        }
    }

    public void addLifecycleListener(LifecycleListener listener) {
        synchronized (lifecycleListeners) {
            lifecycleListeners.add(listener);
        }
    }

    public void removeLifecycleListener(LifecycleListener listener) {
        synchronized (lifecycleListeners) {
            lifecycleListeners.removeValue(listener, true);
        }
    }

    public GlfwCallbacks getCallbacks() {
        return callbacks;
    }
}