jogamp.newt.driver.android.NewtBaseActivity Maven / Gradle / Ivy
/**
* Copyright 2011 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of JogAmp Community.
*/
package jogamp.newt.driver.android;
import java.util.ArrayList;
import java.util.List;
import javax.media.nativewindow.CapabilitiesImmutable;
import javax.media.opengl.FPSCounter;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import com.jogamp.newt.Window;
import com.jogamp.opengl.GLEventListenerState;
import com.jogamp.opengl.GLStateKeeper;
import jogamp.newt.driver.android.WindowDriver;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
public class NewtBaseActivity extends Activity {
List newtWindows = new ArrayList();
List glAutoDrawables = new ArrayList();
GLAnimatorControl animator = null;
boolean isDelegatedActivity;
Activity rootActivity;
boolean setThemeCalled = false;
protected void startAnimation(boolean start) {
if(null != animator) {
final boolean res;
if( start ) {
if( animator.isPaused() ) {
res = animator.resume();
} else {
res = animator.start();
}
} else {
res = animator.stop();
}
Log.d(MD.TAG, "Animator global: start "+start+", result "+res);
}
for(int i=0; i
* This methods issues {@link android.view.Window#setContentView(android.view.View, android.view.ViewGroup.LayoutParams) androidWindow.setContenView(newtWindow.getAndroidView())}
* and finally calls {@link #registerNEWTWindow(Window)}.
*
* @param androidWindow
* @param newtWindow
* @throws IllegalArgumentException if the newtWindow
's {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
* @see #registerNEWTWindow(Window)
* @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
*/
public void setContentView(final android.view.Window androidWindow, final Window newtWindow) throws IllegalArgumentException {
final Window delegateWindow = newtWindow.getDelegatedWindow();
if(delegateWindow instanceof WindowDriver) {
adaptTheme4Transparency(delegateWindow.getRequestedCapabilities());
layoutForNEWTWindow(androidWindow, delegateWindow);
final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
androidWindow.setContentView(newtAWindow.getAndroidView());
} else {
throw new IllegalArgumentException("Given NEWT Window is not an Android Window: "+newtWindow.getClass().getName());
}
registerNEWTWindow(newtWindow);
}
/**
* This is one of the three registration methods (see below).
*
* This methods issues {@link android.view.Window#addContentView(android.view.View, android.view.ViewGroup.LayoutParams) androidWindow.addContenView(newtWindow.getAndroidView(), params)}
* and finally calls {@link #registerNEWTWindow(Window)}.
*
* @param androidWindow
* @param newtWindow
* @param params
* @throws IllegalArgumentException if the newtWindow
's {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
* @see #registerNEWTWindow(Window)
* @see #setContentView(android.view.Window, Window)
*/
public void addContentView(final android.view.Window androidWindow, final Window newtWindow, final android.view.ViewGroup.LayoutParams params) throws IllegalArgumentException {
final Window delegateWindow = newtWindow.getDelegatedWindow();
if(delegateWindow instanceof WindowDriver) {
final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
androidWindow.addContentView(newtAWindow.getAndroidView(), params);
} else {
throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName());
}
registerNEWTWindow(newtWindow);
}
/**
* This is one of the three registration methods (see below).
*
* This methods registers the given NEWT window to ensure it's destruction at {@link #onDestroy()}.
*
*
* If adding a {@link GLAutoDrawable} implementation, the {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()}
* will be used for {@link #onPause()} and {@link #onResume()}.
*
*
* If adding a {@link GLAutoDrawable} implementation, the {@link GLEventListenerState} will preserve it's state
* when {@link #onPause()} is being called while not {@link #isFinishing()}. A later {@link #onResume()} will
* reinstate the {@link GLEventListenerState}.
*
*
* @param newtWindow
* @throws IllegalArgumentException if the newtWindow
's {@link Window#getDelegatedWindow() delegate} is not an AndroidDriver.
* @see #setContentView(android.view.Window, Window)
* @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
*/
public void registerNEWTWindow(final Window newtWindow) throws IllegalArgumentException {
final Window delegateWindow = newtWindow.getDelegatedWindow();
Log.d(MD.TAG, "registerNEWTWindow: Type "+newtWindow.getClass().getName()+", delegate "+delegateWindow.getClass().getName());
if(delegateWindow instanceof WindowDriver) {
final WindowDriver newtAWindow = (WindowDriver)delegateWindow;
newtAWindow.registerActivity(getActivity());
} else {
throw new IllegalArgumentException("Given NEWT Window's Delegate is not an Android Window: "+delegateWindow.getClass().getName());
}
newtWindows.add(newtWindow);
if(newtWindow instanceof GLAutoDrawable) {
glAutoDrawables.add((GLAutoDrawable)newtWindow);
}
if(newtWindow instanceof GLStateKeeper) {
((GLStateKeeper)newtWindow).setGLStateKeeperListener(glStateKeeperListener);
}
}
private final GLStateKeeper.Listener glStateKeeperListener = new GLStateKeeper.Listener() {
@Override
public void glStatePreserveNotify(GLStateKeeper glsk) {
Log.d(MD.TAG, "GLStateKeeper Preserving: 0x"+Integer.toHexString(glsk.hashCode()));
}
@Override
public void glStateRestored(GLStateKeeper glsk) {
Log.d(MD.TAG, "GLStateKeeper Restored: 0x"+Integer.toHexString(glsk.hashCode()));
startAnimation(true);
}
};
/**
* Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window.
*
* Must be called before creating the view and adding any content, i.e. setContentView() !
*
* @param androidWindow
* @param newtWindow
*/
public void layoutForNEWTWindow(android.view.Window androidWindow, Window newtWindow) {
if(null == androidWindow || null == newtWindow) {
throw new IllegalArgumentException("Android or NEWT Window null");
}
if( newtWindow.isFullscreen() || newtWindow.isUndecorated() ) {
androidWindow.requestFeature(android.view.Window.FEATURE_NO_TITLE);
}
if( newtWindow.isFullscreen() ) {
androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} else {
androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
if(newtWindow.getWidth()>0 && newtWindow.getHeight()>0 && !newtWindow.isFullscreen()) {
androidWindow.setLayout(newtWindow.getWidth(), newtWindow.getHeight());
}
}
/**
* Convenient method to set the Android window's flags to fullscreen or size-layout depending on the given NEWT window.
*
* Must be called before creating the view and adding any content, i.e. setContentView() !
*
* @param androidWindow
* @param newtWindow
*/
public void setFullscreenFeature(android.view.Window androidWindow, boolean fullscreen) {
if(null == androidWindow) {
throw new IllegalArgumentException("Android or Window null");
}
if( fullscreen ) {
androidWindow.requestFeature(android.view.Window.FEATURE_NO_TITLE);
androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
} else {
androidWindow.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
androidWindow.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}
/**
* Convenient method to set this context's theme to transparency depending on {@link CapabilitiesImmutable#isBackgroundOpaque()}.
*
* Must be called before creating the view and adding any content, i.e. setContentView() !
*
*/
protected void adaptTheme4Transparency(CapabilitiesImmutable caps) {
if(!caps.isBackgroundOpaque()) {
setTransparencyTheme();
}
}
/**
* Convenient method to set this context's theme to transparency.
*
* Must be called before creating the view and adding any content, i.e. setContentView() !
*
*
* Is normally issued by {@link #setContentView(android.view.Window, Window)}
* if the requested NEWT Capabilities ask for transparency.
*
*
* Can be called only once.
*
*/
public void setTransparencyTheme() {
if(!setThemeCalled) {
setThemeCalled = true;
final Context ctx = getActivity().getApplicationContext();
final String frn = ctx.getPackageName()+":style/Theme.Transparent";
final int resID = ctx.getResources().getIdentifier("Theme.Transparent", "style", ctx.getPackageName());
if(0 == resID) {
Log.d(MD.TAG, "SetTransparencyTheme: Resource n/a: "+frn);
} else {
Log.d(MD.TAG, "SetTransparencyTheme: Setting style: "+frn+": 0x"+Integer.toHexString(resID));
ctx.setTheme(resID);
}
}
}
/**
* Setting up a global {@Link GLAnimatorControl} for {@link #onPause()} and {@link #onResume()}.
*
* Note that if adding a {@link GLAutoDrawable} implementation via {@link #registerNEWTWindow(Window)},
* {@link #setContentView(android.view.Window, Window)} or {@link #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)}
* their {@link GLAnimatorControl} retrieved by {@link GLAutoDrawable#getAnimator()} will be used as well.
* In this case, using this global {@Link GLAnimatorControl} is redundant.
*
* @see #registerNEWTWindow(Window)
* @see #setContentView(android.view.Window, Window)
* @see #addContentView(android.view.Window, Window, android.view.ViewGroup.LayoutParams)
*/
public void setAnimator(GLAnimatorControl animator) {
this.animator = animator;
if(!animator.isStarted()) {
animator.start();
}
animator.pause();
}
@Override
public android.view.Window getWindow() {
if( isDelegatedActivity() ) {
return getActivity().getWindow();
} else {
return super.getWindow();
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
Log.d(MD.TAG, "onCreate.0");
if(!isDelegatedActivity()) {
super.onCreate(savedInstanceState);
}
// Extraordinary cleanup, for cases of 'onCreate()' calls w/ valid states,
// i.e. w/o having onDestroy() being called.
// Could happened due to spec when App process is killed for memory exhaustion or other reasons.
cleanup();
jogamp.common.os.android.StaticContext.init(rootActivity.getApplicationContext());
Log.d(MD.TAG, "onCreate.X");
}
@Override
public void onStart() {
Log.d(MD.TAG, "onStart.0");
if(!isDelegatedActivity()) {
super.onStart();
}
Log.d(MD.TAG, "onStart.X");
}
@Override
public void onRestart() {
Log.d(MD.TAG, "onRestart.0");
if(!isDelegatedActivity()) {
super.onRestart();
}
Log.d(MD.TAG, "onRestart.X");
}
@Override
public void onResume() {
Log.d(MD.TAG, "onResume.0");
if(!isDelegatedActivity()) {
super.onResume();
}
for(int i=0; i
* Cleaning and destroying up all preserved GLEventListenerState
* and clearing the preserve-flag of all GLStateKeeper.
*
*
* Destroying all GLWindow.
*
*/
private void cleanup() {
Log.d(MD.TAG, "cleanup.0");
int glelsKilled = 0, glelsClean = 0;
for(int i=0; i