com.badlogic.gdx.backends.iosrobovm.IOSApplication Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.backends.iosrobovm;
import java.io.File;
import org.robovm.apple.coregraphics.CGSize;
import org.robovm.apple.foundation.NSDictionary;
import org.robovm.apple.foundation.NSMutableDictionary;
import org.robovm.apple.foundation.NSObject;
import org.robovm.apple.foundation.NSString;
import org.robovm.apple.uikit.UIApplication;
import org.robovm.apple.uikit.UIApplicationDelegateAdapter;
import org.robovm.apple.uikit.UIDevice;
import org.robovm.apple.uikit.UIInterfaceOrientation;
import org.robovm.apple.uikit.UIScreen;
import org.robovm.apple.uikit.UIUserInterfaceIdiom;
import org.robovm.apple.uikit.UIViewController;
import org.robovm.apple.uikit.UIWindow;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Audio;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Graphics;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.LifecycleListener;
import com.badlogic.gdx.Net;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Clipboard;
public class IOSApplication implements Application {
public static abstract class Delegate extends UIApplicationDelegateAdapter {
private IOSApplication app;
protected abstract IOSApplication createApplication();
@Override
public boolean didFinishLaunching (UIApplication application, NSDictionary launchOptions) {
application.addStrongRef(this); // Prevent this from being GCed until the ObjC UIApplication is deallocated
this.app = createApplication();
return app.didFinishLaunching(application, launchOptions);
}
@Override
public void didBecomeActive (UIApplication application) {
app.didBecomeActive(application);
}
@Override
public void willResignActive (UIApplication application) {
app.willResignActive(application);
}
@Override
public void willTerminate (UIApplication application) {
app.willTerminate(application);
}
}
UIApplication uiApp;
UIWindow uiWindow;
ApplicationListener listener;
IOSApplicationConfiguration config;
IOSGraphics graphics;
IOSAudio audio;
IOSFiles files;
IOSInput input;
IOSNet net;
int logLevel = Application.LOG_DEBUG;
/** The display scale factor (1.0f for normal; 2.0f to use retina coordinates/dimensions). */
float displayScaleFactor;
Array runnables = new Array();
Array executedRunnables = new Array();
Array lifecycleListeners = new Array();
public IOSApplication (ApplicationListener listener, IOSApplicationConfiguration config) {
this.listener = listener;
this.config = config;
}
final boolean didFinishLaunching (UIApplication uiApp, NSDictionary, ?> options) {
Gdx.app = this;
this.uiApp = uiApp;
// enable or disable screen dimming
UIApplication.getSharedApplication().setIdleTimerDisabled(config.preventScreenDimming);
// fix the scale factor if we have a retina device (NOTE: iOS screen sizes are in "points" not pixels by default!)
if (UIScreen.getMainScreen().getScale() == 2.0f) {
// we have a retina device!
if (UIDevice.getCurrentDevice().getUserInterfaceIdiom() == UIUserInterfaceIdiom.Pad) {
// it's an iPad!
displayScaleFactor = config.displayScaleLargeScreenIfRetina * 2.0f;
} else {
// it's an iPod or iPhone
displayScaleFactor = config.displayScaleSmallScreenIfRetina * 2.0f;
}
}
else {
// no retina screen: no scaling!
if (UIDevice.getCurrentDevice().getUserInterfaceIdiom() == UIUserInterfaceIdiom.Pad) {
// it's an iPad!
displayScaleFactor = config.displayScaleLargeScreenIfNonRetina;
} else {
// it's an iPod or iPhone
displayScaleFactor = config.displayScaleSmallScreenIfNonRetina;
}
}
GL20 gl20 = new IOSGLES20();
Gdx.gl = gl20;
Gdx.gl20 = gl20;
// setup libgdx
this.input = new IOSInput(this);
this.graphics = new IOSGraphics(getBounds(null), this, config, input, gl20);
this.files = new IOSFiles();
this.audio = new IOSAudio(config);
this.net = new IOSNet(this);
Gdx.files = this.files;
Gdx.graphics = this.graphics;
Gdx.audio = this.audio;
Gdx.input = this.input;
Gdx.net = this.net;
this.input.setupPeripherals();
this.uiWindow = new UIWindow(UIScreen.getMainScreen().getBounds());
this.uiWindow.setRootViewController(this.graphics.viewController);
this.uiWindow.makeKeyAndVisible();
Gdx.app.debug("IOSApplication", "created");
return true;
}
/**
* Return the UI view controller of IOSApplication
* @return the view controller of IOSApplication
*/
public UIViewController getUIViewController(){
return graphics.viewController;
}
/**
* Return the UI Window of IOSApplication
* @return the window
*/
public UIWindow getUIWindow() {
return uiWindow;
}
/** Returns our real display dimension based on screen orientation.
*
* @param viewController The view controller.
* @return Or real display dimension. */
CGSize getBounds (UIViewController viewController) {
// or screen size (always portrait)
// CGSize bounds = UIScreen.getMainScreen().getBounds().size();
CGSize bounds = UIScreen.getMainScreen().getApplicationFrame().size();
// determine orientation and resulting width + height
UIInterfaceOrientation orientation;
if (viewController != null) {
orientation = viewController.getInterfaceOrientation();
} else if (config.orientationLandscape == config.orientationPortrait) {
/*
* if the app has orientation in any side then we can only check
* status bar orientation
*/
orientation = uiApp.getStatusBarOrientation();
} else if (config.orientationLandscape) {// is landscape true and portrait false
orientation = UIInterfaceOrientation.LandscapeRight;
} else {// is portrait true and landscape false
orientation = UIInterfaceOrientation.Portrait;
}
int width;
int height;
switch (orientation) {
case LandscapeLeft:
case LandscapeRight:
height = (int)bounds.width();
width = (int)bounds.height();
break;
default:
// assume portrait
width = (int)bounds.width();
height = (int)bounds.height();
}
// update width/height depending on display scaling selected
width *= displayScaleFactor;
height *= displayScaleFactor;
// log screen dimensions
Gdx.app.debug("IOSApplication", "View: " + orientation.toString() + " " + width + "x" + height);
// return resulting view size (based on orientation)
return new CGSize(width, height);
}
final void didBecomeActive (UIApplication uiApp) {
Gdx.app.debug("IOSApplication", "resumed");
// workaround for ObjectAL crash problem
// see: https://groups.google.com/forum/?fromgroups=#!topic/objectal-for-iphone/ubRWltp_i1Q
// OALAudioSession.sharedInstance().forceEndInterrupt();
graphics.makeCurrent();
graphics.resume();
}
final void willResignActive (UIApplication uiApp) {
Gdx.app.debug("IOSApplication", "paused");
graphics.makeCurrent();
graphics.pause();
Gdx.gl.glFlush();
}
final void willTerminate (UIApplication uiApp) {
Gdx.app.debug("IOSApplication", "disposed");
graphics.makeCurrent();
Array listeners = lifecycleListeners;
synchronized(listeners) {
for(LifecycleListener listener: listeners) {
listener.pause();
}
}
listener.dispose();
Gdx.gl.glFlush();
}
@Override
public ApplicationListener getApplicationListener () {
return listener;
}
@Override
public Graphics getGraphics () {
return graphics;
}
@Override
public Audio getAudio () {
return audio;
}
@Override
public Input getInput () {
return input;
}
@Override
public Files getFiles () {
return files;
}
@Override
public Net getNet () {
return net;
}
@Override
public void log (String tag, String message) {
if (logLevel > LOG_NONE) {
System.out.println("[info] " + tag + ": " + message);
}
}
@Override
public void log (String tag, String message, Throwable exception) {
if (logLevel > LOG_NONE) {
System.out.println("[info] " + tag + ": " + message);
exception.printStackTrace();
}
}
@Override
public void error (String tag, String message) {
if (logLevel >= LOG_ERROR) {
System.out.println("[error] " + tag + ": " + message);
}
}
@Override
public void error (String tag, String message, Throwable exception) {
if (logLevel >= LOG_ERROR) {
System.out.println("[error] " + tag + ": " + message);
exception.printStackTrace();
}
}
@Override
public void debug (String tag, String message) {
if (logLevel >= LOG_DEBUG) {
System.out.println("[debug] " + tag + ": " + message);
}
}
@Override
public void debug (String tag, String message, Throwable exception) {
if (logLevel >= LOG_DEBUG) {
System.out.println("[error] " + tag + ": " + message);
exception.printStackTrace();
}
}
@Override
public void setLogLevel (int logLevel) {
this.logLevel = logLevel;
}
@Override
public int getLogLevel() {
return logLevel;
}
@Override
public ApplicationType getType () {
return ApplicationType.iOS;
}
@Override
public int getVersion () {
return Integer.parseInt(UIDevice.getCurrentDevice().getSystemVersion().split("\\.")[0]);
}
@Override
public long getJavaHeap () {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
@Override
public long getNativeHeap () {
return getJavaHeap();
}
@Override
public Preferences getPreferences (String name) {
File libraryPath = new File(System.getenv("HOME"), "Library");
File finalPath = new File(libraryPath, name + ".plist");
Gdx.app.debug("IOSApplication", "Loading NSDictionary from file " + finalPath);
@SuppressWarnings("unchecked")
NSMutableDictionary nsDictionary =
(NSMutableDictionary) NSMutableDictionary.read(finalPath);
// if it fails to get an existing dictionary, create a new one.
if (nsDictionary == null) {
Gdx.app.debug("IOSApplication", "NSDictionary not found, creating a new one");
nsDictionary = new NSMutableDictionary();
boolean fileWritten = nsDictionary.write(finalPath, false);
if (fileWritten)
Gdx.app.debug("IOSApplication", "NSDictionary file written");
else
Gdx.app.debug("IOSApplication", "Failed to write NSDictionary to file " + finalPath);
}
return new IOSPreferences(nsDictionary, finalPath.getAbsolutePath());
}
@Override
public void postRunnable (Runnable runnable) {
synchronized (runnables) {
runnables.add(runnable);
}
}
public void processRunnables () {
synchronized (runnables) {
executedRunnables.clear();
executedRunnables.addAll(runnables);
runnables.clear();
}
for (int i = 0; i < executedRunnables.size; i++) {
try {
executedRunnables.get(i).run();
} catch (Throwable t) {
t.printStackTrace();
}
}
}
@Override
public void exit () {
System.exit(0);
}
@Override
public Clipboard getClipboard () {
// FIXME implement clipboard
return new Clipboard() {
@Override
public void setContents (String content) {
}
@Override
public String getContents () {
return null;
}
};
}
@Override
public void addLifecycleListener (LifecycleListener listener) {
synchronized(lifecycleListeners) {
lifecycleListeners.add(listener);
}
}
@Override
public void removeLifecycleListener (LifecycleListener listener) {
synchronized(lifecycleListeners) {
lifecycleListeners.removeValue(listener, true);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy