com.badlogic.gdx.backends.lwjgl.LwjglCanvas.java Source code

Java tutorial

Introduction

Here is the source code for com.badlogic.gdx.backends.lwjgl.LwjglCanvas.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.lwjgl;

import java.awt.Canvas;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.HashMap;
import java.util.Map;

import org.lwjgl.opengl.Display;

import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Audio;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.LifecycleListener;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.backends.lwjgl.audio.OpenALAudio;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard;
import com.badlogic.gdx.utils.SharedLibraryLoader;

/** An OpenGL surface on an AWT Canvas, allowing OpenGL to be embedded in a Swing application. All OpenGL calls are done on the
 * EDT. This is slightly less efficient than a dedicated thread, but greatly simplifies synchronization. Note that you may need to
 * call {@link #stop()} or a Swing application may deadlock on System.exit due to how LWJGL and/or Swing deal with shutdown hooks.
 * @author Nathan Sweet */
public class LwjglCanvas implements Application {
    LwjglGraphics graphics;
    OpenALAudio audio;
    LwjglFiles files;
    LwjglInput input;
    LwjglNet net;
    ApplicationListener listener;
    Canvas canvas;
    final Array<Runnable> runnables = new Array();
    final Array<Runnable> executedRunnables = new Array();
    final Array<LifecycleListener> lifecycleListeners = new Array<LifecycleListener>();
    boolean running = true;
    int logLevel = LOG_INFO;
    Cursor cursor;

    public LwjglCanvas(ApplicationListener listener) {
        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        initialize(listener, config);
    }

    public LwjglCanvas(ApplicationListener listener, LwjglApplicationConfiguration config) {
        initialize(listener, config);
    }

    private void initialize(ApplicationListener listener, LwjglApplicationConfiguration config) {
        LwjglNativesLoader.load();

        canvas = new Canvas() {
            private final Dimension minSize = new Dimension(1, 1);

            public final void addNotify() {
                super.addNotify();
                if (SharedLibraryLoader.isMac) {
                    EventQueue.invokeLater(new Runnable() {
                        public void run() {
                            create();
                        }
                    });
                } else
                    create();
            }

            public final void removeNotify() {
                stop();
                super.removeNotify();
            }

            public Dimension getMinimumSize() {
                return minSize;
            }
        };
        canvas.setSize(1, 1);
        canvas.setIgnoreRepaint(true);

        graphics = new LwjglGraphics(canvas, config) {
            public void setTitle(String title) {
                super.setTitle(title);
                LwjglCanvas.this.setTitle(title);
            }

            public boolean setDisplayMode(int width, int height, boolean fullscreen) {
                if (!super.setDisplayMode(width, height, fullscreen))
                    return false;
                if (!fullscreen)
                    LwjglCanvas.this.setDisplayMode(width, height);
                return true;
            }

            public boolean setDisplayMode(DisplayMode displayMode) {
                if (!super.setDisplayMode(displayMode))
                    return false;
                LwjglCanvas.this.setDisplayMode(displayMode.width, displayMode.height);
                return true;
            }
        };
        graphics.setVSync(config.vSyncEnabled);
        if (!LwjglApplicationConfiguration.disableAudio)
            audio = new OpenALAudio();
        files = new LwjglFiles();
        input = new LwjglInput();
        net = new LwjglNet();
        this.listener = listener;

        Gdx.app = this;
        Gdx.graphics = graphics;
        Gdx.audio = audio;
        Gdx.files = files;
        Gdx.input = input;
        Gdx.net = net;
    }

    protected void setDisplayMode(int width, int height) {
    }

    protected void setTitle(String title) {
    }

    @Override
    public ApplicationListener getApplicationListener() {
        return listener;
    }

    public Canvas getCanvas() {
        return canvas;
    }

    @Override
    public Audio getAudio() {
        return audio;
    }

    @Override
    public Files getFiles() {
        return files;
    }

    @Override
    public Graphics getGraphics() {
        return graphics;
    }

    @Override
    public Input getInput() {
        return input;
    }

    @Override
    public Net getNet() {
        return net;
    }

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

    @Override
    public int getVersion() {
        return 0;
    }

    void create() {
        try {
            graphics.setupDisplay();

            listener.create();
            listener.resize(Math.max(1, graphics.getWidth()), Math.max(1, graphics.getHeight()));

            start();
        } catch (Exception ex) {
            stopped();
            exception(ex);
            return;
        }

        EventQueue.invokeLater(new Runnable() {
            int lastWidth = Math.max(1, graphics.getWidth());
            int lastHeight = Math.max(1, graphics.getHeight());

            public void run() {
                if (!running || Display.isCloseRequested()) {
                    running = false;
                    stopped();
                    return;
                }
                try {
                    graphics.updateTime();

                    int width = Math.max(1, graphics.getWidth());
                    int height = Math.max(1, graphics.getHeight());
                    if (lastWidth != width || lastHeight != height) {
                        lastWidth = width;
                        lastHeight = height;
                        Gdx.gl.glViewport(0, 0, lastWidth, lastHeight);
                        resize(width, height);
                        listener.resize(width, height);
                    }

                    executeRunnables();

                    input.update();
                    input.processEvents();
                    graphics.frameId++;
                    listener.render();
                    if (audio != null)
                        audio.update();
                    Display.update();
                    canvas.setCursor(cursor);
                    Display.sync(getFrameRate());
                } catch (Throwable ex) {
                    exception(ex);
                }
                EventQueue.invokeLater(this);
            }
        });
    }

    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;
    }

    protected int getFrameRate() {
        int frameRate = Display.isActive() ? graphics.config.foregroundFPS : graphics.config.backgroundFPS;
        if (frameRate == -1)
            frameRate = 10;
        if (frameRate == 0)
            frameRate = graphics.config.backgroundFPS;
        if (frameRate == 0)
            frameRate = 30;
        return frameRate;
    }

    protected void exception(Throwable ex) {
        ex.printStackTrace();
        stop();
    }

    /** Called after {@link ApplicationListener} create and resize, but before the game loop iteration. */
    protected void start() {
    }

    /** Called when the canvas size changes. */
    protected void resize(int width, int height) {
    }

    /** Called when the game loop has stopped. */
    protected void stopped() {
    }

    public void stop() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                if (!running)
                    return;
                running = false;
                try {
                    Display.destroy();
                    if (audio != null)
                        audio.dispose();
                } catch (Throwable ignored) {
                }
                Array<LifecycleListener> listeners = lifecycleListeners;
                synchronized (listeners) {
                    for (LifecycleListener listener : listeners) {
                        listener.pause();
                        listener.dispose();
                    }
                }
                listener.pause();
                listener.dispose();
            }
        });
    }

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

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

    Map<String, Preferences> preferences = new HashMap<String, Preferences>();

    @Override
    public Preferences getPreferences(String name) {
        if (preferences.containsKey(name)) {
            return preferences.get(name);
        } else {
            Preferences prefs = new LwjglPreferences(name, ".prefs/");
            preferences.put(name, prefs);
            return prefs;
        }
    }

    @Override
    public Clipboard getClipboard() {
        return new LwjglClipboard();
    }

    @Override
    public void postRunnable(Runnable runnable) {
        synchronized (runnables) {
            runnables.add(runnable);
        }
    }

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

    @Override
    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);
        }
    }

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

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

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

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

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

    @Override
    public void exit() {
        postRunnable(new Runnable() {
            @Override
            public void run() {
                LwjglCanvas.this.listener.pause();
                LwjglCanvas.this.listener.dispose();
                if (audio != null)
                    audio.dispose();
                System.exit(-1);
            }
        });
    }

    /** @param cursor May be null. */
    public void setCursor(Cursor cursor) {
        this.cursor = cursor;
    }

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

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