com.badlogic.gdx.backends.gwt.GwtGraphics Maven / Gradle / Ivy
Show all versions of vtm-web Show documentation
/*******************************************************************************
* 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.gwt;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.graphics.Cursor;
import com.badlogic.gdx.graphics.Cursor.SystemCursor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.GL30;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.glutils.GLVersion;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.webgl.client.WebGLContextAttributes;
import com.google.gwt.webgl.client.WebGLRenderingContext;
import org.oscim.gdx.client.GdxGL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GwtGraphics implements Graphics {
static final Logger log = LoggerFactory.getLogger(GwtGraphics.class);
/* Enum values from http://www.w3.org/TR/screen-orientation. Filtered based on what the browsers actually support. */
public enum OrientationLockType {
LANDSCAPE("landscape"), PORTRAIT("portrait"), PORTRAIT_PRIMARY("portrait-primary"), PORTRAIT_SECONDARY(
"portrait-secondary"), LANDSCAPE_PRIMARY("landscape-primary"), LANDSCAPE_SECONDARY("landscape-secondary");
private final String name;
private OrientationLockType(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
;
CanvasElement canvas;
WebGLRenderingContext context;
GLVersion glVersion;
GL20 gl;
String extensions;
float fps = 0;
long lastTimeStamp = System.currentTimeMillis();
long frameId = -1;
float deltaTime = 0;
float time = 0;
int frames;
GwtApplicationConfiguration config;
double pixelRatio;
public GwtGraphics(Panel root, GwtApplicationConfiguration config) {
this.pixelRatio = getDevicePixelRatioJSNI();
if (config.canvasId == null) {
Canvas canvasWidget = Canvas.createIfSupported();
if (canvasWidget == null)
throw new GdxRuntimeException("Canvas not supported");
canvas = canvasWidget.getCanvasElement();
root.add(canvasWidget);
} else {
canvas = (CanvasElement) Document.get().getElementById(config.canvasId);
canvas.setWidth((int) (config.width * pixelRatio));
canvas.setHeight((int) (config.height * pixelRatio));
canvas.getStyle().setWidth(config.width, Style.Unit.PX);
canvas.getStyle().setHeight(config.height, Style.Unit.PX);
}
this.config = config;
WebGLContextAttributes attributes = WebGLContextAttributes.create();
attributes.setAntialias(config.antialiasing);
attributes.setStencil(config.stencil);
attributes.setAlpha(false);
attributes.setPremultipliedAlpha(false);
attributes.setPreserveDrawingBuffer(false);
context = WebGLRenderingContext.getContext(canvas, attributes);
if (context == null)
throw new GdxRuntimeException("Could not create Canvas for " + attributes);
context.viewport(0, 0, config.width, config.height);
// this actually *enables* the option to use std derivatives in shader..
if (context.getExtension("OES_standard_derivatives") == null) {
log.error("Missing gl extension for OES_standard_derivatives");
}
if (context.getExtension("WEBKIT_WEBGL_depth_texture") == null) {
log.error("Missing gl extension for WEBKIT_WEBGL_depth_texture");
}
this.gl = config.useDebugGL ? new GwtGL20Debug(context) : new GdxGL(context);
String versionString = gl.glGetString(GL20.GL_VERSION);
String vendorString = gl.glGetString(GL20.GL_VENDOR);
String rendererString = gl.glGetString(GL20.GL_RENDERER);
glVersion = new GLVersion(Application.ApplicationType.WebGL, versionString, vendorString, rendererString);
}
public static native double getDevicePixelRatioJSNI() /*-{
return $wnd.devicePixelRatio || 1.0;
}-*/;
public static native int getWindowWidthJSNI() /*-{
return $wnd.innerWidth;
}-*/;
public static native int getWindowHeightJSNI() /*-{
return $wnd.innerHeight;
}-*/;
public WebGLRenderingContext getContext() {
return context;
}
@Override
public GL20 getGL20() {
return gl;
}
@Override
public void setGL20(GL20 gl20) {
this.gl = gl20;
Gdx.gl = gl20;
Gdx.gl20 = gl20;
}
@Override
public boolean isGL30Available() {
return false;
}
@Override
public GL30 getGL30() {
return null;
}
@Override
public void setGL30(GL30 gl30) {
}
@Override
public int getWidth() {
return canvas.getWidth();
}
@Override
public int getHeight() {
return canvas.getHeight();
}
@Override
public int getBackBufferWidth() {
return canvas.getWidth();
}
@Override
public int getBackBufferHeight() {
return canvas.getHeight();
}
@Override
public long getFrameId() {
return frameId;
}
@Override
public float getDeltaTime() {
return deltaTime;
}
@Override
public int getFramesPerSecond() {
return (int) fps;
}
@Override
public GraphicsType getType() {
return GraphicsType.WebGL;
}
@Override
public GLVersion getGLVersion() {
return glVersion;
}
@Override
public float getPpiX() {
return 96;
}
@Override
public float getPpiY() {
return 96;
}
@Override
public float getPpcX() {
return 96 / 2.54f;
}
@Override
public float getPpcY() {
return 96 / 2.54f;
}
@Override
public boolean supportsDisplayModeChange() {
return supportsFullscreenJSNI();
}
private native boolean supportsFullscreenJSNI() /*-{
if ("fullscreenEnabled" in $doc) {
return $doc.fullscreenEnabled;
}
if ("webkitFullscreenEnabled" in $doc) {
return $doc.webkitFullscreenEnabled;
}
if ("mozFullScreenEnabled" in $doc) {
return $doc.mozFullScreenEnabled;
}
if ("msFullscreenEnabled" in $doc) {
return $doc.msFullscreenEnabled;
}
return false;
}-*/;
@Override
public DisplayMode[] getDisplayModes() {
return new DisplayMode[]{new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60, 8) {
}};
}
private native int getScreenWidthJSNI() /*-{
return $wnd.screen.width;
}-*/;
private native int getScreenHeightJSNI() /*-{
return $wnd.screen.height;
}-*/;
private native boolean isFullscreenJSNI() /*-{
// Standards compliant check for fullscreen
if ("fullscreenElement" in $doc) {
return $doc.fullscreenElement != null;
}
// Vendor prefixed versions of standard check
if ("msFullscreenElement" in $doc) {
return $doc.msFullscreenElement != null;
}
if ("webkitFullscreenElement" in $doc) {
return $doc.webkitFullscreenElement != null;
}
if ("mozFullScreenElement" in $doc) { // Yes, with a capital 'S'
return $doc.mozFullScreenElement != null;
}
// Older, non-standard ways of checking for fullscreen
if ("webkitIsFullScreen" in $doc) {
return $doc.webkitIsFullScreen;
}
if ("mozFullScreen" in $doc) {
return $doc.mozFullScreen;
}
return false
}-*/;
private void fullscreenChanged() {
if (!isFullscreen()) {
canvas.setWidth(config.width);
canvas.setHeight(config.height);
if (config.fullscreenOrientation != null) unlockOrientation();
} else {
/* We just managed to go full-screen. Check if the user has requested a specific orientation. */
if (config.fullscreenOrientation != null) lockOrientation(config.fullscreenOrientation);
}
}
private native boolean setFullscreenJSNI(GwtGraphics graphics, CanvasElement element) /*-{
// Attempt to use the non-prefixed standard API (https://fullscreen.spec.whatwg.org)
if (element.requestFullscreen) {
element.width = $wnd.screen.width;
element.height = $wnd.screen.height;
element.requestFullscreen();
$doc
.addEventListener(
"fullscreenchange",
function() {
[email protected]::fullscreenChanged()();
}, false);
return true;
}
// Attempt to the vendor specific variants of the API
if (element.webkitRequestFullScreen) {
element.width = $wnd.screen.width;
element.height = $wnd.screen.height;
element.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT);
$doc
.addEventListener(
"webkitfullscreenchange",
function() {
[email protected]::fullscreenChanged()();
}, false);
return true;
}
if (element.mozRequestFullScreen) {
element.width = $wnd.screen.width;
element.height = $wnd.screen.height;
element.mozRequestFullScreen();
$doc
.addEventListener(
"mozfullscreenchange",
function() {
[email protected]::fullscreenChanged()();
}, false);
return true;
}
if (element.msRequestFullscreen) {
element.width = $wnd.screen.width;
element.height = $wnd.screen.height;
element.msRequestFullscreen();
$doc
.addEventListener(
"msfullscreenchange",
function() {
[email protected]::fullscreenChanged()();
}, false);
return true;
}
return false;
}-*/;
private native void exitFullscreen() /*-{
if ($doc.exitFullscreen)
$doc.exitFullscreen();
if ($doc.msExitFullscreen)
$doc.msExitFullscreen();
if ($doc.webkitExitFullscreen)
$doc.webkitExitFullscreen();
if ($doc.mozExitFullscreen)
$doc.mozExitFullscreen();
if ($doc.webkitCancelFullScreen) // Old WebKit
$doc.webkitCancelFullScreen();
}-*/;
@Override
public DisplayMode getDisplayMode() {
return new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60, 8) {
};
}
@Override
public boolean setFullscreenMode(DisplayMode displayMode) {
if (displayMode.width != getScreenWidthJSNI() && displayMode.height != getScreenHeightJSNI())
return false;
return setFullscreenJSNI(this, canvas);
}
@Override
public boolean setWindowedMode(int width, int height) {
if (isFullscreenJSNI()) exitFullscreen();
canvas.setWidth(width);
canvas.setHeight(height);
return true;
}
@Override
public Monitor getPrimaryMonitor() {
return new GwtMonitor(0, 0, "Primary Monitor");
}
@Override
public Monitor getMonitor() {
return getPrimaryMonitor();
}
@Override
public Monitor[] getMonitors() {
return new Monitor[]{getPrimaryMonitor()};
}
@Override
public DisplayMode[] getDisplayModes(Monitor monitor) {
return getDisplayModes();
}
@Override
public DisplayMode getDisplayMode(Monitor monitor) {
return getDisplayMode();
}
/**
* Attempt to lock the orientation. Typically only supported when in full-screen mode.
*
* @param orientation the orientation to attempt locking
* @return did the locking succeed
*/
public boolean lockOrientation(OrientationLockType orientation) {
return lockOrientationJSNI(orientation.getName());
}
/**
* Attempt to unlock the orientation.
*
* @return did the unlocking succeed
*/
public boolean unlockOrientation() {
return unlockOrientationJSNI();
}
private native boolean lockOrientationJSNI(String orientationEnumValue) /*-{
var screen = $wnd.screen;
// Attempt to find the lockOrientation function
screen.gdxLockOrientation = screen.lockOrientation
|| screen.mozLockOrientation || screen.msLockOrientation
|| screen.webkitLockOrientation;
if (screen.gdxLockOrientation) {
return screen.gdxLockOrientation(orientationEnumValue);
}
// Actually, the Chrome guys do things a little different for now
else if (screen.orientation && screen.orientation.lock) {
screen.orientation.lock(orientationEnumValue);
// The Chrome API is async, so we can't at this point tell if we succeeded
return true;
}
return false;
}-*/;
private native boolean unlockOrientationJSNI() /*-{
var screen = $wnd.screen;
// Attempt to find the lockOrientation function
screen.gdxUnlockOrientation = screen.unlockOrientation
|| screen.mozUnlockOrientation || screen.msUnlockOrientation
|| screen.webkitUnlockOrientation;
if (screen.gdxUnlockOrientation) {
return screen.gdxUnlockOrientation();
}
// Actually, the Chrome guys do things a little different for now
else if (screen.orientation && screen.orientation.unlock) {
screen.orientation.unlock();
// The Chrome API is async, so we can't at this point tell if we succeeded
return true;
}
return false;
}-*/;
@Override
public BufferFormat getBufferFormat() {
return new BufferFormat(8, 8, 8, 0, 16, config.stencil ? 8 : 0, 0, false);
}
@Override
public boolean supportsExtension(String extensionName) {
// Contrary to regular OpenGL, WebGL extensions need to be explicitly enabled before they can be used. See
// https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Using_Extensions
// Thus, it is not safe to use an extension just because context.getSupportedExtensions() tells you it is available.
// We need to call getExtension() to enable it.
return context.getExtension(extensionName) != null;
}
public void update() {
long currTimeStamp = System.currentTimeMillis();
deltaTime = (currTimeStamp - lastTimeStamp) / 1000.0f;
lastTimeStamp = currTimeStamp;
time += deltaTime;
frames++;
if (time > 1) {
this.fps = frames;
time = 0;
frames = 0;
}
}
@Override
public void setTitle(String title) {
}
@Override
public void setUndecorated(boolean undecorated) {
}
@Override
public void setResizable(boolean resizable) {
}
@Override
public void setVSync(boolean vsync) {
}
@Override
public float getDensity() {
return 96.0f / 160;
}
@Override
public void setContinuousRendering(boolean isContinuous) {
}
@Override
public boolean isContinuousRendering() {
return false;
}
@Override
public void requestRendering() {
}
@Override
public float getRawDeltaTime() {
return getDeltaTime();
}
@Override
public boolean isFullscreen() {
return isFullscreenJSNI();
}
@Override
public Cursor newCursor(Pixmap pixmap, int xHotspot, int yHotspot) {
return new GwtCursor(pixmap, xHotspot, yHotspot);
}
@Override
public void setCursor(Cursor cursor) {
((GwtApplication) Gdx.app).graphics.canvas.getStyle().setProperty("cursor", ((GwtCursor) cursor).cssCursorProperty);
}
@Override
public void setSystemCursor(SystemCursor systemCursor) {
((GwtApplication) Gdx.app).graphics.canvas.getStyle().setProperty("cursor", GwtCursor.getNameForSystemCursor(systemCursor));
}
static class GwtMonitor extends Monitor {
protected GwtMonitor(int virtualX, int virtualY, String name) {
super(virtualX, virtualY, name);
}
}
}