Update vtm-web modules (#240) #51

This commit is contained in:
Izumi Kawashima 2016-11-20 17:37:01 +09:00 committed by Emux
parent bfa5a095f0
commit 308497ffa6
16 changed files with 1410 additions and 752 deletions

View File

@ -40,6 +40,7 @@ If you have any questions or problems, don't hesitate to ask our public [mailing
- **vtm-web-app** HTML5/GWT application - **vtm-web-app** HTML5/GWT application
The libGDX backend for GWT is experimental. The libGDX backend for GWT is experimental.
- `./gradlew :vtm-web-app:jettyDraftWar` will run standalone Jetty server at port 8080. See http://localhost:8080/vtm-web-app in your web browser.
## Applications ## Applications
- VTM is used by many [applications](docs/Applications.md). - VTM is used by many [applications](docs/Applications.md).

View File

@ -15,6 +15,7 @@ allprojects {
ext.androidBuildVersionTools = "25.0.0" ext.androidBuildVersionTools = "25.0.0"
ext.gdxVersion = "1.9.4" ext.gdxVersion = "1.9.4"
ext.gwtVersion = "2.7.0"
if (JavaVersion.current().isJava8Compatible()) { if (JavaVersion.current().isJava8Compatible()) {
tasks.withType(Javadoc) { tasks.withType(Javadoc) {

View File

@ -10,8 +10,8 @@ include ':vtm-themes'
include ':vtm-gdx' include ':vtm-gdx'
include ':vtm-desktop' include ':vtm-desktop'
include ':vtm-android-gdx' include ':vtm-android-gdx'
//include ':vtm-web' include ':vtm-web'
//include ':vtm-web-app' include ':vtm-web-app'
//include ':vtm-web-js' //include ':vtm-web-js'
include ':vtm-jeo' include ':vtm-jeo'
include ':vtm-playground' include ':vtm-playground'

View File

@ -5,7 +5,7 @@ buildscript {
maven { url 'http://dl.bintray.com/steffenschaefer/maven' } maven { url 'http://dl.bintray.com/steffenschaefer/maven' }
} }
dependencies { dependencies {
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.5' classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
} }
} }
@ -38,7 +38,7 @@ evaluationDependsOn(':vtm-gdx')
evaluationDependsOn(':vtm-web') evaluationDependsOn(':vtm-web')
gwt { gwt {
gwtVersion = '2.6.1' gwtVersion = project.ext.gwtVersion
modules 'org.oscim.web.VtmWebApp' modules 'org.oscim.web.VtmWebApp'
superDev { superDev {

View File

@ -6,8 +6,6 @@
<set-property name='gwt.logging.enabled' value='TRUE' /> <set-property name='gwt.logging.enabled' value='TRUE' />
<set-property name='gwt.logging.consoleHandler' value='ENABLED' /> <set-property name='gwt.logging.consoleHandler' value='ENABLED' />
<set-property name='gwt.logging.firebugHandler' value='DISABLED' />
<set-property name='gwt.logging.popupHandler' value='DISABLED' />
<set-property name="gwt.logging.logLevel" value="FINE" /> <set-property name="gwt.logging.logLevel" value="FINE" />
<!-- super dev mode --> <!-- super dev mode -->
@ -23,4 +21,5 @@
<set-configuration-property name="gdx.assetoutputpath" value="build/gwt/draftOut" /> <set-configuration-property name="gdx.assetoutputpath" value="build/gwt/draftOut" />
<set-property name="user.agent" value="safari" /> <set-property name="user.agent" value="safari" />
</module> </module>

View File

@ -27,6 +27,8 @@ import org.oscim.gdx.client.MapConfig;
public class GwtLauncher extends GwtApplication { public class GwtLauncher extends GwtApplication {
private ApplicationListener applicationListener;
@Override @Override
public GwtApplicationConfiguration getConfig() { public GwtApplicationConfiguration getConfig() {
@ -36,7 +38,6 @@ public class GwtLauncher extends GwtApplication {
cfg.canvasId = "map-canvas"; cfg.canvasId = "map-canvas";
cfg.stencil = true; cfg.stencil = true;
cfg.fps = 120;
return cfg; return cfg;
} }
@ -45,6 +46,14 @@ public class GwtLauncher extends GwtApplication {
public ApplicationListener getApplicationListener() { public ApplicationListener getApplicationListener() {
Tile.SIZE = MapConfig.get().getTileSize(); Tile.SIZE = MapConfig.get().getTileSize();
if (applicationListener == null) {
applicationListener = createApplicationListener();
}
return applicationListener;
}
@Override
public ApplicationListener createApplicationListener() {
return new GwtMap(); return new GwtMap();
} }

View File

@ -1,5 +1,6 @@
/* /*
* Copyright 2013 Hannes Janetzek * Copyright 2013 Hannes Janetzek
* Copyright 2016 Izumi Kawashima
* *
* This file is part of the OpenScienceMap project (http://www.opensciencemap.org). * This file is part of the OpenScienceMap project (http://www.opensciencemap.org).
* *
@ -63,6 +64,7 @@ class GwtMap extends GdxMap {
GdxAssets.init(""); GdxAssets.init("");
CanvasAdapter.textScale = 0.7f; CanvasAdapter.textScale = 0.7f;
log.debug("GLAdapter.init");
GLAdapter.init((GL) Gdx.graphics.getGL20()); GLAdapter.init((GL) Gdx.graphics.getGL20());
GLAdapter.GDX_WEBGL_QUIRKS = true; GLAdapter.GDX_WEBGL_QUIRKS = true;
MapRenderer.setBackgroundColor(0xffffff); MapRenderer.setBackgroundColor(0xffffff);
@ -92,12 +94,18 @@ class GwtMap extends GdxMap {
ts = DefaultSources.STAMEN_TONER.build(); ts = DefaultSources.STAMEN_TONER.build();
else if ("osm".equals(mapName)) else if ("osm".equals(mapName))
ts = DefaultSources.OPENSTREETMAP.build(); ts = DefaultSources.OPENSTREETMAP.build();
else if ("osm-transport".equals(mapName))
ts = DefaultSources.OSM_TRANSPORT.build();
else if ("watercolor".equals(mapName)) else if ("watercolor".equals(mapName))
ts = DefaultSources.STAMEN_WATERCOLOR.build(); ts = DefaultSources.STAMEN_WATERCOLOR.build();
else if ("arcgis-shaded".equals(mapName))
ts = DefaultSources.ARCGIS_RELIEF.build();
else if ("imagico".equals(mapName)) else if ("imagico".equals(mapName))
ts = DefaultSources.IMAGICO_LANDCOVER.build(); ts = DefaultSources.IMAGICO_LANDCOVER.build();
else if ("ne-landcover".equals(mapName))
ts = DefaultSources.NE_LANDCOVER.build();
else if ("hikebike".equals(mapName))
ts = DefaultSources.HIKEBIKE.build();
else if ("hikebike-hillshade".equals(mapName))
ts = DefaultSources.HIKEBIKE_HILLSHADE.build();
else else
ts = DefaultSources.STAMEN_TONER.build(); ts = DefaultSources.STAMEN_TONER.build();

View File

@ -5,7 +5,7 @@ buildscript {
maven { url 'http://dl.bintray.com/steffenschaefer/maven' } maven { url 'http://dl.bintray.com/steffenschaefer/maven' }
} }
dependencies { dependencies {
classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.5' classpath 'de.richsource.gradle.plugins:gwt-gradle-plugin:0.6'
} }
} }
@ -39,7 +39,7 @@ evaluationDependsOn(':vtm-gdx')
evaluationDependsOn(':vtm-web') evaluationDependsOn(':vtm-web')
gwt { gwt {
gwtVersion = '2.6.1' gwtVersion = project.ext.gwtVersion
modules 'org.oscim.web.VtmWebJs' modules 'org.oscim.web.VtmWebJs'
superDev { superDev {

View File

@ -10,8 +10,6 @@
<set-property name='gwt.logging.enabled' value='TRUE' /> <set-property name='gwt.logging.enabled' value='TRUE' />
<set-property name='gwt.logging.consoleHandler' value='ENABLED' /> <set-property name='gwt.logging.consoleHandler' value='ENABLED' />
<set-property name='gwt.logging.firebugHandler' value='DISABLED' />
<set-property name='gwt.logging.popupHandler' value='DISABLED' />
<set-property name="gwt.logging.logLevel" value="FINE" /> <set-property name="gwt.logging.logLevel" value="FINE" />
<!-- super dev mode --> <!-- super dev mode -->
@ -25,4 +23,8 @@
<set-configuration-property name="gdx.assetoutputpath" value="build/gwt/draftOut" /> <set-configuration-property name="gdx.assetoutputpath" value="build/gwt/draftOut" />
<set-property name="user.agent" value="safari" /> <set-property name="user.agent" value="safari" />
<set-property name="compiler.stackMode" value="emulated" />
<set-configuration-property name="compiler.emulatedStack.recordFileNames" value="true" />
<set-configuration-property name="compiler.emulatedStack.recordLineNumbers" value="true" />
</module> </module>

View File

@ -28,6 +28,8 @@ import org.timepedia.exporter.client.ExporterUtil;
public class GwtLauncher extends GwtApplication { public class GwtLauncher extends GwtApplication {
private ApplicationListener applicationListener;
@Override @Override
public void onModuleLoad() { public void onModuleLoad() {
//GWT.create(GwtGdxMap.class); //GWT.create(GwtGdxMap.class);
@ -46,7 +48,6 @@ public class GwtLauncher extends GwtApplication {
cfg.canvasId = "map-canvas"; cfg.canvasId = "map-canvas";
cfg.stencil = true; cfg.stencil = true;
cfg.fps = 120;
return cfg; return cfg;
} }
@ -55,6 +56,14 @@ public class GwtLauncher extends GwtApplication {
public ApplicationListener getApplicationListener() { public ApplicationListener getApplicationListener() {
Tile.SIZE = MapConfig.get().getTileSize(); Tile.SIZE = MapConfig.get().getTileSize();
if (applicationListener == null) {
applicationListener = createApplicationListener();
}
return applicationListener;
}
@Override
public ApplicationListener createApplicationListener() {
return new GwtMap(); return new GwtMap();
} }

View File

@ -1,12 +1,12 @@
/******************************************************************************* /*******************************************************************************
* Copyright 2011 See libgdx AUTHORS file. * Copyright 2011 See AUTHORS file.
* <p/> *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* <p/> *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* <p/> *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -29,37 +29,44 @@ import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.backends.gwt.preloader.Preloader; import com.badlogic.gdx.backends.gwt.preloader.Preloader;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderCallback; import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderCallback;
import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderState; import com.badlogic.gdx.backends.gwt.preloader.Preloader.PreloaderState;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard; import com.badlogic.gdx.utils.Clipboard;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
import com.google.gwt.animation.client.AnimationScheduler;
import com.google.gwt.animation.client.AnimationScheduler.AnimationCallback;
import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.Timer; import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import org.slf4j.Logger; /** Implementation of an {@link Application} based on GWT. Clients have to override {@link #getConfig()} and
import org.slf4j.LoggerFactory; * {@link #createApplicationListener()}. Clients can override the default loading screen via
* {@link #getPreloaderCallback()} and implement any loading screen drawing via GWT widgets.
/** * @author mzechner */
* Implementation of an {@link Application} based on GWT. Clients have to
* override {@link #getConfig()} and {@link #getApplicationListener()}. Clients
* can override the default loading screen via {@link #getPreloaderCallback()}
* and implement any loading screen drawing via GWT widgets.
*
* @author mzechner
*/
public abstract class GwtApplication implements EntryPoint, Application { public abstract class GwtApplication implements EntryPoint, Application {
private final static Logger log = LoggerFactory.getLogger(GwtApplication.class);
private ApplicationListener listener; private ApplicationListener listener;
private GwtApplicationConfiguration config; GwtApplicationConfiguration config;
private GwtGraphics graphics; GwtGraphics graphics;
private GwtInput input; private GwtInput input;
private GwtNet net; private GwtNet net;
private Panel root = null;
private TextArea log = null;
private int logLevel = LOG_ERROR; private int logLevel = LOG_ERROR;
private Array<Runnable> runnables = new Array<Runnable>(); private Array<Runnable> runnables = new Array<Runnable>();
private Array<Runnable> runnablesHelper = new Array<Runnable>(); private Array<Runnable> runnablesHelper = new Array<Runnable>();
@ -69,55 +76,104 @@ public abstract class GwtApplication implements EntryPoint, Application {
Preloader preloader; Preloader preloader;
private static AgentInfo agentInfo; private static AgentInfo agentInfo;
private ObjectMap<String, Preferences> prefs = new ObjectMap<String, Preferences>(); private ObjectMap<String, Preferences> prefs = new ObjectMap<String, Preferences>();
private Clipboard clipboard;
LoadingListener loadingListener;
/** /** @return the configuration for the {@link GwtApplication}. */
* @return the configuration for the {@link GwtApplication}. public abstract GwtApplicationConfiguration getConfig ();
*/
public abstract GwtApplicationConfiguration getConfig();
public String getPreloaderBaseURL() {
public String getPreloaderBaseURL()
{
return GWT.getHostPageBaseURL() + "assets/"; return GWT.getHostPageBaseURL() + "assets/";
} }
@Override @Override
public void onModuleLoad() { public ApplicationListener getApplicationListener() {
return listener;
}
public abstract ApplicationListener createApplicationListener();
@Override
public void onModuleLoad () {
GwtApplication.agentInfo = computeAgentInfo(); GwtApplication.agentInfo = computeAgentInfo();
this.listener = getApplicationListener(); this.listener = createApplicationListener();
this.config = getConfig(); this.config = getConfig();
this.log = config.log;
addEventListeners();
if (config.rootPanel != null) {
this.root = config.rootPanel;
} else {
Element element = Document.get().getElementById("embed-" + GWT.getModuleName());
if (element == null) {
VerticalPanel panel = new VerticalPanel();
panel.setWidth("" + config.width + "px");
panel.setHeight("" + config.height + "px");
panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
RootPanel.get().add(panel);
RootPanel.get().setWidth("" + config.width + "px");
RootPanel.get().setHeight("" + config.height + "px");
this.root = panel;
} else {
VerticalPanel panel = new VerticalPanel();
panel.setWidth("" + config.width + "px");
panel.setHeight("" + config.height + "px");
panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
element.appendChild(panel.getElement());
root = panel;
}
}
final PreloaderCallback callback = getPreloaderCallback(); final PreloaderCallback callback = getPreloaderCallback();
preloader = createPreloader(); preloader = createPreloader();
preloader.preload("assets.txt", new PreloaderCallback() { preloader.preload("assets.txt", new PreloaderCallback() {
@Override @Override
public void error(String file) { public void error (String file) {
callback.error(file); callback.error(file);
} }
@Override @Override
public void update(PreloaderState state) { public void update (PreloaderState state) {
callback.update(state); callback.update(state);
if (state.hasEnded()) { if (state.hasEnded()) {
//getRootPanel().clear(); getRootPanel().clear();
if(loadingListener != null)
loadingListener.beforeSetup();
setupLoop(); setupLoop();
if(loadingListener != null)
loadingListener.afterSetup();
} }
} }
}); });
} }
void setupLoop() { /**
Gdx.app = this; * Override this method to return a custom widget informing the that their browser lacks support of WebGL.
*
* @return Widget to display when WebGL is not supported.
*/
public Widget getNoWebGLSupportWidget() {
return new Label("Sorry, your browser doesn't seem to support WebGL");
}
void setupLoop () {
// setup modules // setup modules
try { try {
graphics = new GwtGraphics(null, config); graphics = new GwtGraphics(root, config);
} catch (Throwable e) { } catch (Throwable e) {
error("GwtApplication", "exception: " + e.getMessage(), e); root.clear();
//root.clear(); root.add(getNoWebGLSupportWidget());
//root.add(new Label("Sorry, your browser doesn't seem to support WebGL"));
return; return;
} }
lastWidth = graphics.getWidth(); lastWidth = graphics.getWidth();
lastHeight = graphics.getHeight(); lastHeight = graphics.getHeight();
Gdx.app = this; Gdx.app = this;
Gdx.audio = new GwtAudio();
Gdx.graphics = graphics; Gdx.graphics = graphics;
Gdx.gl20 = graphics.getGL20(); Gdx.gl20 = graphics.getGL20();
Gdx.gl = Gdx.gl20; Gdx.gl = Gdx.gl20;
@ -126,6 +182,8 @@ public abstract class GwtApplication implements EntryPoint, Application {
Gdx.input = this.input; Gdx.input = this.input;
this.net = new GwtNet(); this.net = new GwtNet();
Gdx.net = this.net; Gdx.net = this.net;
this.clipboard = new GwtClipboard();
updateLogLabelSize();
// tell listener about app creation // tell listener about app creation
try { try {
@ -137,26 +195,21 @@ public abstract class GwtApplication implements EntryPoint, Application {
throw new RuntimeException(t); throw new RuntimeException(t);
} }
Gdx.gl.glClearColor(1, 1, 1, 1); AnimationScheduler.get().requestAnimationFrame(new AnimationCallback() {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
final int frameTime = (int) ((1f / config.fps) * 1000);
// setup rendering timer
new Timer() {
@Override @Override
public void run() { public void execute (double timestamp) {
try { try {
mainLoop(this, frameTime); mainLoop();
} catch (Throwable t) { } catch (Throwable t) {
error("GwtApplication", "exception: " + t.getMessage(), t); error("GwtApplication", "exception: " + t.getMessage(), t);
throw new RuntimeException(t); throw new RuntimeException(t);
} }
AnimationScheduler.get().requestAnimationFrame(this, graphics.canvas);
} }
}.schedule(1); }, graphics.canvas);
} }
void mainLoop(Timer timer, int frameTime) { void mainLoop() {
graphics.update(); graphics.update();
if (Gdx.graphics.getWidth() != lastWidth || Gdx.graphics.getHeight() != lastHeight) { if (Gdx.graphics.getWidth() != lastWidth || Gdx.graphics.getHeight() != lastHeight) {
GwtApplication.this.listener.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); GwtApplication.this.listener.resize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
@ -170,17 +223,13 @@ public abstract class GwtApplication implements EntryPoint, Application {
runnablesHelper.get(i).run(); runnablesHelper.get(i).run();
} }
runnablesHelper.clear(); runnablesHelper.clear();
graphics.frameId++;
listener.render(); listener.render();
input.justTouched = false; input.reset();
long now = System.currentTimeMillis();
int diff = (int) (now - graphics.lastTimeStamp);
diff = frameTime - diff;
timer.schedule(diff > 5 ? diff : 5);
} }
public Panel getRootPanel() { public Panel getRootPanel () {
throw new GdxRuntimeException("no panel!"); return root;
} }
long loadStart = TimeUtils.nanoTime(); long loadStart = TimeUtils.nanoTime();
@ -189,27 +238,53 @@ public abstract class GwtApplication implements EntryPoint, Application {
return new Preloader(getPreloaderBaseURL()); return new Preloader(getPreloaderBaseURL());
} }
public PreloaderCallback getPreloaderCallback() { public PreloaderCallback getPreloaderCallback () {
return null; final Panel preloaderPanel = new VerticalPanel();
preloaderPanel.setStyleName("gdx-preloader");
final Image logo = new Image(GWT.getModuleBaseURL() + "logo.png");
logo.setStyleName("logo");
preloaderPanel.add(logo);
final Panel meterPanel = new SimplePanel();
meterPanel.setStyleName("gdx-meter");
meterPanel.addStyleName("red");
final InlineHTML meter = new InlineHTML();
final Style meterStyle = meter.getElement().getStyle();
meterStyle.setWidth(0, Unit.PCT);
meterPanel.add(meter);
preloaderPanel.add(meterPanel);
getRootPanel().add(preloaderPanel);
return new PreloaderCallback() {
@Override
public void error (String file) {
System.out.println("error: " + file);
}
@Override
public void update (PreloaderState state) {
meterStyle.setWidth(100f * state.getProgress(), Unit.PCT);
}
};
} }
@Override @Override
public Graphics getGraphics() { public Graphics getGraphics () {
return graphics; return graphics;
} }
@Override @Override
public Audio getAudio() { public Audio getAudio () {
return Gdx.audio; return Gdx.audio;
} }
@Override @Override
public Input getInput() { public Input getInput () {
return Gdx.input; return Gdx.input;
} }
@Override @Override
public Files getFiles() { public Files getFiles () {
return Gdx.files; return Gdx.files;
} }
@ -218,37 +293,107 @@ public abstract class GwtApplication implements EntryPoint, Application {
return Gdx.net; return Gdx.net;
} }
@Override private void updateLogLabelSize () {
public void log(String tag, String message) { if (log != null) {
log.info("{} : {}", tag, message); if (graphics != null) {
log.setSize(graphics.getWidth() + "px", "200px");
} else {
log.setSize("400px", "200px"); // Should not happen at this point, use dummy value
}
}
}
private void checkLogLabel () {
if (log == null) {
log = new TextArea();
// It's possible that log functions are called
// before the app is initialized. E.g. SoundManager can call log functions before the app is initialized.
// Since graphics is null, we're getting errors. The log size will be updated later, in case graphics was null
if (graphics != null) {
log.setSize(graphics.getWidth() + "px", "200px");
} else {
log.setSize("400px", "200px"); // Dummy value
}
log.setReadOnly(true);
root.add(log);
}
} }
@Override @Override
public void log(String tag, String message, Throwable exception) { public void log (String tag, String message) {
log.info("{} : {}\n{}", tag, exception, getStackTrace(exception)); if (logLevel >= LOG_INFO) {
checkLogLabel();
log.setText(log.getText() + "\n" + tag + ": " + message);
log.setCursorPos(log.getText().length() - 1);
System.out.println(tag + ": " + message);
}
} }
@Override @Override
public void error(String tag, String message) { public void log (String tag, String message, Throwable exception) {
log.error("{} : {}", tag, message); if (logLevel >= LOG_INFO) {
checkLogLabel();
log.setText(log.getText() + "\n" + tag + ": " + message + "\n" + getMessages(exception) + "\n");
log.setCursorPos(log.getText().length() - 1);
System.out.println(tag + ": " + message + "\n" + exception.getMessage());
System.out.println(getStackTrace(exception));
}
} }
@Override @Override
public void error(String tag, String message, Throwable exception) { public void error (String tag, String message) {
log.error("{} : {}\n{}", tag, message, getStackTrace(exception)); if (logLevel >= LOG_ERROR) {
checkLogLabel();
log.setText(log.getText() + "\n" + tag + ": " + message + "\n");
log.setCursorPos(log.getText().length() - 1);
System.err.println(tag + ": " + message);
}
} }
@Override @Override
public void debug(String tag, String message) { public void error (String tag, String message, Throwable exception) {
log.debug("{} : {}", tag, message); if (logLevel >= LOG_ERROR) {
checkLogLabel();
log.setText(log.getText() + "\n" + tag + ": " + message + "\n" + getMessages(exception) + "\n");
log.setCursorPos(log.getText().length() - 1);
System.err.println(tag + ": " + message + "\n" + exception.getMessage() + "\n");
System.out.println(getStackTrace(exception));
}
} }
@Override @Override
public void debug(String tag, String message, Throwable exception) { public void debug (String tag, String message) {
log.debug("{} : {}\n{}", tag, message, getStackTrace(exception)); if (logLevel >= LOG_DEBUG) {
checkLogLabel();
log.setText(log.getText() + "\n" + tag + ": " + message + "\n");
log.setCursorPos(log.getText().length() - 1);
System.out.println(tag + ": " + message + "\n");
}
} }
private String getStackTrace(Throwable e) { @Override
public void debug (String tag, String message, Throwable exception) {
if (logLevel >= LOG_DEBUG) {
checkLogLabel();
log.setText(log.getText() + "\n" + tag + ": " + message + "\n" + getMessages(exception) + "\n");
log.setCursorPos(log.getText().length() - 1);
System.out.println(tag + ": " + message + "\n" + exception.getMessage());
System.out.println(getStackTrace(exception));
}
}
private String getMessages (Throwable e) {
StringBuffer buffer = new StringBuffer();
while (e != null) {
buffer.append(e.getMessage() + "\n");
e = e.getCause();
}
return buffer.toString();
}
private String getStackTrace (Throwable e) {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
for (StackTraceElement trace : e.getStackTrace()) { for (StackTraceElement trace : e.getStackTrace()) {
buffer.append(trace.toString() + "\n"); buffer.append(trace.toString() + "\n");
@ -257,36 +402,37 @@ public abstract class GwtApplication implements EntryPoint, Application {
} }
@Override @Override
public void setLogLevel(int logLevel) { public void setLogLevel (int logLevel) {
this.logLevel = logLevel;
} }
@Override @Override
public int getLogLevel() { public int getLogLevel() {
return LOG_DEBUG; return logLevel;
} }
@Override @Override
public ApplicationType getType() { public ApplicationType getType () {
return ApplicationType.WebGL; return ApplicationType.WebGL;
} }
@Override @Override
public int getVersion() { public int getVersion () {
return 0; return 0;
} }
@Override @Override
public long getJavaHeap() { public long getJavaHeap () {
return 0; return 0;
} }
@Override @Override
public long getNativeHeap() { public long getNativeHeap () {
return 0; return 0;
} }
@Override @Override
public Preferences getPreferences(String name) { public Preferences getPreferences (String name) {
Preferences pref = prefs.get(name); Preferences pref = prefs.get(name);
if (pref == null) { if (pref == null) {
pref = new GwtPreferences(name); pref = new GwtPreferences(name);
@ -296,115 +442,151 @@ public abstract class GwtApplication implements EntryPoint, Application {
} }
@Override @Override
public Clipboard getClipboard() { public Clipboard getClipboard () {
return new Clipboard() { return clipboard;
@Override
public String getContents() {
return null;
}
@Override
public void setContents(String content) {
}
};
} }
@Override @Override
public void postRunnable(Runnable runnable) { public void postRunnable (Runnable runnable) {
runnables.add(runnable); runnables.add(runnable);
} }
@Override @Override
public void exit() { public void exit () {
} }
/** /** Contains precomputed information on the user-agent. Useful for dealing with browser and OS behavioral differences. Kindly
* Contains precomputed information on the user-agent. Useful for dealing * borrowed from PlayN */
* with browser and OS behavioral differences. Kindly public static AgentInfo agentInfo () {
* borrowed from PlayN
*/
public static AgentInfo agentInfo() {
return agentInfo; return agentInfo;
} }
/** /** kindly borrowed from PlayN **/
* kindly borrowed from PlayN private static native AgentInfo computeAgentInfo () /*-{
**/ var userAgent = navigator.userAgent.toLowerCase();
private static native AgentInfo computeAgentInfo() /*-{ return {
var userAgent = navigator.userAgent.toLowerCase(); // browser type flags
return { isFirefox : userAgent.indexOf("firefox") != -1,
// browser type flags isChrome : userAgent.indexOf("chrome") != -1,
isFirefox : userAgent.indexOf("firefox") != -1, isSafari : userAgent.indexOf("safari") != -1,
isChrome : userAgent.indexOf("chrome") != -1, isOpera : userAgent.indexOf("opera") != -1,
isSafari : userAgent.indexOf("safari") != -1, isIE : userAgent.indexOf("msie") != -1,
isOpera : userAgent.indexOf("opera") != -1, // OS type flags
isIE : userAgent.indexOf("msie") != -1, isMacOS : userAgent.indexOf("mac") != -1,
// OS type flags isLinux : userAgent.indexOf("linux") != -1,
isMacOS : userAgent.indexOf("mac") != -1, isWindows : userAgent.indexOf("win") != -1
isLinux : userAgent.indexOf("linux") != -1, };
isWindows : userAgent.indexOf("win") != -1 }-*/;
};
}-*/;
/** /** Returned by {@link #agentInfo}. Kindly borrowed from PlayN. */
* Returned by {@link #agentInfo}. Kindly borrowed from PlayN.
*/
public static class AgentInfo extends JavaScriptObject { public static class AgentInfo extends JavaScriptObject {
public final native boolean isFirefox() /*-{ public final native boolean isFirefox () /*-{
return this.isFirefox; return this.isFirefox;
}-*/; }-*/;
public final native boolean isChrome() /*-{ public final native boolean isChrome () /*-{
return this.isChrome; return this.isChrome;
}-*/; }-*/;
public final native boolean isSafari() /*-{ public final native boolean isSafari () /*-{
return this.isSafari; return this.isSafari;
}-*/; }-*/;
public final native boolean isOpera() /*-{ public final native boolean isOpera () /*-{
return this.isOpera; return this.isOpera;
}-*/; }-*/;
public final native boolean isIE() /*-{ public final native boolean isIE () /*-{
return this.isIE; return this.isIE;
}-*/; }-*/;
public final native boolean isMacOS() /*-{ public final native boolean isMacOS () /*-{
return this.isMacOS; return this.isMacOS;
}-*/; }-*/;
public final native boolean isLinux() /*-{ public final native boolean isLinux () /*-{
return this.isLinux; return this.isLinux;
}-*/; }-*/;
public final native boolean isWindows() /*-{ public final native boolean isWindows () /*-{
return this.isWindows; return this.isWindows;
}-*/; }-*/;
protected AgentInfo() { protected AgentInfo () {
} }
} }
public String getBaseUrl() { public String getBaseUrl () {
return preloader.baseUrl; return preloader.baseUrl;
} }
public Preloader getPreloader() { public Preloader getPreloader () {
return preloader; return preloader;
} }
public CanvasElement getCanvasElement(){
return graphics.canvas;
}
public LoadingListener getLoadingListener () {
return loadingListener;
}
public void setLoadingListener (LoadingListener loadingListener) {
this.loadingListener = loadingListener;
}
@Override @Override
public void addLifecycleListener(LifecycleListener listener) { public void addLifecycleListener (LifecycleListener listener) {
synchronized (lifecycleListeners) { synchronized(lifecycleListeners) {
lifecycleListeners.add(listener); lifecycleListeners.add(listener);
} }
} }
@Override @Override
public void removeLifecycleListener(LifecycleListener listener) { public void removeLifecycleListener (LifecycleListener listener) {
synchronized (lifecycleListeners) { synchronized(lifecycleListeners) {
lifecycleListeners.removeValue(listener, true); lifecycleListeners.removeValue(listener, true);
} }
} }
native static public void consoleLog(String message) /*-{
console.log( "GWT: " + message );
}-*/;
private native void addEventListeners () /*-{
var self = this;
$doc.addEventListener('visibilitychange', function (e) {
self.@com.badlogic.gdx.backends.gwt.GwtApplication::onVisibilityChange(Z)($doc['hidden'] !== true);
});
}-*/;
private void onVisibilityChange (boolean visible) {
if (visible) {
for (LifecycleListener listener : lifecycleListeners) {
listener.resume();
}
listener.resume();
} else {
for (LifecycleListener listener : lifecycleListeners) {
listener.pause();
}
listener.pause();
}
}
/**
* LoadingListener interface main purpose is to do some things before or after {@link GwtApplication#setupLoop()}
*/
public interface LoadingListener{
/**
* Method called before the setup
*/
public void beforeSetup();
/**
* Method called after the setup
*/
public void afterSetup();
}
} }

View File

@ -1,12 +1,12 @@
/******************************************************************************* /*******************************************************************************
* Copyright 2011 See libgdx AUTHORS file. * Copyright 2011 See AUTHORS file.
* <p/> *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* <p/> *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* <p/> *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -16,15 +16,20 @@
package com.badlogic.gdx.backends.gwt; package com.badlogic.gdx.backends.gwt;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics; 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.GL20;
import com.badlogic.gdx.graphics.GL30; 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.badlogic.gdx.utils.GdxRuntimeException;
import com.google.gwt.canvas.client.Canvas; import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.dom.client.CanvasElement; import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.webgl.client.WebGLContextAttributes; import com.google.gwt.webgl.client.WebGLContextAttributes;
import com.google.gwt.webgl.client.WebGLRenderingContext; import com.google.gwt.webgl.client.WebGLRenderingContext;
@ -36,20 +41,39 @@ import org.slf4j.LoggerFactory;
public class GwtGraphics implements Graphics { public class GwtGraphics implements Graphics {
static final Logger log = LoggerFactory.getLogger(GwtGraphics.class); 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; CanvasElement canvas;
WebGLRenderingContext context; WebGLRenderingContext context;
GLVersion glVersion;
GL20 gl; GL20 gl;
String extensions; String extensions;
float fps = 0; float fps = 0;
long lastTimeStamp = System.currentTimeMillis(); long lastTimeStamp = System.currentTimeMillis();
long frameId = -1;
float deltaTime = 0; float deltaTime = 0;
float time = 0; float time = 0;
int frames; int frames;
GwtApplicationConfiguration config; GwtApplicationConfiguration config;
boolean inFullscreenMode = false;
double pixelRatio; double pixelRatio;
public GwtGraphics(Panel root, final GwtApplicationConfiguration config) { public GwtGraphics(Panel root, GwtApplicationConfiguration config) {
this.pixelRatio = getDevicePixelRatioJSNI(); this.pixelRatio = getDevicePixelRatioJSNI();
if (config.canvasId == null) { if (config.canvasId == null) {
@ -64,10 +88,9 @@ public class GwtGraphics implements Graphics {
canvas.setWidth((int) (config.width * pixelRatio)); canvas.setWidth((int) (config.width * pixelRatio));
canvas.setHeight((int) (config.height * pixelRatio)); canvas.setHeight((int) (config.height * pixelRatio));
canvas.getStyle().setWidth(config.width, Unit.PX); canvas.getStyle().setWidth(config.width, Style.Unit.PX);
canvas.getStyle().setHeight(config.height, Unit.PX); canvas.getStyle().setHeight(config.height, Style.Unit.PX);
} }
this.config = config; this.config = config;
WebGLContextAttributes attributes = WebGLContextAttributes.create(); WebGLContextAttributes attributes = WebGLContextAttributes.create();
@ -75,11 +98,11 @@ public class GwtGraphics implements Graphics {
attributes.setStencil(config.stencil); attributes.setStencil(config.stencil);
attributes.setAlpha(false); attributes.setAlpha(false);
attributes.setPremultipliedAlpha(false); attributes.setPremultipliedAlpha(false);
attributes.setPreserveDrawingBuffer(false);
context = WebGLRenderingContext.getContext(canvas, attributes); context = WebGLRenderingContext.getContext(canvas, attributes);
if (context == null) if (context == null)
throw new GdxRuntimeException("Could not create Canvas for " + attributes); throw new GdxRuntimeException("Could not create Canvas for " + attributes);
context.viewport(0, 0, config.width, config.height); context.viewport(0, 0, config.width, config.height);
// this actually *enables* the option to use std derivatives in shader.. // this actually *enables* the option to use std derivatives in shader..
@ -92,6 +115,11 @@ public class GwtGraphics implements Graphics {
} }
this.gl = config.useDebugGL ? new GwtGL20Debug(context) : new GdxGL(context); 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() /*-{ public static native double getDevicePixelRatioJSNI() /*-{
@ -125,6 +153,21 @@ public class GwtGraphics implements Graphics {
return canvas.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 @Override
public float getDeltaTime() { public float getDeltaTime() {
return deltaTime; return deltaTime;
@ -140,6 +183,11 @@ public class GwtGraphics implements Graphics {
return GraphicsType.WebGL; return GraphicsType.WebGL;
} }
@Override
public GLVersion getGLVersion() {
return glVersion;
}
@Override @Override
public float getPpiX() { public float getPpiX() {
return 96; return 96;
@ -162,13 +210,28 @@ public class GwtGraphics implements Graphics {
@Override @Override
public boolean supportsDisplayModeChange() { public boolean supportsDisplayModeChange() {
return true; 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 @Override
public DisplayMode[] getDisplayModes() { public DisplayMode[] getDisplayModes() {
return new DisplayMode[]{new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60, return new DisplayMode[]{new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60, 8) {
8) {
}}; }};
} }
@ -181,6 +244,21 @@ public class GwtGraphics implements Graphics {
}-*/; }-*/;
private native boolean isFullscreenJSNI() /*-{ 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) { if ("webkitIsFullScreen" in $doc) {
return $doc.webkitIsFullScreen; return $doc.webkitIsFullScreen;
} }
@ -194,10 +272,28 @@ public class GwtGraphics implements Graphics {
if (!isFullscreen()) { if (!isFullscreen()) {
canvas.setWidth(config.width); canvas.setWidth(config.width);
canvas.setHeight(config.height); 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) /*-{ 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() {
graphics.@com.badlogic.gdx.backends.gwt.GwtGraphics::fullscreenChanged()();
}, false);
return true;
}
// Attempt to the vendor specific variants of the API
if (element.webkitRequestFullScreen) { if (element.webkitRequestFullScreen) {
element.width = $wnd.screen.width; element.width = $wnd.screen.width;
element.height = $wnd.screen.height; element.height = $wnd.screen.height;
@ -222,46 +318,140 @@ public class GwtGraphics implements Graphics {
}, false); }, false);
return true; return true;
} }
if (element.msRequestFullscreen) {
element.width = $wnd.screen.width;
element.height = $wnd.screen.height;
element.msRequestFullscreen();
$doc
.addEventListener(
"msfullscreenchange",
function() {
graphics.@com.badlogic.gdx.backends.gwt.GwtGraphics::fullscreenChanged()();
}, false);
return true;
}
return false; return false;
}-*/; }-*/;
private native void exitFullscreen() /*-{ private native void exitFullscreen() /*-{
if ($doc.exitFullscreen)
$doc.exitFullscreen();
if ($doc.msExitFullscreen)
$doc.msExitFullscreen();
if ($doc.webkitExitFullscreen) if ($doc.webkitExitFullscreen)
$doc.webkitExitFullscreen(); $doc.webkitExitFullscreen();
if ($doc.mozExitFullscreen) if ($doc.mozExitFullscreen)
$doc.mozExitFullscreen(); $doc.mozExitFullscreen();
if ($doc.webkitCancelFullScreen) // Old WebKit
$doc.webkitCancelFullScreen();
}-*/; }-*/;
@Override @Override
public DisplayMode getDesktopDisplayMode() { public DisplayMode getDisplayMode() {
return new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60, 8) { return new DisplayMode(getScreenWidthJSNI(), getScreenHeightJSNI(), 60, 8) {
}; };
} }
@Override @Override
public boolean setDisplayMode(DisplayMode displayMode) { public boolean setFullscreenMode(DisplayMode displayMode) {
if (displayMode.width != getScreenWidthJSNI() if (displayMode.width != getScreenWidthJSNI() && displayMode.height != getScreenHeightJSNI())
&& displayMode.height != getScreenHeightJSNI())
return false; return false;
return setFullscreenJSNI(this, canvas); return setFullscreenJSNI(this, canvas);
} }
@Override @Override
public boolean setDisplayMode(int width, int height, boolean fullscreen) { public boolean setWindowedMode(int width, int height) {
if (fullscreen) { if (isFullscreenJSNI()) exitFullscreen();
if (width != getScreenWidthJSNI() && height != getScreenHeightJSNI()) canvas.setWidth(width);
return false; canvas.setHeight(height);
return setFullscreenJSNI(this, canvas); return true;
} else { }
if (isFullscreenJSNI())
exitFullscreen();
canvas.setWidth(width); @Override
canvas.setHeight(height); public Monitor getPrimaryMonitor() {
canvas.getStyle().setWidth(width, Unit.PX); return new GwtMonitor(0, 0, "Primary Monitor");
canvas.getStyle().setHeight(height, Unit.PX); }
@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 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 @Override
public BufferFormat getBufferFormat() { public BufferFormat getBufferFormat() {
@ -269,10 +459,12 @@ public class GwtGraphics implements Graphics {
} }
@Override @Override
public boolean supportsExtension(String extension) { public boolean supportsExtension(String extensionName) {
if (extensions == null) // Contrary to regular OpenGL, WebGL extensions need to be explicitly enabled before they can be used. See
extensions = Gdx.gl.glGetString(GL20.GL_EXTENSIONS); // https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Using_Extensions
return extensions.contains(extension); // 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() { public void update() {
@ -292,6 +484,14 @@ public class GwtGraphics implements Graphics {
public void setTitle(String title) { public void setTitle(String title) {
} }
@Override
public void setUndecorated(boolean undecorated) {
}
@Override
public void setResizable(boolean resizable) {
}
@Override @Override
public void setVSync(boolean vsync) { public void setVSync(boolean vsync) {
} }
@ -335,8 +535,23 @@ public class GwtGraphics implements Graphics {
} }
@Override @Override
public long getFrameId() { public Cursor newCursor(Pixmap pixmap, int xHotspot, int yHotspot) {
// TODO Auto-generated method stub return new GwtCursor(pixmap, xHotspot, yHotspot);
return 0; }
@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);
}
} }
} }

View File

@ -1,12 +1,12 @@
/******************************************************************************* /*******************************************************************************
* Copyright 2011 See AUTHORS file. * Copyright 2011 See AUTHORS file.
* <p/> *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* <p/> *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* <p/> *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -21,28 +21,30 @@ import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.backends.gwt.widgets.TextInputDialogBox; import com.badlogic.gdx.backends.gwt.widgets.TextInputDialogBox;
import com.badlogic.gdx.backends.gwt.widgets.TextInputDialogBox.TextInputDialogListener; import com.badlogic.gdx.backends.gwt.widgets.TextInputDialogBox.TextInputDialogListener;
import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.IntSet;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray; import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.CanvasElement; import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Touch; import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyCodes;
import java.util.HashSet;
import java.util.Set;
public class GwtInput implements Input { public class GwtInput implements Input {
static final int MAX_TOUCHES = 20;
boolean justTouched = false; boolean justTouched = false;
private boolean[] touched = new boolean[20]; private IntMap<Integer> touchMap = new IntMap<Integer>(20);
private int[] touchX = new int[20]; private boolean[] touched = new boolean[MAX_TOUCHES];
private int[] touchY = new int[20]; private int[] touchX = new int[MAX_TOUCHES];
private int[] deltaX = new int[20]; private int[] touchY = new int[MAX_TOUCHES];
private int[] deltaY = new int[20]; private int[] deltaX = new int[MAX_TOUCHES];
Set<Integer> pressedButtons = new HashSet<Integer>(); private int[] deltaY = new int[MAX_TOUCHES];
Set<Integer> pressedKeys = new HashSet<Integer>(); IntSet pressedButtons = new IntSet();
int pressedKeyCount = 0;
boolean[] pressedKeys = new boolean[256];
boolean keyJustPressed = false;
boolean[] justPressedKeys = new boolean[256];
InputProcessor processor; InputProcessor processor;
char lastKeyCharPressed; char lastKeyCharPressed;
float keyRepeatTimer; float keyRepeatTimer;
@ -50,107 +52,154 @@ public class GwtInput implements Input {
final CanvasElement canvas; final CanvasElement canvas;
boolean hasFocus = true; boolean hasFocus = true;
public GwtInput(CanvasElement canvas) { public GwtInput (CanvasElement canvas) {
this.canvas = canvas; this.canvas = canvas;
hookEvents(); hookEvents();
} }
void reset () {
justTouched = false;
if (keyJustPressed) {
keyJustPressed = false;
for (int i = 0; i < justPressedKeys.length; i++) {
justPressedKeys[i] = false;
}
}
}
@Override @Override
public float getAccelerometerX() { public float getAccelerometerX () {
return 0; return 0;
} }
@Override @Override
public float getAccelerometerY() { public float getAccelerometerY () {
return 0; return 0;
} }
@Override @Override
public float getAccelerometerZ() { public float getAccelerometerZ () {
return 0; return 0;
} }
@Override @Override
public int getX() { public float getGyroscopeX () {
// TODO Auto-generated method stub
return 0;
}
@Override
public float getGyroscopeY () {
// TODO Auto-generated method stub
return 0;
}
@Override
public float getGyroscopeZ () {
// TODO Auto-generated method stub
return 0;
}
@Override
public int getX () {
return touchX[0]; return touchX[0];
} }
@Override @Override
public int getX(int pointer) { public int getX (int pointer) {
return touchX[pointer]; return touchX[pointer];
} }
@Override @Override
public int getDeltaX() { public int getDeltaX () {
return deltaX[0]; return deltaX[0];
} }
@Override @Override
public int getDeltaX(int pointer) { public int getDeltaX (int pointer) {
return deltaX[pointer]; return deltaX[pointer];
} }
@Override @Override
public int getY() { public int getY () {
return touchY[0]; return touchY[0];
} }
@Override @Override
public int getY(int pointer) { public int getY (int pointer) {
return touchY[pointer]; return touchY[pointer];
} }
@Override @Override
public int getDeltaY() { public int getDeltaY () {
return deltaY[0]; return deltaY[0];
} }
@Override @Override
public int getDeltaY(int pointer) { public int getDeltaY (int pointer) {
return deltaY[pointer]; return deltaY[pointer];
} }
@Override @Override
public boolean isTouched() { public boolean isTouched () {
return touched[0]; for (int pointer = 0; pointer < MAX_TOUCHES; pointer++) {
if (touched[pointer]) {
return true;
}
}
return false;
} }
@Override @Override
public boolean justTouched() { public boolean justTouched () {
return justTouched; return justTouched;
} }
@Override @Override
public boolean isTouched(int pointer) { public boolean isTouched (int pointer) {
return touched[pointer]; return touched[pointer];
} }
@Override @Override
public boolean isButtonPressed(int button) { public boolean isButtonPressed (int button) {
return button == Buttons.LEFT && touched[0]; return pressedButtons.contains(button) && touched[0];
} }
@Override @Override
public boolean isKeyPressed(int key) { public boolean isKeyPressed (int key) {
if (key == Keys.ANY_KEY) if (key == Keys.ANY_KEY) {
return pressedKeys.size() > 0; return pressedKeyCount > 0;
return pressedKeys.contains(key); }
if (key < 0 || key > 255) {
return false;
}
return pressedKeys[key];
} }
@Override @Override
public void getTextInput(TextInputListener listener, String title, String text) { public boolean isKeyJustPressed (int key) {
TextInputDialogBox dialog = new TextInputDialogBox(title, text, null); if (key == Keys.ANY_KEY) {
return keyJustPressed;
}
if (key < 0 || key > 255) {
return false;
}
return justPressedKeys[key];
}
public void getTextInput (TextInputListener listener, String title, String text, String hint) {
TextInputDialogBox dialog = new TextInputDialogBox(title, text, hint);
final TextInputListener capturedListener = listener; final TextInputListener capturedListener = listener;
dialog.setListener(new TextInputDialogListener() { dialog.setListener(new TextInputDialogListener() {
@Override @Override
public void onPositive(String text) { public void onPositive (String text) {
if (capturedListener != null) { if (capturedListener != null) {
capturedListener.input(text); capturedListener.input(text);
} }
} }
@Override @Override
public void onNegative() { public void onNegative () {
if (capturedListener != null) { if (capturedListener != null) {
capturedListener.canceled(); capturedListener.canceled();
} }
@ -159,208 +208,174 @@ public class GwtInput implements Input {
} }
@Override @Override
public void getPlaceholderTextInput(TextInputListener listener, String title, String placeholder) { public void setOnscreenKeyboardVisible (boolean visible) {
TextInputDialogBox dialog = new TextInputDialogBox(title, null, placeholder);
final TextInputListener capturedListener = listener;
dialog.setListener(new TextInputDialogListener() {
@Override
public void onPositive(String text) {
if (capturedListener != null) {
capturedListener.input(text);
}
}
@Override
public void onNegative() {
if (capturedListener != null) {
capturedListener.canceled();
}
}
});
} }
@Override @Override
public void setOnscreenKeyboardVisible(boolean visible) { public void vibrate (int milliseconds) {
} }
@Override @Override
public void vibrate(int milliseconds) { public void vibrate (long[] pattern, int repeat) {
} }
@Override @Override
public void vibrate(long[] pattern, int repeat) { public void cancelVibrate () {
} }
@Override @Override
public void cancelVibrate() { public float getAzimuth () {
}
@Override
public float getAzimuth() {
return 0; return 0;
} }
@Override @Override
public float getPitch() { public float getPitch () {
return 0; return 0;
} }
@Override @Override
public float getRoll() { public float getRoll () {
return 0; return 0;
} }
@Override @Override
public void getRotationMatrix(float[] matrix) { public void getRotationMatrix (float[] matrix) {
} }
@Override @Override
public long getCurrentEventTime() { public long getCurrentEventTime () {
return currentEventTimeStamp; return currentEventTimeStamp;
} }
@Override @Override
public void setCatchBackKey(boolean catchBack) { public void setCatchBackKey (boolean catchBack) {
} }
@Override @Override
public void setCatchMenuKey(boolean catchMenu) { public boolean isCatchBackKey () {
return false;
} }
@Override @Override
public void setInputProcessor(InputProcessor processor) { public void setCatchMenuKey (boolean catchMenu) {
}
@Override
public boolean isCatchMenuKey () {
return false;
}
@Override
public void setInputProcessor (InputProcessor processor) {
this.processor = processor; this.processor = processor;
} }
@Override @Override
public InputProcessor getInputProcessor() { public InputProcessor getInputProcessor () {
return processor; return processor;
} }
@Override @Override
public boolean isPeripheralAvailable(Peripheral peripheral) { public boolean isPeripheralAvailable (Peripheral peripheral) {
if (peripheral == Peripheral.Accelerometer) if (peripheral == Peripheral.Accelerometer) return false;
return false; if (peripheral == Peripheral.Compass) return false;
if (peripheral == Peripheral.Compass) if (peripheral == Peripheral.HardwareKeyboard) return true;
return false; if (peripheral == Peripheral.MultitouchScreen) return isTouchScreen();
if (peripheral == Peripheral.HardwareKeyboard) if (peripheral == Peripheral.OnscreenKeyboard) return false;
return true; if (peripheral == Peripheral.Vibrator) return false;
if (peripheral == Peripheral.MultitouchScreen)
return isTouchScreen();
if (peripheral == Peripheral.OnscreenKeyboard)
return false;
if (peripheral == Peripheral.Vibrator)
return false;
return false; return false;
} }
@Override @Override
public int getRotation() { public int getRotation () {
return 0; return 0;
} }
@Override @Override
public Orientation getNativeOrientation() { public Orientation getNativeOrientation () {
return Orientation.Landscape; return Orientation.Landscape;
} }
/** /** from https://github.com/toji/game-shim/blob/master/game-shim.js
* from https://github.com/toji/game-shim/blob/master/game-shim.js * @return is Cursor catched */
* private native boolean isCursorCatchedJSNI () /*-{
* @return is Cursor catched if (!navigator.pointer) {
*/ navigator.pointer = navigator.webkitPointer || navigator.mozPointer;
private native boolean isCursorCatchedJSNI() /*-{ }
if (!navigator.pointer) { if (navigator.pointer) {
navigator.pointer = navigator.webkitPointer || navigator.mozPointer; if (typeof (navigator.pointer.isLocked) === "boolean") {
} // Chrome initially launched with this interface
if (navigator.pointer) { return navigator.pointer.isLocked;
if (typeof (navigator.pointer.isLocked) === "boolean") { } else if (typeof (navigator.pointer.isLocked) === "function") {
// Chrome initially launched with this interface // Some older builds might provide isLocked as a function
return navigator.pointer.isLocked; return navigator.pointer.isLocked();
} else if (typeof (navigator.pointer.isLocked) === "function") { } else if (typeof (navigator.pointer.islocked) === "function") {
// Some older builds might provide isLocked as a function // For compatibility with early Firefox build
return navigator.pointer.isLocked(); return navigator.pointer.islocked();
} else if (typeof (navigator.pointer.islocked) === "function") { }
// For compatibility with early Firefox build }
return navigator.pointer.islocked(); return false;
} }-*/;
}
return false;
}-*/;
/** /** from https://github.com/toji/game-shim/blob/master/game-shim.js
* from https://github.com/toji/game-shim/blob/master/game-shim.js * @param element Canvas */
* private native void setCursorCatchedJSNI (CanvasElement element) /*-{
* @param element Canvas // Navigator pointer is not the right interface according to spec.
*/ // Here for backwards compatibility only
private native void setCursorCatchedJSNI(CanvasElement element) /*-{ if (!navigator.pointer) {
// Navigator pointer is not the right interface according to spec. navigator.pointer = navigator.webkitPointer || navigator.mozPointer;
// Here for backwards compatibility only }
if (!navigator.pointer) { // element.requestPointerLock
navigator.pointer = navigator.webkitPointer || navigator.mozPointer; if (!element.requestPointerLock) {
} element.requestPointerLock = (function() {
// element.requestPointerLock return element.webkitRequestPointerLock
if (!element.requestPointerLock) { || element.mozRequestPointerLock || function() {
element.requestPointerLock = (function() { if (navigator.pointer) {
return element.webkitRequestPointerLock navigator.pointer.lock(element);
|| element.mozRequestPointerLock || function() { }
if (navigator.pointer) { };
navigator.pointer.lock(element); })();
} }
}; element.requestPointerLock();
})(); }-*/;
}
element.requestPointerLock();
}-*/;
/** /** from https://github.com/toji/game-shim/blob/master/game-shim.js */
* from https://github.com/toji/game-shim/blob/master/game-shim.js private native void exitCursorCatchedJSNI () /*-{
*/ if (!$doc.exitPointerLock) {
private native void exitCursorCatchedJSNI() /*-{ $doc.exitPointerLock = (function() {
if (!$doc.exitPointerLock) { return $doc.webkitExitPointerLock || $doc.mozExitPointerLock
$doc.exitPointerLock = (function() { || function() {
return $doc.webkitExitPointerLock || $doc.mozExitPointerLock if (navigator.pointer) {
|| function() { var elem = this;
if (navigator.pointer) { navigator.pointer.unlock();
var elem = this; }
navigator.pointer.unlock(); };
} })();
}; }
})(); }-*/;
}
}-*/;
/** /** from https://github.com/toji/game-shim/blob/master/game-shim.js
* from https://github.com/toji/game-shim/blob/master/game-shim.js
*
* @param event JavaScript Mouse Event * @param event JavaScript Mouse Event
* @return movement in x direction * @return movement in x direction */
*/ private native float getMovementXJSNI (NativeEvent event) /*-{
private native float getMovementXJSNI(NativeEvent event) /*-{ return event.movementX || event.webkitMovementX || 0;
return event.movementX || event.webkitMovementX || 0; }-*/;
}-*/;
/** /** from https://github.com/toji/game-shim/blob/master/game-shim.js
* from https://github.com/toji/game-shim/blob/master/game-shim.js
*
* @param event JavaScript Mouse Event * @param event JavaScript Mouse Event
* @return movement in y direction * @return movement in y direction */
*/ private native float getMovementYJSNI (NativeEvent event) /*-{
private native float getMovementYJSNI(NativeEvent event) /*-{ return event.movementY || event.webkitMovementY || 0;
return event.movementY || event.webkitMovementY || 0; }-*/;
}-*/;
private static native boolean isTouchScreen() /*-{ private static native boolean isTouchScreen () /*-{
return (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0)); return (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));
}-*/; }-*/;
/** /** works only for Chrome > Version 18 with enabled Mouse Lock enable in about:flags or start Chrome with the
* works only for Chrome > Version 18 with enabled Mouse Lock enable in * --enable-pointer-lock flag */
* about:flags or start Chrome with the
* --enable-pointer-lock flag
*/
@Override @Override
public void setCursorCatched(boolean catched) { public void setCursorCatched (boolean catched) {
if (catched) if (catched)
setCursorCatchedJSNI(canvas); setCursorCatchedJSNI(canvas);
else else
@ -368,89 +383,90 @@ public class GwtInput implements Input {
} }
@Override @Override
public boolean isCursorCatched() { public boolean isCursorCatched () {
return isCursorCatchedJSNI(); return isCursorCatchedJSNI();
} }
@Override @Override
public void setCursorPosition(int x, int y) { public void setCursorPosition (int x, int y) {
// FIXME?? // FIXME??
} }
@Override
public void setCursorImage(Pixmap pixmap, int xHotspot, int yHotspot) {
}
// kindly borrowed from our dear playn friends... // kindly borrowed from our dear playn friends...
static native void addEventListener(JavaScriptObject target, String name, GwtInput handler, static native void addEventListener (JavaScriptObject target, String name, GwtInput handler, boolean capture) /*-{
boolean capture) /*-{ target
target .addEventListener(
.addEventListener( name,
name, function(e) {
function(e) { handler.@com.badlogic.gdx.backends.gwt.GwtInput::handleEvent(Lcom/google/gwt/dom/client/NativeEvent;)(e);
handler.@com.badlogic.gdx.backends.gwt.GwtInput::handleEvent(Lcom/google/gwt/dom/client/NativeEvent;)(e); }, capture);
}, capture); }-*/;
}-*/;
private static native float getMouseWheelVelocity(NativeEvent evt) /*-{ private static native float getMouseWheelVelocity (NativeEvent evt) /*-{
var delta = 0.0; var delta = 0.0;
var agentInfo = @com.badlogic.gdx.backends.gwt.GwtApplication::agentInfo()(); var agentInfo = @com.badlogic.gdx.backends.gwt.GwtApplication::agentInfo()();
if (agentInfo.isFirefox) { if (agentInfo.isFirefox) {
if (agentInfo.isMacOS) { if (agentInfo.isMacOS) {
delta = 1.0 * evt.detail; delta = 1.0 * evt.detail;
} else { } else {
delta = 1.0 * evt.detail / 3; delta = 1.0 * evt.detail / 3;
} }
} else if (agentInfo.isOpera) { } else if (agentInfo.isOpera) {
if (agentInfo.isLinux) { if (agentInfo.isLinux) {
delta = -1.0 * evt.wheelDelta / 80; delta = -1.0 * evt.wheelDelta / 80;
} else { } else {
// on mac // on mac
delta = -1.0 * evt.wheelDelta / 40; delta = -1.0 * evt.wheelDelta / 40;
} }
} else if (agentInfo.isChrome || agentInfo.isSafari) { } else if (agentInfo.isChrome || agentInfo.isSafari) {
delta = -1.0 * evt.wheelDelta / 120; delta = -1.0 * evt.wheelDelta / 120;
// handle touchpad for chrome // handle touchpad for chrome
if (Math.abs(delta) < 1) { if (Math.abs(delta) < 1) {
if (agentInfo.isWindows) { if (agentInfo.isWindows) {
delta = -1.0 * evt.wheelDelta; delta = -1.0 * evt.wheelDelta;
} else if (agentInfo.isMacOS) { } else if (agentInfo.isMacOS) {
delta = -1.0 * evt.wheelDelta / 3; delta = -1.0 * evt.wheelDelta / 3;
} }
} }
} }
return delta; return delta;
}-*/; }-*/;
/** /** Kindly borrowed from PlayN. **/
* Kindly borrowed from PlayN. protected static native String getMouseWheelEvent () /*-{
**/ if (navigator.userAgent.toLowerCase().indexOf('firefox') != -1) {
protected static native String getMouseWheelEvent() /*-{ return "DOMMouseScroll";
if (navigator.userAgent.toLowerCase().indexOf('firefox') != -1) { } else {
return "DOMMouseScroll"; return "mousewheel";
} else { }
return "mousewheel"; }-*/;
}
}-*/;
/** /** Kindly borrowed from PlayN. **/
* Kindly borrowed from PlayN. protected int getRelativeX (NativeEvent e, CanvasElement target) {
**/ float xScaleRatio = target.getWidth() * 1f / target.getClientWidth(); // Correct for canvas CSS scaling
protected static float getRelativeX(NativeEvent e, Element target) { return Math.round(xScaleRatio
return e.getClientX() - target.getAbsoluteLeft() + target.getScrollLeft() * (e.getClientX() - target.getAbsoluteLeft() + target.getScrollLeft() + target.getOwnerDocument().getScrollLeft()));
+ target.getOwnerDocument().getScrollLeft();
} }
/** /** Kindly borrowed from PlayN. **/
* Kindly borrowed from PlayN. protected int getRelativeY (NativeEvent e, CanvasElement target) {
**/ float yScaleRatio = target.getHeight() * 1f / target.getClientHeight(); // Correct for canvas CSS scaling
protected static float getRelativeY(NativeEvent e, Element target) { return Math.round(yScaleRatio
return e.getClientY() - target.getAbsoluteTop() + target.getScrollTop() * (e.getClientY() - target.getAbsoluteTop() + target.getScrollTop() + target.getOwnerDocument().getScrollTop()));
+ target.getOwnerDocument().getScrollTop();
} }
private void hookEvents() { protected int getRelativeX (Touch touch, CanvasElement target) {
float xScaleRatio = target.getWidth() * 1f / target.getClientWidth(); // Correct for canvas CSS scaling
return Math.round(xScaleRatio * touch.getRelativeX(target));
}
protected int getRelativeY (Touch touch, CanvasElement target) {
float yScaleRatio = target.getHeight() * 1f / target.getClientHeight(); // Correct for canvas CSS scaling
return Math.round(yScaleRatio * touch.getRelativeY(target));
}
private void hookEvents () {
addEventListener(canvas, "mousedown", this, true); addEventListener(canvas, "mousedown", this, true);
// addEventListener(Document.get(), "mousedown", this, true); // addEventListener(Document.get(), "mousedown", this, true);
addEventListener(canvas, "mouseup", this, true); addEventListener(canvas, "mouseup", this, true);
@ -464,6 +480,7 @@ public class GwtInput implements Input {
addEventListener(canvas, "keydown", this, false); addEventListener(canvas, "keydown", this, false);
addEventListener(canvas, "keyup", this, false); addEventListener(canvas, "keyup", this, false);
addEventListener(canvas, "keypress", this, false); addEventListener(canvas, "keypress", this, false);
addEventListener(canvas, "touchstart", this, true); addEventListener(canvas, "touchstart", this, true);
addEventListener(canvas, "touchmove", this, true); addEventListener(canvas, "touchmove", this, true);
addEventListener(canvas, "touchcancel", this, true); addEventListener(canvas, "touchcancel", this, true);
@ -471,23 +488,19 @@ public class GwtInput implements Input {
} }
private int getButton(int button) { private int getButton (int button) {
if (button == NativeEvent.BUTTON_LEFT) if (button == NativeEvent.BUTTON_LEFT) return Buttons.LEFT;
return Buttons.LEFT; if (button == NativeEvent.BUTTON_RIGHT) return Buttons.RIGHT;
if (button == NativeEvent.BUTTON_RIGHT) if (button == NativeEvent.BUTTON_MIDDLE) return Buttons.MIDDLE;
return Buttons.RIGHT;
if (button == NativeEvent.BUTTON_MIDDLE)
return Buttons.MIDDLE;
return Buttons.LEFT; return Buttons.LEFT;
} }
private void handleEvent(NativeEvent e) { private void handleEvent (NativeEvent e) {
if (e.getType().equals("mousedown")) { if (e.getType().equals("mousedown")) {
if (!e.getEventTarget().equals(canvas) || touched[0]) { if (!e.getEventTarget().equals(canvas) || touched[0]) {
float mouseX = (int) getRelativeX(e, canvas); float mouseX = getRelativeX(e, canvas);
float mouseY = (int) getRelativeY(e, canvas); float mouseY = getRelativeY(e, canvas);
if (mouseX < 0 || mouseX > Gdx.graphics.getWidth() || mouseY < 0 if (mouseX < 0 || mouseX > Gdx.graphics.getWidth() || mouseY < 0 || mouseY > Gdx.graphics.getHeight()) {
|| mouseY > Gdx.graphics.getHeight()) {
hasFocus = false; hasFocus = false;
} }
return; return;
@ -502,25 +515,24 @@ public class GwtInput implements Input {
this.touchX[0] += getMovementXJSNI(e); this.touchX[0] += getMovementXJSNI(e);
this.touchY[0] += getMovementYJSNI(e); this.touchY[0] += getMovementYJSNI(e);
} else { } else {
this.touchX[0] = (int) getRelativeX(e, canvas); this.touchX[0] = getRelativeX(e, canvas);
this.touchY[0] = (int) getRelativeY(e, canvas); this.touchY[0] = getRelativeY(e, canvas);
} }
this.currentEventTimeStamp = TimeUtils.nanoTime(); this.currentEventTimeStamp = TimeUtils.nanoTime();
if (processor != null) if (processor != null) processor.touchDown(touchX[0], touchY[0], 0, getButton(e.getButton()));
processor.touchDown(touchX[0], touchY[0], 0, getButton(e.getButton()));
} }
if (e.getType().equals("mousemove")) { if (e.getType().equals("mousemove")) {
if (isCursorCatched()) { if (isCursorCatched()) {
this.deltaX[0] = (int) getMovementXJSNI(e); this.deltaX[0] = (int)getMovementXJSNI(e);
this.deltaY[0] = (int) getMovementYJSNI(e); this.deltaY[0] = (int)getMovementYJSNI(e);
this.touchX[0] += getMovementXJSNI(e); this.touchX[0] += getMovementXJSNI(e);
this.touchY[0] += getMovementYJSNI(e); this.touchY[0] += getMovementYJSNI(e);
} else { } else {
this.deltaX[0] = (int) getRelativeX(e, canvas) - touchX[0]; this.deltaX[0] = getRelativeX(e, canvas) - touchX[0];
this.deltaY[0] = (int) getRelativeY(e, canvas) - touchY[0]; this.deltaY[0] = getRelativeY(e, canvas) - touchY[0];
this.touchX[0] = (int) getRelativeX(e, canvas); this.touchX[0] = getRelativeX(e, canvas);
this.touchY[0] = (int) getRelativeY(e, canvas); this.touchY[0] = getRelativeY(e, canvas);
} }
this.currentEventTimeStamp = TimeUtils.nanoTime(); this.currentEventTimeStamp = TimeUtils.nanoTime();
if (processor != null) { if (processor != null) {
@ -532,35 +544,33 @@ public class GwtInput implements Input {
} }
if (e.getType().equals("mouseup")) { if (e.getType().equals("mouseup")) {
if (!touched[0]) if (!touched[0]) return;
return;
this.pressedButtons.remove(getButton(e.getButton())); this.pressedButtons.remove(getButton(e.getButton()));
this.touched[0] = pressedButtons.size() > 0; this.touched[0] = pressedButtons.size > 0;
if (isCursorCatched()) { if (isCursorCatched()) {
this.deltaX[0] = (int) getMovementXJSNI(e); this.deltaX[0] = (int)getMovementXJSNI(e);
this.deltaY[0] = (int) getMovementYJSNI(e); this.deltaY[0] = (int)getMovementYJSNI(e);
this.touchX[0] += getMovementXJSNI(e); this.touchX[0] += getMovementXJSNI(e);
this.touchY[0] += getMovementYJSNI(e); this.touchY[0] += getMovementYJSNI(e);
} else { } else {
this.deltaX[0] = (int) getRelativeX(e, canvas) - touchX[0]; this.deltaX[0] = getRelativeX(e, canvas) - touchX[0];
this.deltaY[0] = (int) getRelativeY(e, canvas) - touchY[0]; this.deltaY[0] = getRelativeY(e, canvas) - touchY[0];
this.touchX[0] = (int) getRelativeX(e, canvas); this.touchX[0] = getRelativeX(e, canvas);
this.touchY[0] = (int) getRelativeY(e, canvas); this.touchY[0] = getRelativeY(e, canvas);
} }
this.currentEventTimeStamp = TimeUtils.nanoTime(); this.currentEventTimeStamp = TimeUtils.nanoTime();
this.touched[0] = false; this.touched[0] = false;
if (processor != null) if (processor != null) processor.touchUp(touchX[0], touchY[0], 0, getButton(e.getButton()));
processor.touchUp(touchX[0], touchY[0], 0, getButton(e.getButton()));
} }
if (e.getType().equals(getMouseWheelEvent())) { if (e.getType().equals(getMouseWheelEvent())) {
if (processor != null) { if (processor != null) {
processor.scrolled((int) getMouseWheelVelocity(e)); processor.scrolled((int)getMouseWheelVelocity(e));
} }
this.currentEventTimeStamp = TimeUtils.nanoTime(); this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault(); e.preventDefault();
} }
if (e.getType().equals("keydown") && hasFocus) { if (e.getType().equals("keydown") && hasFocus) {
//System.out.println("keydown"); // System.out.println("keydown");
int code = keyForCode(e.getKeyCode()); int code = keyForCode(e.getKeyCode());
if (code == 67) { if (code == 67) {
e.preventDefault(); e.preventDefault();
@ -569,23 +579,31 @@ public class GwtInput implements Input {
processor.keyTyped('\b'); processor.keyTyped('\b');
} }
} else { } else {
if (this.pressedKeys.add(code) && processor != null) { if (!pressedKeys[code]) {
processor.keyDown(code); pressedKeyCount++;
pressedKeys[code] = true;
keyJustPressed = true;
justPressedKeys[code] = true;
if (processor != null) {
processor.keyDown(code);
}
} }
} }
} }
if (e.getType().equals("keypress") && hasFocus) { if (e.getType().equals("keypress") && hasFocus) {
//System.out.println("keypress"); // System.out.println("keypress");
char c = (char) e.getCharCode(); char c = (char)e.getCharCode();
if (processor != null) if (processor != null) processor.keyTyped(c);
processor.keyTyped(c);
} }
if (e.getType().equals("keyup") && hasFocus) { if (e.getType().equals("keyup") && hasFocus) {
//System.out.println("keyup"); // System.out.println("keyup");
int code = keyForCode(e.getKeyCode()); int code = keyForCode(e.getKeyCode());
this.pressedKeys.remove(code); if (pressedKeys[code]) {
pressedKeyCount--;
pressedKeys[code] = false;
}
if (processor != null) { if (processor != null) {
processor.keyUp(code); processor.keyUp(code);
} }
@ -596,10 +614,12 @@ public class GwtInput implements Input {
JsArray<Touch> touches = e.getChangedTouches(); JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) { for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i); Touch touch = touches.get(i);
int touchId = touch.getIdentifier(); int real = touch.getIdentifier();
int touchId;
touchMap.put(real, touchId = getAvailablePointer());
touched[touchId] = true; touched[touchId] = true;
touchX[touchId] = touch.getRelativeX(canvas); touchX[touchId] = getRelativeX(touch, canvas);
touchY[touchId] = touch.getRelativeY(canvas); touchY[touchId] = getRelativeY(touch, canvas);
deltaX[touchId] = 0; deltaX[touchId] = 0;
deltaY[touchId] = 0; deltaY[touchId] = 0;
if (processor != null) { if (processor != null) {
@ -613,11 +633,12 @@ public class GwtInput implements Input {
JsArray<Touch> touches = e.getChangedTouches(); JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) { for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i); Touch touch = touches.get(i);
int touchId = touch.getIdentifier(); int real = touch.getIdentifier();
deltaX[touchId] = touch.getRelativeX(canvas) - touchX[touchId]; int touchId = touchMap.get(real);
deltaY[touchId] = touch.getRelativeY(canvas) - touchY[touchId]; deltaX[touchId] = getRelativeX(touch, canvas) - touchX[touchId];
touchX[touchId] = touch.getRelativeX(canvas); deltaY[touchId] = getRelativeY(touch, canvas) - touchY[touchId];
touchY[touchId] = touch.getRelativeY(canvas); touchX[touchId] = getRelativeX(touch, canvas);
touchY[touchId] = getRelativeY(touch, canvas);
if (processor != null) { if (processor != null) {
processor.touchDragged(touchX[touchId], touchY[touchId], touchId); processor.touchDragged(touchX[touchId], touchY[touchId], touchId);
} }
@ -629,12 +650,14 @@ public class GwtInput implements Input {
JsArray<Touch> touches = e.getChangedTouches(); JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) { for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i); Touch touch = touches.get(i);
int touchId = touch.getIdentifier(); int real = touch.getIdentifier();
int touchId = touchMap.get(real);
touchMap.remove(real);
touched[touchId] = false; touched[touchId] = false;
deltaX[touchId] = touch.getRelativeX(canvas) - touchX[touchId]; deltaX[touchId] = getRelativeX(touch, canvas) - touchX[touchId];
deltaY[touchId] = touch.getRelativeY(canvas) - touchY[touchId]; deltaY[touchId] = getRelativeY(touch, canvas) - touchY[touchId];
touchX[touchId] = touch.getRelativeX(canvas); touchX[touchId] = getRelativeX(touch, canvas);
touchY[touchId] = touch.getRelativeY(canvas); touchY[touchId] = getRelativeY(touch, canvas);
if (processor != null) { if (processor != null) {
processor.touchUp(touchX[touchId], touchY[touchId], touchId, Buttons.LEFT); processor.touchUp(touchX[touchId], touchY[touchId], touchId, Buttons.LEFT);
} }
@ -646,12 +669,14 @@ public class GwtInput implements Input {
JsArray<Touch> touches = e.getChangedTouches(); JsArray<Touch> touches = e.getChangedTouches();
for (int i = 0, j = touches.length(); i < j; i++) { for (int i = 0, j = touches.length(); i < j; i++) {
Touch touch = touches.get(i); Touch touch = touches.get(i);
int touchId = touch.getIdentifier(); int real = touch.getIdentifier();
int touchId = touchMap.get(real);
touchMap.remove(real);
touched[touchId] = false; touched[touchId] = false;
deltaX[touchId] = touch.getRelativeX(canvas) - touchX[touchId]; deltaX[touchId] = getRelativeX(touch, canvas) - touchX[touchId];
deltaY[touchId] = touch.getRelativeY(canvas) - touchY[touchId]; deltaY[touchId] = getRelativeY(touch, canvas) - touchY[touchId];
touchX[touchId] = touch.getRelativeX(canvas); touchX[touchId] = getRelativeX(touch, canvas);
touchY[touchId] = touch.getRelativeY(canvas); touchY[touchId] = getRelativeY(touch, canvas);
if (processor != null) { if (processor != null) {
processor.touchUp(touchX[touchId], touchY[touchId], touchId, Buttons.LEFT); processor.touchUp(touchX[touchId], touchY[touchId], touchId, Buttons.LEFT);
} }
@ -659,13 +684,18 @@ public class GwtInput implements Input {
this.currentEventTimeStamp = TimeUtils.nanoTime(); this.currentEventTimeStamp = TimeUtils.nanoTime();
e.preventDefault(); e.preventDefault();
} }
// if(hasFocus) e.preventDefault(); // if(hasFocus) e.preventDefault();
} }
/** private int getAvailablePointer () {
* borrowed from PlayN, thanks guys for (int i = 0; i < MAX_TOUCHES; i++) {
**/ if (!touchMap.containsValue(i, false)) return i;
private static int keyForCode(int keyCode) { }
return -1;
}
/** borrowed from PlayN, thanks guys **/
private static int keyForCode (int keyCode) {
switch (keyCode) { switch (keyCode) {
case KeyCodes.KEY_ALT: case KeyCodes.KEY_ALT:
return Keys.ALT_LEFT; return Keys.ALT_LEFT;
@ -955,15 +985,4 @@ public class GwtInput implements Input {
private static final int KEY_CLOSE_BRACKET = 221; private static final int KEY_CLOSE_BRACKET = 221;
private static final int KEY_SINGLE_QUOTE = 222; private static final int KEY_SINGLE_QUOTE = 222;
@Override
public boolean isKeyJustPressed(int key) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean isCatchBackKey() {
// TODO Auto-generated method stub
return false;
}
} }

View File

@ -1,12 +1,12 @@
/******************************************************************************* /*******************************************************************************
* Copyright 2011 See libgdx AUTHORS file. * Copyright 2011 See AUTHORS file.
* <p/> *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* <p/> *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* <p/> *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -16,6 +16,11 @@
package com.badlogic.gdx.graphics; package com.badlogic.gdx.graphics;
import java.nio.Buffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
import com.badlogic.gdx.backends.gwt.GwtFileHandle; import com.badlogic.gdx.backends.gwt.GwtFileHandle;
import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.BufferUtils; import com.badlogic.gdx.utils.BufferUtils;
@ -28,38 +33,48 @@ import com.google.gwt.canvas.dom.client.Context2d.Composite;
import com.google.gwt.dom.client.CanvasElement; import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.ImageElement; import com.google.gwt.dom.client.ImageElement;
import java.nio.Buffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.Map;
public class Pixmap implements Disposable { public class Pixmap implements Disposable {
public static Map<Integer, Pixmap> pixmaps = new HashMap<Integer, Pixmap>(); public static Map<Integer, Pixmap> pixmaps = new HashMap<Integer, Pixmap>();
static int nextId = 0; static int nextId = 0;
/** /** Different pixel formats.
* Different pixel formats.
* *
* @author mzechner * @author mzechner */
*/
public enum Format { public enum Format {
Alpha, Intensity, LuminanceAlpha, RGB565, RGBA4444, RGB888, RGBA8888; Alpha, Intensity, LuminanceAlpha, RGB565, RGBA4444, RGB888, RGBA8888;
public static int toGlFormat (Format format) {
if (format == Alpha) return GL20.GL_ALPHA;
if (format == Intensity) return GL20.GL_ALPHA;
if (format == LuminanceAlpha) return GL20.GL_LUMINANCE_ALPHA;
if (format == RGB565) return GL20.GL_RGB;
if (format == RGB888) return GL20.GL_RGB;
if (format == RGBA4444) return GL20.GL_RGBA;
if (format == RGBA8888) return GL20.GL_RGBA;
throw new GdxRuntimeException("unknown format: " + format);
}
public static int toGlType (Format format) {
if (format == Alpha) return GL20.GL_UNSIGNED_BYTE;
if (format == Intensity) return GL20.GL_UNSIGNED_BYTE;
if (format == LuminanceAlpha) return GL20.GL_UNSIGNED_BYTE;
if (format == RGB565) return GL20.GL_UNSIGNED_SHORT_5_6_5;
if (format == RGB888) return GL20.GL_UNSIGNED_BYTE;
if (format == RGBA4444) return GL20.GL_UNSIGNED_SHORT_4_4_4_4;
if (format == RGBA8888) return GL20.GL_UNSIGNED_BYTE;
throw new GdxRuntimeException("unknown format: " + format);
}
} }
/** /** Blending functions to be set with {@link Pixmap#setBlending}.
* Blending functions to be set with {@link Pixmap#setBlending}. * @author mzechner */
*
* @author mzechner
*/
public enum Blending { public enum Blending {
None, SourceOver None, SourceOver
} }
/** /** Filters to be used with {@link Pixmap#drawPixmap(Pixmap, int, int, int, int, int, int, int, int)}.
* Filters to be used with {@link Pixmap#drawPixmap(Pixmap, int, int, int, int, int, int, int, int)}.
* *
* @author mzechner * @author mzechner */
*/
public enum Filter { public enum Filter {
NearestNeighbour, BiLinear NearestNeighbour, BiLinear
} }
@ -74,128 +89,139 @@ public class Pixmap implements Disposable {
int r = 255, g = 255, b = 255; int r = 255, g = 255, b = 255;
float a; float a;
String color = make(r, g, b, a); String color = make(r, g, b, a);
static String clearColor = make(255, 255, 255, 1.0f);
static Blending blending; static Blending blending;
CanvasPixelArray pixels; CanvasPixelArray pixels;
private ImageElement imageElement;
public Pixmap (FileHandle file) {
this(((GwtFileHandle)file).preloader.images.get(file.path()));
if (imageElement == null) throw new GdxRuntimeException("Couldn't load image '" + file.path() + "', file does not exist");
}
public Context2d getContext() { public Context2d getContext() {
ensureCanvasExists();
return context; return context;
} }
public Pixmap(FileHandle file) { private static Composite getComposite () {
GwtFileHandle gwtFile = (GwtFileHandle) file; return Composite.SOURCE_OVER;
ImageElement img = gwtFile.preloader.images.get(file.path());
if (img == null)
throw new GdxRuntimeException("Couldn't load image '" + file.path() + "', file does not exist");
create(img.getWidth(), img.getHeight(), Format.RGBA8888);
context.setGlobalCompositeOperation(Composite.COPY);
context.drawImage(img, 0, 0);
context.setGlobalCompositeOperation(getComposite());
} }
private static Composite getComposite() { public Pixmap (ImageElement img) {
return blending == Blending.None ? Composite.COPY : Composite.SOURCE_OVER; this(-1, -1, img);
} }
public Pixmap(ImageElement img) { public Pixmap (int width, int height, Format format) {
create(img.getWidth(), img.getHeight(), Format.RGBA8888); this(width, height, (ImageElement)null);
context.drawImage(img, 0, 0);
} }
public Pixmap(int width, int height, Format format) { private Pixmap(int width, int height, ImageElement imageElement) {
create(width, height, format); this.imageElement = imageElement;
} this.width = imageElement != null ? imageElement.getWidth() : width;
this.height = imageElement != null ? imageElement.getHeight() : height;
private void create(int width, int height, Format format2) {
this.width = width;
this.height = height;
this.format = Format.RGBA8888;
canvas = Canvas.createIfSupported();
canvas.getCanvasElement().setWidth(width);
canvas.getCanvasElement().setHeight(height);
context = canvas.getContext2d();
context.setGlobalCompositeOperation(getComposite());
buffer = BufferUtils.newIntBuffer(1); buffer = BufferUtils.newIntBuffer(1);
id = nextId++; id = nextId++;
buffer.put(0, id); buffer.put(0, id);
pixmaps.put(id, this); pixmaps.put(id, this);
} }
public static String make(int r2, int g2, int b2, float a2) { private void create () {
canvas = Canvas.createIfSupported();
canvas.getCanvasElement().setWidth(width);
canvas.getCanvasElement().setHeight(height);
context = canvas.getContext2d();
context.setGlobalCompositeOperation(getComposite());
}
public static String make (int r2, int g2, int b2, float a2) {
return "rgba(" + r2 + "," + g2 + "," + b2 + "," + a2 + ")"; return "rgba(" + r2 + "," + g2 + "," + b2 + "," + a2 + ")";
} }
/** /** Sets the type of {@link Blending} to be used for all operations. Default is {@link Blending#SourceOver}.
* Sets the type of {@link Blending} to be used for all operations. Default is {@link Blending#SourceOver}. * @param blending the blending type */
* public static void setBlending (Blending blending) {
* @param blending the blending type
*/
public static void setBlending(Blending blending) {
Pixmap.blending = blending; Pixmap.blending = blending;
Composite composite = getComposite(); Composite composite = getComposite();
for (Pixmap pixmap : pixmaps.values()) { for (Pixmap pixmap : pixmaps.values()) {
pixmap.ensureCanvasExists();
pixmap.context.setGlobalCompositeOperation(composite); pixmap.context.setGlobalCompositeOperation(composite);
} }
} }
/** /** @return the currently set {@link Blending} */
* @return the currently set {@link Blending} public static Blending getBlending () {
*/
public static Blending getBlending() {
return blending; return blending;
} }
/** /** Sets the type of interpolation {@link Filter} to be used in conjunction with
* Sets the type of interpolation {@link Filter} to be used in conjunction with
* {@link Pixmap#drawPixmap(Pixmap, int, int, int, int, int, int, int, int)}. * {@link Pixmap#drawPixmap(Pixmap, int, int, int, int, int, int, int, int)}.
* * @param filter the filter. */
* @param filter the filter. public static void setFilter (Filter filter) {
*/
public static void setFilter(Filter filter) {
} }
public Format getFormat() { public Format getFormat () {
return format; return format;
} }
public int getGLInternalFormat() { public int getGLInternalFormat () {
return GL20.GL_RGBA; return GL20.GL_RGBA;
} }
public int getGLFormat() { public int getGLFormat () {
return GL20.GL_RGBA; return GL20.GL_RGBA;
} }
public int getGLType() { public int getGLType () {
return GL20.GL_UNSIGNED_BYTE; return GL20.GL_UNSIGNED_BYTE;
} }
public int getWidth() { public int getWidth () {
return width; return width;
} }
public int getHeight() { public int getHeight () {
return height; return height;
} }
public Buffer getPixels() { public Buffer getPixels () {
return buffer; return buffer;
} }
@Override @Override
public void dispose() { public void dispose () {
pixmaps.remove(id); pixmaps.remove(id);
} }
public CanvasElement getCanvasElement() { public CanvasElement getCanvasElement () {
ensureCanvasExists();
return canvas.getCanvasElement(); return canvas.getCanvasElement();
} }
/** private void ensureCanvasExists () {
* Sets the color for the following drawing operations if (canvas == null) {
* create();
* @param color the color, encoded as RGBA8888 if (imageElement != null) {
*/ context.setGlobalCompositeOperation(Composite.COPY);
public void setColor(int color) { context.drawImage(imageElement, 0, 0);
context.setGlobalCompositeOperation(getComposite());
}
}
}
public boolean canUseImageElement () {
return canvas == null && imageElement != null;
}
public ImageElement getImageElement () {
return imageElement;
}
/** Sets the color for the following drawing operations
* @param color the color, encoded as RGBA8888 */
public void setColor (int color) {
ensureCanvasExists();
r = (color >>> 24) & 0xff; r = (color >>> 24) & 0xff;
g = (color >>> 16) & 0xff; g = (color >>> 16) & 0xff;
b = (color >>> 8) & 0xff; b = (color >>> 8) & 0xff;
@ -205,38 +231,34 @@ public class Pixmap implements Disposable {
context.setStrokeStyle(this.color); context.setStrokeStyle(this.color);
} }
/** /** Sets the color for the following drawing operations.
* Sets the color for the following drawing operations.
* *
* @param r The red component. * @param r The red component.
* @param g The green component. * @param g The green component.
* @param b The blue component. * @param b The blue component.
* @param a The alpha component. * @param a The alpha component. */
*/ public void setColor (float r, float g, float b, float a) {
public void setColor(float r, float g, float b, float a) { ensureCanvasExists();
this.r = (int) (r * 255); this.r = (int)(r * 255);
this.g = (int) (g * 255); this.g = (int)(g * 255);
this.b = (int) (b * 255); this.b = (int)(b * 255);
this.a = a; this.a = a;
color = make(this.r, this.g, this.b, this.a); color = make(this.r, this.g, this.b, this.a);
context.setFillStyle(color); context.setFillStyle(color);
context.setStrokeStyle(this.color); context.setStrokeStyle(this.color);
} }
/** /** Sets the color for the following drawing operations.
* Sets the color for the following drawing operations. * @param color The color. */
* public void setColor (Color color) {
* @param color The color.
*/
public void setColor(Color color) {
setColor(color.r, color.g, color.b, color.a); setColor(color.r, color.g, color.b, color.a);
} }
/** /** Fills the complete bitmap with the currently set color. */
* Fills the complete bitmap with the currently set color. public void fill () {
*/ ensureCanvasExists();
public void fill() { context.clearRect(0, 0, getWidth(), getHeight());
context.fillRect(0, 0, getWidth(), getHeight()); rectangle(0, 0, getWidth(), getHeight(), DrawType.FILL);
} }
// /** // /**
@ -246,153 +268,117 @@ public class Pixmap implements Disposable {
// */ // */
// public void setStrokeWidth (int width); // public void setStrokeWidth (int width);
/** /** Draws a line between the given coordinates using the currently set color.
* Draws a line between the given coordinates using the currently set color.
* *
* @param x The x-coodinate of the first point * @param x The x-coodinate of the first point
* @param y The y-coordinate of the first point * @param y The y-coordinate of the first point
* @param x2 The x-coordinate of the first point * @param x2 The x-coordinate of the first point
* @param y2 The y-coordinate of the first point * @param y2 The y-coordinate of the first point */
*/ public void drawLine (int x, int y, int x2, int y2) {
public void drawLine(int x, int y, int x2, int y2) { line(x, y, x2, y2, DrawType.STROKE);
context.beginPath();
context.moveTo(x, y);
context.lineTo(x2, y2);
context.stroke();
context.closePath();
} }
/** /** Draws a rectangle outline starting at x, y extending by width to the right and by height downwards (y-axis points downwards)
* Draws a rectangle outline starting at x, y extending by width to the right and by height downwards (y-axis points downwards)
* using the current color. * using the current color.
* *
* @param x The x coordinate * @param x The x coordinate
* @param y The y coordinate * @param y The y coordinate
* @param width The width in pixels * @param width The width in pixels
* @param height The height in pixels * @param height The height in pixels */
*/ public void drawRectangle (int x, int y, int width, int height) {
public void drawRectangle(int x, int y, int width, int height) { rectangle(x, y, width, height, DrawType.STROKE);
context.beginPath();
context.rect(x, y, width, height);
context.stroke();
context.closePath();
} }
/** /** Draws an area form another Pixmap to this Pixmap.
* Draws an area form another Pixmap to this Pixmap.
* *
* @param pixmap The other Pixmap * @param pixmap The other Pixmap
* @param x The target x-coordinate (top left corner) * @param x The target x-coordinate (top left corner)
* @param y The target y-coordinate (top left corner) * @param y The target y-coordinate (top left corner) */
*/ public void drawPixmap (Pixmap pixmap, int x, int y) {
public void drawPixmap(Pixmap pixmap, int x, int y) { CanvasElement image = pixmap.getCanvasElement();
context.drawImage(pixmap.getCanvasElement(), x, y); image(image, 0, 0, image.getWidth(), image.getHeight(), x, y, image.getWidth(), image.getHeight());
} }
/** /** Draws an area form another Pixmap to this Pixmap.
* Draws an area form another Pixmap to this Pixmap.
* *
* @param pixmap The other Pixmap * @param pixmap The other Pixmap
* @param x The target x-coordinate (top left corner) * @param x The target x-coordinate (top left corner)
* @param y The target y-coordinate (top left corner) * @param y The target y-coordinate (top left corner)
* @param srcx The source x-coordinate (top left corner) * @param srcx The source x-coordinate (top left corner)
* @param srcy The source y-coordinate (top left corner); * @param srcy The source y-coordinate (top left corner);
* @param srcWidth The width of the area form the other Pixmap in pixels * @param srcWidth The width of the area form the other Pixmap in pixels
* @param srcHeight The height of the area form the other Pixmap in pixles * @param srcHeight The height of the area form the other Pixmap in pixles */
*/ public void drawPixmap (Pixmap pixmap, int x, int y, int srcx, int srcy, int srcWidth, int srcHeight) {
public void drawPixmap(Pixmap pixmap, int x, int y, int srcx, int srcy, int srcWidth, int srcHeight) { CanvasElement image = pixmap.getCanvasElement();
context.drawImage(pixmap.getCanvasElement(), srcx, srcy, srcWidth, srcHeight, x, y, srcWidth, srcHeight); image(image, srcx, srcy, srcWidth, srcHeight, x, y, srcWidth, srcHeight);
} }
/** /** Draws an area form another Pixmap to this Pixmap. This will automatically scale and stretch the source image to the
* Draws an area form another Pixmap to this Pixmap. This will automatically scale and stretch the source image to the
* specified target rectangle. Use {@link Pixmap#setFilter(Filter)} to specify the type of filtering to be used (nearest * specified target rectangle. Use {@link Pixmap#setFilter(Filter)} to specify the type of filtering to be used (nearest
* neighbour or bilinear). * neighbour or bilinear).
* *
* @param pixmap The other Pixmap * @param pixmap The other Pixmap
* @param srcx The source x-coordinate (top left corner) * @param srcx The source x-coordinate (top left corner)
* @param srcy The source y-coordinate (top left corner); * @param srcy The source y-coordinate (top left corner);
* @param srcWidth The width of the area form the other Pixmap in pixels * @param srcWidth The width of the area form the other Pixmap in pixels
* @param srcHeight The height of the area form the other Pixmap in pixles * @param srcHeight The height of the area form the other Pixmap in pixles
* @param dstx The target x-coordinate (top left corner) * @param dstx The target x-coordinate (top left corner)
* @param dsty The target y-coordinate (top left corner) * @param dsty The target y-coordinate (top left corner)
* @param dstWidth The target width * @param dstWidth The target width
* @param dstHeight the target height * @param dstHeight the target height */
*/ public void drawPixmap (Pixmap pixmap, int srcx, int srcy, int srcWidth, int srcHeight, int dstx, int dsty, int dstWidth,
public void drawPixmap(Pixmap pixmap, int srcx, int srcy, int srcWidth, int srcHeight, int dstx, int dsty, int dstWidth, int dstHeight) {
int dstHeight) { image(pixmap.getCanvasElement(), srcx, srcy, srcWidth, srcHeight, dstx, dsty, dstWidth, dstHeight);
context.drawImage(pixmap.getCanvasElement(), srcx, srcy, srcWidth, srcHeight, dstx, dsty, dstWidth, dstHeight);
} }
/** /** Fills a rectangle starting at x, y extending by width to the right and by height downwards (y-axis points downwards) using
* Fills a rectangle starting at x, y extending by width to the right and by height downwards (y-axis points downwards) using
* the current color. * the current color.
* *
* @param x The x coordinate * @param x The x coordinate
* @param y The y coordinate * @param y The y coordinate
* @param width The width in pixels * @param width The width in pixels
* @param height The height in pixels * @param height The height in pixels */
*/ public void fillRectangle (int x, int y, int width, int height) {
public void fillRectangle(int x, int y, int width, int height) { rectangle(x, y, width, height, DrawType.FILL);
context.fillRect(x, y, width, height);
} }
/** /** Draws a circle outline with the center at x,y and a radius using the current color and stroke width.
* Draws a circle outline with the center at x,y and a radius using the current color and stroke width.
* *
* @param x The x-coordinate of the center * @param x The x-coordinate of the center
* @param y The y-coordinate of the center * @param y The y-coordinate of the center
* @param radius The radius in pixels * @param radius The radius in pixels */
*/ public void drawCircle (int x, int y, int radius) {
public void drawCircle(int x, int y, int radius) { circle(x, y, radius, DrawType.STROKE);
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.stroke();
context.closePath();
} }
/** /** Fills a circle with the center at x,y and a radius using the current color.
* Fills a circle with the center at x,y and a radius using the current color.
* *
* @param x The x-coordinate of the center * @param x The x-coordinate of the center
* @param y The y-coordinate of the center * @param y The y-coordinate of the center
* @param radius The radius in pixels * @param radius The radius in pixels */
*/ public void fillCircle (int x, int y, int radius) {
public void fillCircle(int x, int y, int radius) { circle(x, y, radius, DrawType.FILL);
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fill();
context.closePath();
} }
/** /** Fills a triangle with vertices at x1,y1 and x2,y2 and x3,y3 using the current color.
* Fills a triangle with vertices at x1,y1 and x2,y2 and x3,y3 using the current color.
* *
* @param x1 The x-coordinate of vertex 1 * @param x1 The x-coordinate of vertex 1
* @param y1 The y-coordinate of vertex 1 * @param y1 The y-coordinate of vertex 1
* @param x2 The x-coordinate of vertex 2 * @param x2 The x-coordinate of vertex 2
* @param y2 The y-coordinate of vertex 2 * @param y2 The y-coordinate of vertex 2
* @param x3 The x-coordinate of vertex 3 * @param x3 The x-coordinate of vertex 3
* @param y3 The y-coordinate of vertex 3 * @param y3 The y-coordinate of vertex 3 */
*/ public void fillTriangle (int x1, int y1, int x2, int y2, int x3, int y3) {
public void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3) { triangle(x1, y1, x2, y2, x3, y3, DrawType.FILL);
context.beginPath();
context.moveTo(x1, y1);
context.lineTo(x2, y2);
context.lineTo(x3, y3);
context.lineTo(x1, y1);
context.fill();
context.closePath();
} }
/** /** Returns the 32-bit RGBA8888 value of the pixel at x, y. For Alpha formats the RGB components will be one.
* Returns the 32-bit RGBA8888 value of the pixel at x, y. For Alpha formats the RGB components will be one.
* *
* @param x The x-coordinate * @param x The x-coordinate
* @param y The y-coordinate * @param y The y-coordinate
* @return The pixel color in RGBA8888 format. * @return The pixel color in RGBA8888 format. */
*/ public int getPixel (int x, int y) {
public int getPixel(int x, int y) { ensureCanvasExists();
if (pixels == null) pixels = context.getImageData(0, 0, width, height).getData(); if (pixels == null) pixels = context.getImageData(0, 0, width, height).getData();
int i = x * 4 + y * width * 4; int i = x * 4 + y * width * 4;
int r = pixels.get(i + 0) & 0xff; int r = pixels.get(i + 0) & 0xff;
@ -402,26 +388,148 @@ public class Pixmap implements Disposable {
return (r << 24) | (g << 16) | (b << 8) | (a); return (r << 24) | (g << 16) | (b << 8) | (a);
} }
/** /** Draws a pixel at the given location with the current color.
* Draws a pixel at the given location with the current color. *
* @param x the x-coordinate
* @param y the y-coordinate */
public void drawPixel (int x, int y) {
rectangle(x, y, 1, 1, DrawType.FILL);
}
/** Draws a pixel at the given location with the given color.
* *
* @param x the x-coordinate * @param x the x-coordinate
* @param y the y-coordinate * @param y the y-coordinate
*/ * @param color the color in RGBA8888 format. */
public void drawPixel(int x, int y) { public void drawPixel (int x, int y, int color) {
context.fillRect(x, y, 1, 1);
}
/**
* Draws a pixel at the given location with the given color.
*
* @param x the x-coordinate
* @param y the y-coordinate
* @param color the color in RGBA8888 format.
*/
public void drawPixel(int x, int y, int color) {
setColor(color); setColor(color);
drawPixel(x, y); drawPixel(x, y);
} }
private void circle (int x, int y, int radius, DrawType drawType) {
ensureCanvasExists();
if (blending == Blending.None) {
context.setFillStyle(clearColor);
context.setStrokeStyle(clearColor);
context.setGlobalCompositeOperation("destination-out");
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
fillOrStrokePath(drawType);
context.closePath();
context.setFillStyle(color);
context.setStrokeStyle(color);
context.setGlobalCompositeOperation(Composite.SOURCE_OVER);
}
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
fillOrStrokePath(drawType);
context.closePath();
pixels = null;
}
private void line(int x, int y, int x2, int y2, DrawType drawType) {
ensureCanvasExists();
if (blending == Blending.None) {
context.setFillStyle(clearColor);
context.setStrokeStyle(clearColor);
context.setGlobalCompositeOperation("destination-out");
context.beginPath();
context.moveTo(x, y);
context.lineTo(x2, y2);
fillOrStrokePath(drawType);
context.closePath();
context.setFillStyle(color);
context.setStrokeStyle(color);
context.setGlobalCompositeOperation(Composite.SOURCE_OVER);
}
context.beginPath();
context.moveTo(x, y);
context.lineTo(x2, y2);
fillOrStrokePath(drawType);
context.closePath();
pixels = null;
}
private void rectangle(int x, int y, int width, int height, DrawType drawType) {
ensureCanvasExists();
if (blending == Blending.None) {
context.setFillStyle(clearColor);
context.setStrokeStyle(clearColor);
context.setGlobalCompositeOperation("destination-out");
context.beginPath();
context.rect(x, y, width, height);
fillOrStrokePath(drawType);
context.closePath();
context.setFillStyle(color);
context.setStrokeStyle(color);
context.setGlobalCompositeOperation(Composite.SOURCE_OVER);
}
context.beginPath();
context.rect(x, y, width, height);
fillOrStrokePath(drawType);
context.closePath();
pixels = null;
}
private void triangle(int x1, int y1, int x2, int y2, int x3, int y3, DrawType drawType) {
ensureCanvasExists();
if (blending == Blending.None) {
context.setFillStyle(clearColor);
context.setStrokeStyle(clearColor);
context.setGlobalCompositeOperation("destination-out");
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.lineTo(x3,y3);
context.lineTo(x1,y1);
fillOrStrokePath(drawType);
context.closePath();
context.setFillStyle(color);
context.setStrokeStyle(color);
context.setGlobalCompositeOperation(Composite.SOURCE_OVER);
}
context.beginPath();
context.moveTo(x1,y1);
context.lineTo(x2,y2);
context.lineTo(x3,y3);
context.lineTo(x1,y1);
fillOrStrokePath(drawType);
context.closePath();
pixels = null;
}
private void image (CanvasElement image, int srcX, int srcY, int srcWidth, int srcHeight, int dstX, int dstY, int dstWidth, int dstHeight) {
ensureCanvasExists();
if (blending == Blending.None) {
context.setFillStyle(clearColor);
context.setStrokeStyle(clearColor);
context.setGlobalCompositeOperation("destination-out");
context.beginPath();
context.rect(dstX, dstY, dstWidth, dstHeight);
fillOrStrokePath(DrawType.FILL);
context.closePath();
context.setFillStyle(color);
context.setStrokeStyle(color);
context.setGlobalCompositeOperation(Composite.SOURCE_OVER);
}
context.drawImage(image, srcX, srcY, srcWidth, srcHeight, dstX, dstY, dstWidth, dstHeight);
pixels = null;
}
private void fillOrStrokePath(DrawType drawType) {
ensureCanvasExists();
switch (drawType) {
case FILL:
context.fill();
break;
case STROKE:
context.stroke();
break;
}
}
private enum DrawType {
FILL, STROKE
}
} }

View File

@ -0,0 +1,22 @@
package java.io;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FileInputStream extends InputStream {
static final Logger log = LoggerFactory.getLogger(FileInputStream.class);
public FileInputStream(File f) {
}
public FileInputStream(String s) throws FileNotFoundException {
log.debug("FileInputStream {}", s);
}
@Override
public int read() throws IOException {
return 0;
}
}

View File

@ -0,0 +1,83 @@
/** @license
*
* SoundManager 2: JavaScript Sound for the Web
* ----------------------------------------------
* http://schillmania.com/projects/soundmanager2/
*
* Copyright (c) 2007, Scott Schiller. All rights reserved.
* Code provided under the BSD License:
* http://schillmania.com/projects/soundmanager2/license.txt
*
* V2.97a.20150601
*/
(function(h,g){function w(gb,w){function Z(b){return c.preferFlash&&A&&!c.ignoreFlash&&c.flash[b]!==g&&c.flash[b]}function r(b){return function(c){var d=this._s;return d&&d._a?b.call(this,c):null}}this.setupOptions={url:gb||null,flashVersion:8,debugMode:!0,debugFlash:!1,useConsole:!0,consoleOnly:!0,waitForWindowLoad:!1,bgColor:"#ffffff",useHighPerformance:!1,flashPollingInterval:null,html5PollingInterval:null,flashLoadTimeout:1E3,wmode:null,allowScriptAccess:"always",useFlashBlock:!1,useHTML5Audio:!0,
forceUseGlobalHTML5Audio:!1,ignoreMobileRestrictions:!1,html5Test:/^(probably|maybe)$/i,preferFlash:!1,noSWFCache:!1,idPrefix:"sound"};this.defaultOptions={autoLoad:!1,autoPlay:!1,from:null,loops:1,onid3:null,onload:null,whileloading:null,onplay:null,onpause:null,onresume:null,whileplaying:null,onposition:null,onstop:null,onfailure:null,onfinish:null,multiShot:!0,multiShotEvents:!1,position:null,pan:0,stream:!0,to:null,type:null,usePolicyFile:!1,volume:100};this.flash9Options={isMovieStar:null,usePeakData:!1,
useWaveformData:!1,useEQData:!1,onbufferchange:null,ondataerror:null};this.movieStarOptions={bufferTime:3,serverURL:null,onconnect:null,duration:null};this.audioFormats={mp3:{type:['audio/mpeg; codecs="mp3"',"audio/mpeg","audio/mp3","audio/MPA","audio/mpa-robust"],required:!0},mp4:{related:["aac","m4a","m4b"],type:['audio/mp4; codecs="mp4a.40.2"',"audio/aac","audio/x-m4a","audio/MP4A-LATM","audio/mpeg4-generic"],required:!1},ogg:{type:["audio/ogg; codecs=vorbis"],required:!1},opus:{type:["audio/ogg; codecs=opus",
"audio/opus"],required:!1},wav:{type:['audio/wav; codecs="1"',"audio/wav","audio/wave","audio/x-wav"],required:!1}};this.movieID="sm2-container";this.id=w||"sm2movie";this.debugID="soundmanager-debug";this.debugURLParam=/([#?&])debug=1/i;this.versionNumber="V2.97a.20150601";this.altURL=this.movieURL=this.version=null;this.enabled=this.swfLoaded=!1;this.oMC=null;this.sounds={};this.soundIDs=[];this.didFlashBlock=this.muted=!1;this.filePattern=null;this.filePatterns={flash8:/\.mp3(\?.*)?$/i,flash9:/\.mp3(\?.*)?$/i};
this.features={buffering:!1,peakData:!1,waveformData:!1,eqData:!1,movieStar:!1};this.sandbox={};this.html5={usingFlash:null};this.flash={};this.ignoreFlash=this.html5Only=!1;var N,c=this,Oa=null,k=null,aa,u=navigator.userAgent,Pa=h.location.href.toString(),p=document,pa,Qa,qa,m,y=[],O=!1,P=!1,l=!1,B=!1,ra=!1,Q,x,sa,ba,ta,F,H,I,Ra,ua,va,ca,J,da,G,wa,R,xa,ea,K,Sa,ya,Ta,za,Ua,S=null,Aa=null,T,Ba,L,fa,ga,q,U=!1,Ca=!1,Va,Wa,Xa,ha=0,V=null,ia,W=[],X,v=null,Ya,ja,Y,D,ka,Da,Za,t,hb=Array.prototype.slice,
z=!1,Ea,A,Fa,$a,C,la,ab=0,Ga,Ha=u.match(/(ipad|iphone|ipod)/i),Ia=u.match(/android/i),E=u.match(/msie/i),ib=u.match(/webkit/i),ma=u.match(/safari/i)&&!u.match(/chrome/i),Ja=u.match(/opera/i),na=u.match(/(mobile|pre\/|xoom)/i)||Ha||Ia,bb=!Pa.match(/usehtml5audio/i)&&!Pa.match(/sm2\-ignorebadua/i)&&ma&&!u.match(/silk/i)&&u.match(/OS X 10_6_([3-7])/i),Ka=p.hasFocus!==g?p.hasFocus():null,oa=ma&&(p.hasFocus===g||!p.hasFocus()),cb=!oa,db=/(mp3|mp4|mpa|m4a|m4b)/i,La=p.location?p.location.protocol.match(/http/i):
null,jb=La?"":"http://",eb=/^\s*audio\/(?:x-)?(?:mpeg4|aac|flv|mov|mp4||m4v|m4a|m4b|mp4v|3gp|3g2)\s*(?:$|;)/i,fb="mpeg4 aac flv mov mp4 m4v f4v m4a m4b mp4v 3gp 3g2".split(" "),kb=new RegExp("\\.("+fb.join("|")+")(\\?.*)?$","i");this.mimePattern=/^\s*audio\/(?:x-)?(?:mp(?:eg|3))\s*(?:$|;)/i;this.useAltURL=!La;var Ma;try{Ma=Audio!==g&&(Ja&&opera!==g&&10>opera.version()?new Audio(null):new Audio).canPlayType!==g}catch(lb){Ma=!1}this.hasHTML5=Ma;this.setup=function(b){var e=!c.url;b!==g&&l&&v&&c.ok();
sa(b);if(!z)if(na){if(!c.setupOptions.ignoreMobileRestrictions||c.setupOptions.forceUseGlobalHTML5Audio)W.push(J.globalHTML5),z=!0}else c.setupOptions.forceUseGlobalHTML5Audio&&(W.push(J.globalHTML5),z=!0);if(!Ga&&na)if(c.setupOptions.ignoreMobileRestrictions)W.push(J.ignoreMobile);else if(c.setupOptions.useHTML5Audio=!0,c.setupOptions.preferFlash=!1,Ha)c.ignoreFlash=!0;else if(Ia&&!u.match(/android\s2\.3/i)||!Ia)z=!0;b&&(e&&R&&b.url!==g&&c.beginDelayedInit(),R||b.url===g||"complete"!==p.readyState||
setTimeout(G,1));Ga=!0;return c};this.supported=this.ok=function(){return v?l&&!B:c.useHTML5Audio&&c.hasHTML5};this.getMovie=function(b){return aa(b)||p[b]||h[b]};this.createSound=function(b,e){function d(){a=fa(a);c.sounds[a.id]=new N(a);c.soundIDs.push(a.id);return c.sounds[a.id]}var a,f=null;if(!l||!c.ok())return!1;e!==g&&(b={id:b,url:e});a=x(b);a.url=ia(a.url);a.id===g&&(a.id=c.setupOptions.idPrefix+ab++);if(q(a.id,!0))return c.sounds[a.id];if(ja(a))f=d(),f._setup_html5(a);else{if(c.html5Only||
c.html5.usingFlash&&a.url&&a.url.match(/data\:/i))return d();8<m&&null===a.isMovieStar&&(a.isMovieStar=!!(a.serverURL||a.type&&a.type.match(eb)||a.url&&a.url.match(kb)));a=ga(a,void 0);f=d();8===m?k._createSound(a.id,a.loops||1,a.usePolicyFile):(k._createSound(a.id,a.url,a.usePeakData,a.useWaveformData,a.useEQData,a.isMovieStar,a.isMovieStar?a.bufferTime:!1,a.loops||1,a.serverURL,a.duration||null,a.autoPlay,!0,a.autoLoad,a.usePolicyFile),a.serverURL||(f.connected=!0,a.onconnect&&a.onconnect.apply(f)));
a.serverURL||!a.autoLoad&&!a.autoPlay||f.load(a)}!a.serverURL&&a.autoPlay&&f.play();return f};this.destroySound=function(b,e){if(!q(b))return!1;var d=c.sounds[b],a;d.stop();d._iO={};d.unload();for(a=0;a<c.soundIDs.length;a++)if(c.soundIDs[a]===b){c.soundIDs.splice(a,1);break}e||d.destruct(!0);delete c.sounds[b];return!0};this.load=function(b,e){return q(b)?c.sounds[b].load(e):!1};this.unload=function(b){return q(b)?c.sounds[b].unload():!1};this.onposition=this.onPosition=function(b,e,d,a){return q(b)?
c.sounds[b].onposition(e,d,a):!1};this.clearOnPosition=function(b,e,d){return q(b)?c.sounds[b].clearOnPosition(e,d):!1};this.start=this.play=function(b,e){var d=null,a=e&&!(e instanceof Object);if(!l||!c.ok())return!1;if(q(b,a))a&&(e={url:e});else{if(!a)return!1;a&&(e={url:e});e&&e.url&&(e.id=b,d=c.createSound(e).play())}null===d&&(d=c.sounds[b].play(e));return d};this.setPosition=function(b,e){return q(b)?c.sounds[b].setPosition(e):!1};this.stop=function(b){return q(b)?c.sounds[b].stop():!1};this.stopAll=
function(){for(var b in c.sounds)c.sounds.hasOwnProperty(b)&&c.sounds[b].stop()};this.pause=function(b){return q(b)?c.sounds[b].pause():!1};this.pauseAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].pause()};this.resume=function(b){return q(b)?c.sounds[b].resume():!1};this.resumeAll=function(){var b;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].resume()};this.togglePause=function(b){return q(b)?c.sounds[b].togglePause():!1};this.setPan=function(b,e){return q(b)?
c.sounds[b].setPan(e):!1};this.setVolume=function(b,e){var d,a;if(b===g||isNaN(b)||e!==g)return q(b)?c.sounds[b].setVolume(e):!1;d=0;for(a=c.soundIDs.length;d<a;d++)c.sounds[c.soundIDs[d]].setVolume(b)};this.mute=function(b){var e=0;b instanceof String&&(b=null);if(b)return q(b)?c.sounds[b].mute():!1;for(e=c.soundIDs.length-1;0<=e;e--)c.sounds[c.soundIDs[e]].mute();return c.muted=!0};this.muteAll=function(){c.mute()};this.unmute=function(b){b instanceof String&&(b=null);if(b)return q(b)?c.sounds[b].unmute():
!1;for(b=c.soundIDs.length-1;0<=b;b--)c.sounds[c.soundIDs[b]].unmute();c.muted=!1;return!0};this.unmuteAll=function(){c.unmute()};this.toggleMute=function(b){return q(b)?c.sounds[b].toggleMute():!1};this.getMemoryUse=function(){var b=0;k&&8!==m&&(b=parseInt(k._getMemoryUse(),10));return b};this.disable=function(b){var e;b===g&&(b=!1);if(B)return!1;B=!0;for(e=c.soundIDs.length-1;0<=e;e--)Ta(c.sounds[c.soundIDs[e]]);Q(b);t.remove(h,"load",H);return!0};this.canPlayMIME=function(b){var e;c.hasHTML5&&
(e=Y({type:b}));!e&&v&&(e=b&&c.ok()?!!(8<m&&b.match(eb)||b.match(c.mimePattern)):null);return e};this.canPlayURL=function(b){var e;c.hasHTML5&&(e=Y({url:b}));!e&&v&&(e=b&&c.ok()?!!b.match(c.filePattern):null);return e};this.canPlayLink=function(b){return b.type!==g&&b.type&&c.canPlayMIME(b.type)?!0:c.canPlayURL(b.href)};this.getSoundById=function(b,e){return b?c.sounds[b]:null};this.onready=function(b,c){if("function"===typeof b)c||(c=h),ta("onready",b,c),F();else throw T("needFunction","onready");
return!0};this.ontimeout=function(b,c){if("function"===typeof b)c||(c=h),ta("ontimeout",b,c),F({type:"ontimeout"});else throw T("needFunction","ontimeout");return!0};this._wD=this._writeDebug=function(b,c){return!0};this._debug=function(){};this.reboot=function(b,e){var d,a,f;for(d=c.soundIDs.length-1;0<=d;d--)c.sounds[c.soundIDs[d]].destruct();if(k)try{E&&(Aa=k.innerHTML),S=k.parentNode.removeChild(k)}catch(g){}Aa=S=v=k=null;c.enabled=R=l=U=Ca=O=P=B=z=c.swfLoaded=!1;c.soundIDs=[];c.sounds={};ab=
0;Ga=!1;if(b)y=[];else for(d in y)if(y.hasOwnProperty(d))for(a=0,f=y[d].length;a<f;a++)y[d][a].fired=!1;c.html5={usingFlash:null};c.flash={};c.html5Only=!1;c.ignoreFlash=!1;h.setTimeout(function(){e||c.beginDelayedInit()},20);return c};this.reset=function(){return c.reboot(!0,!0)};this.getMoviePercent=function(){return k&&"PercentLoaded"in k?k.PercentLoaded():null};this.beginDelayedInit=function(){ra=!0;G();setTimeout(function(){if(Ca)return!1;ea();da();return Ca=!0},20);I()};this.destruct=function(){c.disable(!0)};
N=function(b){var e,d,a=this,f,n,h,M,p,r,u=!1,l=[],v=0,y,B,w=null,A;d=e=null;this.sID=this.id=b.id;this.url=b.url;this._iO=this.instanceOptions=this.options=x(b);this.pan=this.options.pan;this.volume=this.options.volume;this.isHTML5=!1;this._a=null;A=this.url?!1:!0;this.id3={};this._debug=function(){};this.load=function(b){var e=null,d;b!==g?a._iO=x(b,a.options):(b=a.options,a._iO=b,w&&w!==a.url&&(a._iO.url=a.url,a.url=null));a._iO.url||(a._iO.url=a.url);a._iO.url=ia(a._iO.url);d=a.instanceOptions=
a._iO;if(!d.url&&!a.url)return a;if(d.url===a.url&&0!==a.readyState&&2!==a.readyState)return 3===a.readyState&&d.onload&&la(a,function(){d.onload.apply(a,[!!a.duration])}),a;a.loaded=!1;a.readyState=1;a.playState=0;a.id3={};if(ja(d))e=a._setup_html5(d),e._called_load||(a._html5_canplay=!1,a.url!==d.url&&(a._a.src=d.url,a.setPosition(0)),a._a.autobuffer="auto",a._a.preload="auto",a._a._called_load=!0);else{if(c.html5Only||a._iO.url&&a._iO.url.match(/data\:/i))return a;try{a.isHTML5=!1,a._iO=ga(fa(d)),
a._iO.autoPlay&&(a._iO.position||a._iO.from)&&(a._iO.autoPlay=!1),d=a._iO,8===m?k._load(a.id,d.url,d.stream,d.autoPlay,d.usePolicyFile):k._load(a.id,d.url,!!d.stream,!!d.autoPlay,d.loops||1,!!d.autoLoad,d.usePolicyFile)}catch(f){K({type:"SMSOUND_LOAD_JS_EXCEPTION",fatal:!0})}}a.url=d.url;return a};this.unload=function(){0!==a.readyState&&(a.isHTML5?(M(),a._a&&(a._a.pause(),w=ka(a._a))):8===m?k._unload(a.id,"about:blank"):k._unload(a.id),f());return a};this.destruct=function(b){a.isHTML5?(M(),a._a&&
(a._a.pause(),ka(a._a),z||h(),a._a._s=null,a._a=null)):(a._iO.onfailure=null,k._destroySound(a.id));b||c.destroySound(a.id,!0)};this.start=this.play=function(b,e){var d,f,n,h,Na;f=!0;f=null;e=e===g?!0:e;b||(b={});a.url&&(a._iO.url=a.url);a._iO=x(a._iO,a.options);a._iO=x(b,a._iO);a._iO.url=ia(a._iO.url);a.instanceOptions=a._iO;if(!a.isHTML5&&a._iO.serverURL&&!a.connected)return a.getAutoPlay()||a.setAutoPlay(!0),a;ja(a._iO)&&(a._setup_html5(a._iO),p());1!==a.playState||a.paused||(d=a._iO.multiShot,
d||(a.isHTML5&&a.setPosition(a._iO.position),f=a));if(null!==f)return f;b.url&&b.url!==a.url&&(a.readyState||a.isHTML5||8!==m||!A?a.load(a._iO):A=!1);a.loaded||(0===a.readyState?(a.isHTML5||c.html5Only?a.isHTML5?a.load(a._iO):f=a:(a._iO.autoPlay=!0,a.load(a._iO)),a.instanceOptions=a._iO):2===a.readyState&&(f=a));if(null!==f)return f;!a.isHTML5&&9===m&&0<a.position&&a.position===a.duration&&(b.position=0);if(a.paused&&0<=a.position&&(!a._iO.serverURL||0<a.position))a.resume();else{a._iO=x(b,a._iO);
if((!a.isHTML5&&null!==a._iO.position&&0<a._iO.position||null!==a._iO.from&&0<a._iO.from||null!==a._iO.to)&&0===a.instanceCount&&0===a.playState&&!a._iO.serverURL){d=function(){a._iO=x(b,a._iO);a.play(a._iO)};a.isHTML5&&!a._html5_canplay?(a.load({_oncanplay:d}),f=!1):a.isHTML5||a.loaded||a.readyState&&2===a.readyState||(a.load({onload:d}),f=!1);if(null!==f)return f;a._iO=B()}(!a.instanceCount||a._iO.multiShotEvents||a.isHTML5&&a._iO.multiShot&&!z||!a.isHTML5&&8<m&&!a.getAutoPlay())&&a.instanceCount++;
a._iO.onposition&&0===a.playState&&r(a);a.playState=1;a.paused=!1;a.position=a._iO.position===g||isNaN(a._iO.position)?0:a._iO.position;a.isHTML5||(a._iO=ga(fa(a._iO)));a._iO.onplay&&e&&(a._iO.onplay.apply(a),u=!0);a.setVolume(a._iO.volume,!0);a.setPan(a._iO.pan,!0);a.isHTML5?2>a.instanceCount?(p(),f=a._setup_html5(),a.setPosition(a._iO.position),f.play()):(n=new Audio(a._iO.url),h=function(){t.remove(n,"ended",h);a._onfinish(a);ka(n);n=null},Na=function(){t.remove(n,"canplay",Na);try{n.currentTime=
a._iO.position/1E3}catch(b){}n.play()},t.add(n,"ended",h),a._iO.volume!==g&&(n.volume=Math.max(0,Math.min(1,a._iO.volume/100))),a.muted&&(n.muted=!0),a._iO.position?t.add(n,"canplay",Na):n.play()):(f=k._start(a.id,a._iO.loops||1,9===m?a.position:a.position/1E3,a._iO.multiShot||!1),9!==m||f||a._iO.onplayerror&&a._iO.onplayerror.apply(a))}return a};this.stop=function(b){var c=a._iO;1===a.playState&&(a._onbufferchange(0),a._resetOnPosition(0),a.paused=!1,a.isHTML5||(a.playState=0),y(),c.to&&a.clearOnPosition(c.to),
a.isHTML5?a._a&&(b=a.position,a.setPosition(0),a.position=b,a._a.pause(),a.playState=0,a._onTimer(),M()):(k._stop(a.id,b),c.serverURL&&a.unload()),a.instanceCount=0,a._iO={},c.onstop&&c.onstop.apply(a));return a};this.setAutoPlay=function(b){a._iO.autoPlay=b;a.isHTML5||(k._setAutoPlay(a.id,b),b&&(a.instanceCount||1!==a.readyState||a.instanceCount++))};this.getAutoPlay=function(){return a._iO.autoPlay};this.setPosition=function(b){b===g&&(b=0);var c=a.isHTML5?Math.max(b,0):Math.min(a.duration||a._iO.duration,
Math.max(b,0));a.position=c;b=a.position/1E3;a._resetOnPosition(a.position);a._iO.position=c;if(!a.isHTML5)b=9===m?a.position:b,a.readyState&&2!==a.readyState&&k._setPosition(a.id,b,a.paused||!a.playState,a._iO.multiShot);else if(a._a){if(a._html5_canplay){if(a._a.currentTime!==b)try{a._a.currentTime=b,(0===a.playState||a.paused)&&a._a.pause()}catch(e){}}else if(b)return a;a.paused&&a._onTimer(!0)}return a};this.pause=function(b){if(a.paused||0===a.playState&&1!==a.readyState)return a;a.paused=!0;
a.isHTML5?(a._setup_html5().pause(),M()):(b||b===g)&&k._pause(a.id,a._iO.multiShot);a._iO.onpause&&a._iO.onpause.apply(a);return a};this.resume=function(){var b=a._iO;if(!a.paused)return a;a.paused=!1;a.playState=1;a.isHTML5?(a._setup_html5().play(),p()):(b.isMovieStar&&!b.serverURL&&a.setPosition(a.position),k._pause(a.id,b.multiShot));!u&&b.onplay?(b.onplay.apply(a),u=!0):b.onresume&&b.onresume.apply(a);return a};this.togglePause=function(){if(0===a.playState)return a.play({position:9!==m||a.isHTML5?
a.position/1E3:a.position}),a;a.paused?a.resume():a.pause();return a};this.setPan=function(b,c){b===g&&(b=0);c===g&&(c=!1);a.isHTML5||k._setPan(a.id,b);a._iO.pan=b;c||(a.pan=b,a.options.pan=b);return a};this.setVolume=function(b,e){b===g&&(b=100);e===g&&(e=!1);a.isHTML5?a._a&&(c.muted&&!a.muted&&(a.muted=!0,a._a.muted=!0),a._a.volume=Math.max(0,Math.min(1,b/100))):k._setVolume(a.id,c.muted&&!a.muted||a.muted?0:b);a._iO.volume=b;e||(a.volume=b,a.options.volume=b);return a};this.mute=function(){a.muted=
!0;a.isHTML5?a._a&&(a._a.muted=!0):k._setVolume(a.id,0);return a};this.unmute=function(){a.muted=!1;var b=a._iO.volume!==g;a.isHTML5?a._a&&(a._a.muted=!1):k._setVolume(a.id,b?a._iO.volume:a.options.volume);return a};this.toggleMute=function(){return a.muted?a.unmute():a.mute()};this.onposition=this.onPosition=function(b,c,e){l.push({position:parseInt(b,10),method:c,scope:e!==g?e:a,fired:!1});return a};this.clearOnPosition=function(a,b){var c;a=parseInt(a,10);if(isNaN(a))return!1;for(c=0;c<l.length;c++)a!==
l[c].position||b&&b!==l[c].method||(l[c].fired&&v--,l.splice(c,1))};this._processOnPosition=function(){var b,c;b=l.length;if(!b||!a.playState||v>=b)return!1;for(--b;0<=b;b--)c=l[b],!c.fired&&a.position>=c.position&&(c.fired=!0,v++,c.method.apply(c.scope,[c.position]));return!0};this._resetOnPosition=function(a){var b,c;b=l.length;if(!b)return!1;for(--b;0<=b;b--)c=l[b],c.fired&&a<=c.position&&(c.fired=!1,v--);return!0};B=function(){var b=a._iO,c=b.from,e=b.to,d,f;f=function(){a.clearOnPosition(e,f);
a.stop()};d=function(){if(null!==e&&!isNaN(e))a.onPosition(e,f)};null===c||isNaN(c)||(b.position=c,b.multiShot=!1,d());return b};r=function(){var b,c=a._iO.onposition;if(c)for(b in c)if(c.hasOwnProperty(b))a.onPosition(parseInt(b,10),c[b])};y=function(){var b,c=a._iO.onposition;if(c)for(b in c)c.hasOwnProperty(b)&&a.clearOnPosition(parseInt(b,10))};p=function(){a.isHTML5&&Va(a)};M=function(){a.isHTML5&&Wa(a)};f=function(b){b||(l=[],v=0);u=!1;a._hasTimer=null;a._a=null;a._html5_canplay=!1;a.bytesLoaded=
null;a.bytesTotal=null;a.duration=a._iO&&a._iO.duration?a._iO.duration:null;a.durationEstimate=null;a.buffered=[];a.eqData=[];a.eqData.left=[];a.eqData.right=[];a.failures=0;a.isBuffering=!1;a.instanceOptions={};a.instanceCount=0;a.loaded=!1;a.metadata={};a.readyState=0;a.muted=!1;a.paused=!1;a.peakData={left:0,right:0};a.waveformData={left:[],right:[]};a.playState=0;a.position=null;a.id3={}};f();this._onTimer=function(b){var c,f=!1,g={};if(a._hasTimer||b)return a._a&&(b||(0<a.playState||1===a.readyState)&&
!a.paused)&&(c=a._get_html5_duration(),c!==e&&(e=c,a.duration=c,f=!0),a.durationEstimate=a.duration,c=1E3*a._a.currentTime||0,c!==d&&(d=c,f=!0),(f||b)&&a._whileplaying(c,g,g,g,g)),f};this._get_html5_duration=function(){var b=a._iO;return(b=a._a&&a._a.duration?1E3*a._a.duration:b&&b.duration?b.duration:null)&&!isNaN(b)&&Infinity!==b?b:null};this._apply_loop=function(a,b){a.loop=1<b?"loop":""};this._setup_html5=function(b){b=x(a._iO,b);var c=z?Oa:a._a,e=decodeURI(b.url),d;z?e===decodeURI(Ea)&&(d=!0):
e===decodeURI(w)&&(d=!0);if(c){if(c._s)if(z)c._s&&c._s.playState&&!d&&c._s.stop();else if(!z&&e===decodeURI(w))return a._apply_loop(c,b.loops),c;d||(w&&f(!1),c.src=b.url,Ea=w=a.url=b.url,c._called_load=!1)}else b.autoLoad||b.autoPlay?(a._a=new Audio(b.url),a._a.load()):a._a=Ja&&10>opera.version()?new Audio(null):new Audio,c=a._a,c._called_load=!1,z&&(Oa=c);a.isHTML5=!0;a._a=c;c._s=a;n();a._apply_loop(c,b.loops);b.autoLoad||b.autoPlay?a.load():(c.autobuffer=!1,c.preload="auto");return c};n=function(){if(a._a._added_events)return!1;
var b;a._a._added_events=!0;for(b in C)C.hasOwnProperty(b)&&a._a&&a._a.addEventListener(b,C[b],!1);return!0};h=function(){var b;a._a._added_events=!1;for(b in C)C.hasOwnProperty(b)&&a._a&&a._a.removeEventListener(b,C[b],!1)};this._onload=function(b){var c=!!b||!a.isHTML5&&8===m&&a.duration;a.loaded=c;a.readyState=c?3:2;a._onbufferchange(0);a._iO.onload&&la(a,function(){a._iO.onload.apply(a,[c])});return!0};this._onbufferchange=function(b){if(0===a.playState||b&&a.isBuffering||!b&&!a.isBuffering)return!1;
a.isBuffering=1===b;a._iO.onbufferchange&&a._iO.onbufferchange.apply(a,[b]);return!0};this._onsuspend=function(){a._iO.onsuspend&&a._iO.onsuspend.apply(a);return!0};this._onfailure=function(b,c,e){a.failures++;if(a._iO.onfailure&&1===a.failures)a._iO.onfailure(b,c,e)};this._onwarning=function(b,c,e){if(a._iO.onwarning)a._iO.onwarning(b,c,e)};this._onfinish=function(){var b=a._iO.onfinish;a._onbufferchange(0);a._resetOnPosition(0);a.instanceCount&&(a.instanceCount--,a.instanceCount||(y(),a.playState=
0,a.paused=!1,a.instanceCount=0,a.instanceOptions={},a._iO={},M(),a.isHTML5&&(a.position=0)),(!a.instanceCount||a._iO.multiShotEvents)&&b&&la(a,function(){b.apply(a)}))};this._whileloading=function(b,c,e,d){var f=a._iO;a.bytesLoaded=b;a.bytesTotal=c;a.duration=Math.floor(e);a.bufferLength=d;a.durationEstimate=a.isHTML5||f.isMovieStar?a.duration:f.duration?a.duration>f.duration?a.duration:f.duration:parseInt(a.bytesTotal/a.bytesLoaded*a.duration,10);a.isHTML5||(a.buffered=[{start:0,end:a.duration}]);
(3!==a.readyState||a.isHTML5)&&f.whileloading&&f.whileloading.apply(a)};this._whileplaying=function(b,c,e,d,f){var n=a._iO;if(isNaN(b)||null===b)return!1;a.position=Math.max(0,b);a._processOnPosition();!a.isHTML5&&8<m&&(n.usePeakData&&c!==g&&c&&(a.peakData={left:c.leftPeak,right:c.rightPeak}),n.useWaveformData&&e!==g&&e&&(a.waveformData={left:e.split(","),right:d.split(",")}),n.useEQData&&f!==g&&f&&f.leftEQ&&(b=f.leftEQ.split(","),a.eqData=b,a.eqData.left=b,f.rightEQ!==g&&f.rightEQ&&(a.eqData.right=
f.rightEQ.split(","))));1===a.playState&&(a.isHTML5||8!==m||a.position||!a.isBuffering||a._onbufferchange(0),n.whileplaying&&n.whileplaying.apply(a));return!0};this._oncaptiondata=function(b){a.captiondata=b;a._iO.oncaptiondata&&a._iO.oncaptiondata.apply(a,[b])};this._onmetadata=function(b,c){var e={},d,f;d=0;for(f=b.length;d<f;d++)e[b[d]]=c[d];a.metadata=e;a._iO.onmetadata&&a._iO.onmetadata.call(a,a.metadata)};this._onid3=function(b,c){var e=[],d,f;d=0;for(f=b.length;d<f;d++)e[b[d]]=c[d];a.id3=x(a.id3,
e);a._iO.onid3&&a._iO.onid3.apply(a)};this._onconnect=function(b){b=1===b;if(a.connected=b)a.failures=0,q(a.id)&&(a.getAutoPlay()?a.play(g,a.getAutoPlay()):a._iO.autoLoad&&a.load()),a._iO.onconnect&&a._iO.onconnect.apply(a,[b])};this._ondataerror=function(b){0<a.playState&&a._iO.ondataerror&&a._iO.ondataerror.apply(a)}};xa=function(){return p.body||p.getElementsByTagName("div")[0]};aa=function(b){return p.getElementById(b)};x=function(b,e){var d=b||{},a,f;a=e===g?c.defaultOptions:e;for(f in a)a.hasOwnProperty(f)&&
d[f]===g&&(d[f]="object"!==typeof a[f]||null===a[f]?a[f]:x(d[f],a[f]));return d};la=function(b,c){b.isHTML5||8!==m?c():h.setTimeout(c,0)};ba={onready:1,ontimeout:1,defaultOptions:1,flash9Options:1,movieStarOptions:1};sa=function(b,e){var d,a=!0,f=e!==g,n=c.setupOptions;for(d in b)if(b.hasOwnProperty(d))if("object"!==typeof b[d]||null===b[d]||b[d]instanceof Array||b[d]instanceof RegExp)f&&ba[e]!==g?c[e][d]=b[d]:n[d]!==g?(c.setupOptions[d]=b[d],c[d]=b[d]):ba[d]===g?a=!1:c[d]instanceof Function?c[d].apply(c,
b[d]instanceof Array?b[d]:[b[d]]):c[d]=b[d];else if(ba[d]===g)a=!1;else return sa(b[d],d);return a};t=function(){function b(a){a=hb.call(a);var b=a.length;d?(a[1]="on"+a[1],3<b&&a.pop()):3===b&&a.push(!1);return a}function c(b,e){var g=b.shift(),h=[a[e]];if(d)g[h](b[0],b[1]);else g[h].apply(g,b)}var d=h.attachEvent,a={add:d?"attachEvent":"addEventListener",remove:d?"detachEvent":"removeEventListener"};return{add:function(){c(b(arguments),"add")},remove:function(){c(b(arguments),"remove")}}}();C={abort:r(function(){}),
canplay:r(function(){var b=this._s,c;if(b._html5_canplay)return!0;b._html5_canplay=!0;b._onbufferchange(0);c=b._iO.position===g||isNaN(b._iO.position)?null:b._iO.position/1E3;if(this.currentTime!==c)try{this.currentTime=c}catch(d){}b._iO._oncanplay&&b._iO._oncanplay()}),canplaythrough:r(function(){var b=this._s;b.loaded||(b._onbufferchange(0),b._whileloading(b.bytesLoaded,b.bytesTotal,b._get_html5_duration()),b._onload(!0))}),durationchange:r(function(){var b=this._s,c;c=b._get_html5_duration();isNaN(c)||
c===b.duration||(b.durationEstimate=b.duration=c)}),ended:r(function(){this._s._onfinish()}),error:r(function(){this._s._onload(!1)}),loadeddata:r(function(){var b=this._s;b._loaded||ma||(b.duration=b._get_html5_duration())}),loadedmetadata:r(function(){}),loadstart:r(function(){this._s._onbufferchange(1)}),play:r(function(){this._s._onbufferchange(0)}),playing:r(function(){this._s._onbufferchange(0)}),progress:r(function(b){var c=this._s,d,a,f=0,f=b.target.buffered;d=b.loaded||0;var g=b.total||1;
c.buffered=[];if(f&&f.length){d=0;for(a=f.length;d<a;d++)c.buffered.push({start:1E3*f.start(d),end:1E3*f.end(d)});f=1E3*(f.end(0)-f.start(0));d=Math.min(1,f/(1E3*b.target.duration))}isNaN(d)||(c._whileloading(d,g,c._get_html5_duration()),d&&g&&d===g&&C.canplaythrough.call(this,b))}),ratechange:r(function(){}),suspend:r(function(b){var c=this._s;C.progress.call(this,b);c._onsuspend()}),stalled:r(function(){}),timeupdate:r(function(){this._s._onTimer()}),waiting:r(function(){this._s._onbufferchange(1)})};
ja=function(b){return b&&(b.type||b.url||b.serverURL)?b.serverURL||b.type&&Z(b.type)?!1:b.type?Y({type:b.type}):Y({url:b.url})||c.html5Only||b.url.match(/data\:/i):!1};ka=function(b){var e;b&&(e=ma?"about:blank":c.html5.canPlayType("audio/wav")?"data:audio/wave;base64,/UklGRiYAAABXQVZFZm10IBAAAAABAAEARKwAAIhYAQACABAAZGF0YQIAAAD//w==":"about:blank",b.src=e,b._called_unload!==g&&(b._called_load=!1));z&&(Ea=null);return e};Y=function(b){if(!c.useHTML5Audio||!c.hasHTML5)return!1;var e=b.url||null;b=b.type||
null;var d=c.audioFormats,a;if(b&&c.html5[b]!==g)return c.html5[b]&&!Z(b);if(!D){D=[];for(a in d)d.hasOwnProperty(a)&&(D.push(a),d[a].related&&(D=D.concat(d[a].related)));D=new RegExp("\\.("+D.join("|")+")(\\?.*)?$","i")}(a=e?e.toLowerCase().match(D):null)&&a.length?a=a[1]:b&&(e=b.indexOf(";"),a=(-1!==e?b.substr(0,e):b).substr(6));a&&c.html5[a]!==g?e=c.html5[a]&&!Z(a):(b="audio/"+a,e=c.html5.canPlayType({type:b}),e=(c.html5[a]=e)&&c.html5[b]&&!Z(b));return e};Za=function(){function b(a){var b,d=b=
!1;if(!e||"function"!==typeof e.canPlayType)return b;if(a instanceof Array){h=0;for(b=a.length;h<b;h++)if(c.html5[a[h]]||e.canPlayType(a[h]).match(c.html5Test))d=!0,c.html5[a[h]]=!0,c.flash[a[h]]=!!a[h].match(db);b=d}else a=e&&"function"===typeof e.canPlayType?e.canPlayType(a):!1,b=!(!a||!a.match(c.html5Test));return b}if(!c.useHTML5Audio||!c.hasHTML5)return v=c.html5.usingFlash=!0,!1;var e=Audio!==g?Ja&&10>opera.version()?new Audio(null):new Audio:null,d,a,f={},n,h;n=c.audioFormats;for(d in n)if(n.hasOwnProperty(d)&&
(a="audio/"+d,f[d]=b(n[d].type),f[a]=f[d],d.match(db)?(c.flash[d]=!0,c.flash[a]=!0):(c.flash[d]=!1,c.flash[a]=!1),n[d]&&n[d].related))for(h=n[d].related.length-1;0<=h;h--)f["audio/"+n[d].related[h]]=f[d],c.html5[n[d].related[h]]=f[d],c.flash[n[d].related[h]]=f[d];f.canPlayType=e?b:null;c.html5=x(c.html5,f);c.html5.usingFlash=Ya();v=c.html5.usingFlash;return!0};J={};T=function(){};fa=function(b){8===m&&1<b.loops&&b.stream&&(b.stream=!1);return b};ga=function(b,c){b&&!b.usePolicyFile&&(b.onid3||b.usePeakData||
b.useWaveformData||b.useEQData)&&(b.usePolicyFile=!0);return b};pa=function(){return!1};Ta=function(b){for(var c in b)b.hasOwnProperty(c)&&"function"===typeof b[c]&&(b[c]=pa)};za=function(b){b===g&&(b=!1);(B||b)&&c.disable(b)};Ua=function(b){var e=null;if(b)if(b.match(/\.swf(\?.*)?$/i)){if(e=b.substr(b.toLowerCase().lastIndexOf(".swf?")+4))return b}else b.lastIndexOf("/")!==b.length-1&&(b+="/");b=(b&&-1!==b.lastIndexOf("/")?b.substr(0,b.lastIndexOf("/")+1):"./")+c.movieURL;c.noSWFCache&&(b+="?ts="+
(new Date).getTime());return b};va=function(){m=parseInt(c.flashVersion,10);8!==m&&9!==m&&(c.flashVersion=m=8);var b=c.debugMode||c.debugFlash?"_debug.swf":".swf";c.useHTML5Audio&&!c.html5Only&&c.audioFormats.mp4.required&&9>m&&(c.flashVersion=m=9);c.version=c.versionNumber+(c.html5Only?" (HTML5-only mode)":9===m?" (AS3/Flash 9)":" (AS2/Flash 8)");8<m?(c.defaultOptions=x(c.defaultOptions,c.flash9Options),c.features.buffering=!0,c.defaultOptions=x(c.defaultOptions,c.movieStarOptions),c.filePatterns.flash9=
new RegExp("\\.(mp3|"+fb.join("|")+")(\\?.*)?$","i"),c.features.movieStar=!0):c.features.movieStar=!1;c.filePattern=c.filePatterns[8!==m?"flash9":"flash8"];c.movieURL=(8===m?"soundmanager2.swf":"soundmanager2_flash9.swf").replace(".swf",b);c.features.peakData=c.features.waveformData=c.features.eqData=8<m};Sa=function(b,c){if(!k)return!1;k._setPolling(b,c)};ya=function(){};q=this.getSoundById;L=function(){var b=[];c.debugMode&&b.push("sm2_debug");c.debugFlash&&b.push("flash_debug");c.useHighPerformance&&
b.push("high_performance");return b.join(" ")};Ba=function(){T("fbHandler");var b=c.getMoviePercent(),e={type:"FLASHBLOCK"};if(c.html5Only)return!1;c.ok()?c.oMC&&(c.oMC.className=[L(),"movieContainer","swf_loaded"+(c.didFlashBlock?" swf_unblocked":"")].join(" ")):(v&&(c.oMC.className=L()+" movieContainer "+(null===b?"swf_timedout":"swf_error")),c.didFlashBlock=!0,F({type:"ontimeout",ignoreInit:!0,error:e}),K(e))};ta=function(b,c,d){y[b]===g&&(y[b]=[]);y[b].push({method:c,scope:d||null,fired:!1})};
F=function(b){b||(b={type:c.ok()?"onready":"ontimeout"});if(!l&&b&&!b.ignoreInit||"ontimeout"===b.type&&(c.ok()||B&&!b.ignoreInit))return!1;var e={success:b&&b.ignoreInit?c.ok():!B},d=b&&b.type?y[b.type]||[]:[],a=[],f,e=[e],g=v&&!c.ok();b.error&&(e[0].error=b.error);b=0;for(f=d.length;b<f;b++)!0!==d[b].fired&&a.push(d[b]);if(a.length)for(b=0,f=a.length;b<f;b++)a[b].scope?a[b].method.apply(a[b].scope,e):a[b].method.apply(this,e),g||(a[b].fired=!0);return!0};H=function(){h.setTimeout(function(){c.useFlashBlock&&
Ba();F();"function"===typeof c.onload&&c.onload.apply(h);c.waitForWindowLoad&&t.add(h,"load",H)},1)};Fa=function(){if(A!==g)return A;var b=!1,c=navigator,d=c.plugins,a,f=h.ActiveXObject;if(d&&d.length)(c=c.mimeTypes)&&c["application/x-shockwave-flash"]&&c["application/x-shockwave-flash"].enabledPlugin&&c["application/x-shockwave-flash"].enabledPlugin.description&&(b=!0);else if(f!==g&&!u.match(/MSAppHost/i)){try{a=new f("ShockwaveFlash.ShockwaveFlash")}catch(n){a=null}b=!!a}return A=b};Ya=function(){var b,
e,d=c.audioFormats;Ha&&u.match(/os (1|2|3_0|3_1)\s/i)?(c.hasHTML5=!1,c.html5Only=!0,c.oMC&&(c.oMC.style.display="none")):!c.useHTML5Audio||c.html5&&c.html5.canPlayType||(c.hasHTML5=!1);if(c.useHTML5Audio&&c.hasHTML5)for(e in X=!0,d)d.hasOwnProperty(e)&&d[e].required&&(c.html5.canPlayType(d[e].type)?c.preferFlash&&(c.flash[e]||c.flash[d[e].type])&&(b=!0):(X=!1,b=!0));c.ignoreFlash&&(b=!1,X=!0);c.html5Only=c.hasHTML5&&c.useHTML5Audio&&!b;return!c.html5Only};ia=function(b){var e,d,a=0;if(b instanceof
Array){e=0;for(d=b.length;e<d;e++)if(b[e]instanceof Object){if(c.canPlayMIME(b[e].type)){a=e;break}}else if(c.canPlayURL(b[e])){a=e;break}b[a].url&&(b[a]=b[a].url);b=b[a]}return b};Va=function(b){b._hasTimer||(b._hasTimer=!0,!na&&c.html5PollingInterval&&(null===V&&0===ha&&(V=setInterval(Xa,c.html5PollingInterval)),ha++))};Wa=function(b){b._hasTimer&&(b._hasTimer=!1,!na&&c.html5PollingInterval&&ha--)};Xa=function(){var b;if(null!==V&&!ha)return clearInterval(V),V=null,!1;for(b=c.soundIDs.length-1;0<=
b;b--)c.sounds[c.soundIDs[b]].isHTML5&&c.sounds[c.soundIDs[b]]._hasTimer&&c.sounds[c.soundIDs[b]]._onTimer()};K=function(b){b=b!==g?b:{};"function"===typeof c.onerror&&c.onerror.apply(h,[{type:b.type!==g?b.type:null}]);b.fatal!==g&&b.fatal&&c.disable()};$a=function(){if(!bb||!Fa())return!1;var b=c.audioFormats,e,d;for(d in b)if(b.hasOwnProperty(d)&&("mp3"===d||"mp4"===d)&&(c.html5[d]=!1,b[d]&&b[d].related))for(e=b[d].related.length-1;0<=e;e--)c.html5[b[d].related[e]]=!1};this._setSandboxType=function(b){};
this._externalInterfaceOK=function(b){if(c.swfLoaded)return!1;c.swfLoaded=!0;oa=!1;bb&&$a();setTimeout(qa,E?100:1)};ea=function(b,e){function d(a,b){return'<param name="'+a+'" value="'+b+'" />'}if(O&&P)return!1;if(c.html5Only)return va(),c.oMC=aa(c.movieID),qa(),P=O=!0,!1;var a=e||c.url,f=c.altURL||a,h=xa(),k=L(),m=null,m=p.getElementsByTagName("html")[0],l,r,q,m=m&&m.dir&&m.dir.match(/rtl/i);b=b===g?c.id:b;va();c.url=Ua(La?a:f);e=c.url;c.wmode=!c.wmode&&c.useHighPerformance?"transparent":c.wmode;
null!==c.wmode&&(u.match(/msie 8/i)||!E&&!c.useHighPerformance)&&navigator.platform.match(/win32|win64/i)&&(W.push(J.spcWmode),c.wmode=null);h={name:b,id:b,src:e,quality:"high",allowScriptAccess:c.allowScriptAccess,bgcolor:c.bgColor,pluginspage:jb+"www.macromedia.com/go/getflashplayer",title:"JS/Flash audio component (SoundManager 2)",type:"application/x-shockwave-flash",wmode:c.wmode,hasPriority:"true"};c.debugFlash&&(h.FlashVars="debug=1");c.wmode||delete h.wmode;if(E)a=p.createElement("div"),r=
['<object id="'+b+'" data="'+e+'" type="'+h.type+'" title="'+h.title+'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">',d("movie",e),d("AllowScriptAccess",c.allowScriptAccess),d("quality",h.quality),c.wmode?d("wmode",c.wmode):"",d("bgcolor",c.bgColor),d("hasPriority","true"),c.debugFlash?d("FlashVars",h.FlashVars):"","</object>"].join("");else for(l in a=p.createElement("embed"),h)h.hasOwnProperty(l)&&
a.setAttribute(l,h[l]);ya();k=L();if(h=xa())if(c.oMC=aa(c.movieID)||p.createElement("div"),c.oMC.id)q=c.oMC.className,c.oMC.className=(q?q+" ":"movieContainer")+(k?" "+k:""),c.oMC.appendChild(a),E&&(l=c.oMC.appendChild(p.createElement("div")),l.className="sm2-object-box",l.innerHTML=r),P=!0;else{c.oMC.id=c.movieID;c.oMC.className="movieContainer "+k;l=k=null;c.useFlashBlock||(c.useHighPerformance?k={position:"fixed",width:"8px",height:"8px",bottom:"0px",left:"0px",overflow:"hidden"}:(k={position:"absolute",
width:"6px",height:"6px",top:"-9999px",left:"-9999px"},m&&(k.left=Math.abs(parseInt(k.left,10))+"px")));ib&&(c.oMC.style.zIndex=1E4);if(!c.debugFlash)for(q in k)k.hasOwnProperty(q)&&(c.oMC.style[q]=k[q]);try{E||c.oMC.appendChild(a),h.appendChild(c.oMC),E&&(l=c.oMC.appendChild(p.createElement("div")),l.className="sm2-object-box",l.innerHTML=r),P=!0}catch(t){throw Error(T("domError")+" \n"+t.toString());}}return O=!0};da=function(){if(c.html5Only)return ea(),!1;if(k||!c.url)return!1;k=c.getMovie(c.id);
k||(S?(E?c.oMC.innerHTML=Aa:c.oMC.appendChild(S),S=null,O=!0):ea(c.id,c.url),k=c.getMovie(c.id));"function"===typeof c.oninitmovie&&setTimeout(c.oninitmovie,1);return!0};I=function(){setTimeout(Ra,1E3)};ua=function(){h.setTimeout(function(){c.setup({preferFlash:!1}).reboot();c.didFlashBlock=!0;c.beginDelayedInit()},1)};Ra=function(){var b,e=!1;if(!c.url||U)return!1;U=!0;t.remove(h,"load",I);if(A&&oa&&!Ka)return!1;l||(b=c.getMoviePercent(),0<b&&100>b&&(e=!0));setTimeout(function(){b=c.getMoviePercent();
if(e)return U=!1,h.setTimeout(I,1),!1;!l&&cb&&(null===b?c.useFlashBlock||0===c.flashLoadTimeout?c.useFlashBlock&&Ba():!c.useFlashBlock&&X?ua():F({type:"ontimeout",ignoreInit:!0,error:{type:"INIT_FLASHBLOCK"}}):0!==c.flashLoadTimeout&&(!c.useFlashBlock&&X?ua():za(!0)))},c.flashLoadTimeout)};ca=function(){if(Ka||!oa)return t.remove(h,"focus",ca),!0;Ka=cb=!0;U=!1;I();t.remove(h,"focus",ca);return!0};Q=function(b){if(l)return!1;if(c.html5Only)return l=!0,H(),!0;var e=!0,d;c.useFlashBlock&&c.flashLoadTimeout&&
!c.getMoviePercent()||(l=!0);d={type:!A&&v?"NO_FLASH":"INIT_TIMEOUT"};if(B||b)c.useFlashBlock&&c.oMC&&(c.oMC.className=L()+" "+(null===c.getMoviePercent()?"swf_timedout":"swf_error")),F({type:"ontimeout",error:d,ignoreInit:!0}),K(d),e=!1;B||(c.waitForWindowLoad&&!ra?t.add(h,"load",H):H());return e};Qa=function(){var b,e=c.setupOptions;for(b in e)e.hasOwnProperty(b)&&(c[b]===g?c[b]=e[b]:c[b]!==e[b]&&(c.setupOptions[b]=c[b]))};qa=function(){if(l)return!1;if(c.html5Only)return l||(t.remove(h,"load",
c.beginDelayedInit),c.enabled=!0,Q()),!0;da();try{k._externalInterfaceTest(!1),Sa(!0,c.flashPollingInterval||(c.useHighPerformance?10:50)),c.debugMode||k._disableDebug(),c.enabled=!0,c.html5Only||t.add(h,"unload",pa)}catch(b){return K({type:"JS_TO_FLASH_EXCEPTION",fatal:!0}),za(!0),Q(),!1}Q();t.remove(h,"load",c.beginDelayedInit);return!0};G=function(){if(R)return!1;R=!0;Qa();ya();!A&&c.hasHTML5&&c.setup({useHTML5Audio:!0,preferFlash:!1});Za();!A&&v&&(W.push(J.needFlash),c.setup({flashLoadTimeout:1}));
p.removeEventListener&&p.removeEventListener("DOMContentLoaded",G,!1);da();return!0};Da=function(){"complete"===p.readyState&&(G(),p.detachEvent("onreadystatechange",Da));return!0};wa=function(){ra=!0;G();t.remove(h,"load",wa)};Fa();t.add(h,"focus",ca);t.add(h,"load",I);t.add(h,"load",wa);p.addEventListener?p.addEventListener("DOMContentLoaded",G,!1):p.attachEvent?p.attachEvent("onreadystatechange",Da):K({type:"NO_DOM2_EVENTS",fatal:!0})}if(!h||!h.document)throw Error("SoundManager requires a browser with window and document objects.");
var N=null;h.SM2_DEFER!==g&&SM2_DEFER||(N=new w);"object"===typeof module&&module&&"object"===typeof module.exports?(module.exports.SoundManager=w,module.exports.soundManager=N):"function"===typeof define&&define.amd&&define(function(){return{constructor:w,getInstance:function(g){!h.soundManager&&g instanceof Function&&(g=g(w),g instanceof w&&(h.soundManager=g));return h.soundManager}}});h.SoundManager=w;h.soundManager=N})(window);