package org.andengine.extension.ui.livewallpaper; import org.andengine.audio.music.MusicManager; import org.andengine.audio.sound.SoundManager; import org.andengine.engine.options.EngineOptions; import org.andengine.entity.scene.Scene; import org.andengine.extension.opengl.GLWallpaperService; import org.andengine.input.sensor.acceleration.IAccelerationListener; import org.andengine.input.sensor.orientation.IOrientationListener; import org.andengine.opengl.font.FontManager; import org.andengine.opengl.shader.ShaderProgramManager; import org.andengine.opengl.texture.TextureManager; import org.andengine.opengl.util.GLState; import org.andengine.opengl.vbo.VertexBufferObjectManager; import org.andengine.opengl.view.ConfigChooser; import org.andengine.opengl.view.EngineRenderer; import org.andengine.opengl.view.IRendererListener; import org.andengine.ui.IGameInterface; import org.andengine.util.debug.Debug; import android.app.WallpaperManager; import android.os.Bundle; import android.os.SystemClock; import android.view.MotionEvent; /** * (c) Nicolas Gramlich 2010 * (c) Zynga 2011 * * @author Nicolas Gramlich <ngramlich@zynga.com> * @since 7:32:25 PM - Nov 3, 2011 */ public abstract class BaseLiveWallpaperService extends GLWallpaperService implements IGameInterface, IRendererListener { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== protected EngineOptions mEngineOptions; protected org.andengine.engine.Engine mEngine; private boolean mGamePaused; private boolean mGameCreated; private boolean mCreateGameCalled; private boolean mOnReloadResourcesScheduled; // =========================================================== // Constructors // =========================================================== @Override public void onCreate() { Debug.d(this.getClass().getSimpleName() + ".onCreate" + " @(Thread: '" + Thread.currentThread().getName() + "')"); super.onCreate(); this.mGamePaused = true; this.mEngineOptions = this.onCreateEngineOptions(); this.mEngine = this.onCreateEngine(this.mEngineOptions); this.mEngine.startUpdateThread(); this.applyEngineOptions(); } @Override public org.andengine.engine.Engine onCreateEngine(final EngineOptions pEngineOptions) { return new org.andengine.engine.Engine(pEngineOptions); } @Override public synchronized void onSurfaceCreated(final GLState pGLState) { Debug.d(this.getClass().getSimpleName() + ".onSurfaceCreated" + " @(Thread: '" + Thread.currentThread().getName() + "')"); if(this.mGameCreated) { this.onReloadResources(); } else { if(this.mCreateGameCalled) { this.mOnReloadResourcesScheduled = true; } else { this.mCreateGameCalled = true; this.onCreateGame(); } } } @Override public void onSurfaceChanged(final GLState pGLState, final int pWidth, final int pHeight) { Debug.d(this.getClass().getSimpleName() + ".onSurfaceChanged(Width=" + pWidth + ", Height=" + pHeight + ")" + " @(Thread: '" + Thread.currentThread().getName() + "')"); } protected void onCreateGame() { Debug.d(this.getClass().getSimpleName() + ".onCreateGame" + " @(Thread: '" + Thread.currentThread().getName() + "')"); final OnPopulateSceneCallback onPopulateSceneCallback = new OnPopulateSceneCallback() { @Override public void onPopulateSceneFinished() { try { Debug.d(BaseLiveWallpaperService.this.getClass().getSimpleName() + ".onGameCreated" + " @(Thread: '" + Thread.currentThread().getName() + "')"); BaseLiveWallpaperService.this.onGameCreated(); } catch(final Throwable pThrowable) { Debug.e(BaseLiveWallpaperService.this.getClass().getSimpleName() + ".onGameCreated failed." + " @(Thread: '" + Thread.currentThread().getName() + "')", pThrowable); } BaseLiveWallpaperService.this.onResumeGame(); } }; final OnCreateSceneCallback onCreateSceneCallback = new OnCreateSceneCallback() { @Override public void onCreateSceneFinished(final Scene pScene) { BaseLiveWallpaperService.this.mEngine.setScene(pScene); try { Debug.d(BaseLiveWallpaperService.this.getClass().getSimpleName() + ".onPopulateScene" + " @(Thread: '" + Thread.currentThread().getName() + "')"); BaseLiveWallpaperService.this.onPopulateScene(pScene, onPopulateSceneCallback); } catch(final Throwable pThrowable) { Debug.e(BaseLiveWallpaperService.this.getClass().getSimpleName() + ".onPopulateScene failed." + " @(Thread: '" + Thread.currentThread().getName() + "')", pThrowable); } } }; final OnCreateResourcesCallback onCreateResourcesCallback = new OnCreateResourcesCallback() { @Override public void onCreateResourcesFinished() { try { Debug.d(BaseLiveWallpaperService.this.getClass().getSimpleName() + ".onCreateScene" + " @(Thread: '" + Thread.currentThread().getName() + "')"); BaseLiveWallpaperService.this.onCreateScene(onCreateSceneCallback); } catch(final Throwable pThrowable) { Debug.e(BaseLiveWallpaperService.this.getClass().getSimpleName() + ".onCreateScene failed." + " @(Thread: '" + Thread.currentThread().getName() + "')", pThrowable); } } }; try { Debug.d(this.getClass().getSimpleName() + ".onCreateResources" + " @(Thread: '" + Thread.currentThread().getName() + "')"); this.onCreateResources(onCreateResourcesCallback); } catch(final Throwable pThrowable) { Debug.e(this.getClass().getSimpleName() + ".onCreateGame failed." + " @(Thread: '" + Thread.currentThread().getName() + "')", pThrowable); } } @Override public synchronized void onGameCreated() { this.mGameCreated = true; /* Since the potential asynchronous resource creation, * the surface might already be invalid * and a resource reloading might be necessary. */ if(this.mOnReloadResourcesScheduled) { this.mOnReloadResourcesScheduled = false; try { this.onReloadResources(); } catch(final Throwable pThrowable) { Debug.e(this.getClass().getSimpleName() + ".onReloadResources failed." + " @(Thread: '" + Thread.currentThread().getName() + "')", pThrowable); } } } protected synchronized void onResume() { Debug.d(this.getClass().getSimpleName() + ".onResume" + " @(Thread: '" + Thread.currentThread().getName() + "')"); } @Override public synchronized void onResumeGame() { Debug.d(this.getClass().getSimpleName() + ".onResumeGame" + " @(Thread: '" + Thread.currentThread().getName() + "')"); this.mEngine.start(); this.mGamePaused = false; } @Override public void onReloadResources() { Debug.d(this.getClass().getSimpleName() + ".onReloadResources" + " @(Thread: '" + Thread.currentThread().getName() + "')"); this.mEngine.onReloadResources(); this.onResumeGame(); } protected void onPause(){ Debug.d(this.getClass().getSimpleName() + ".onPause" + " @(Thread: '" + Thread.currentThread().getName() + "')"); if(!this.mGamePaused) { this.onPauseGame(); } } @Override public void onPauseGame() { Debug.d(this.getClass().getSimpleName() + ".onPauseGame" + " @(Thread: '" + Thread.currentThread().getName() + "')"); this.mGamePaused = true; this.mEngine.stop(); } @Override public void onDestroy() { Debug.d(this.getClass().getSimpleName() + ".onDestroy" + " @(Thread: '" + Thread.currentThread().getName() + "')"); super.onDestroy(); this.mEngine.onDestroy(); try { this.onDestroyResources(); } catch (final Throwable pThrowable) { Debug.e(this.getClass().getSimpleName() + ".onDestroyResources failed." + " @(Thread: '" + Thread.currentThread().getName() + "')", pThrowable); } this.onGameDestroyed(); } @Override public void onDestroyResources() throws Exception { Debug.d(this.getClass().getSimpleName() + ".onDestroyResources" + " @(Thread: '" + Thread.currentThread().getName() + "')"); if(this.mEngine.getEngineOptions().getAudioOptions().needsMusic()) { this.mEngine.getMusicManager().releaseAll(); } if(this.mEngine.getEngineOptions().getAudioOptions().needsSound()) { this.mEngine.getSoundManager().releaseAll(); } } @Override public synchronized void onGameDestroyed() { Debug.d(this.getClass().getSimpleName() + ".onGameDestroyed" + " @(Thread: '" + Thread.currentThread().getName() + "')"); this.mGameCreated = false; } // =========================================================== // Getter & Setter // =========================================================== public org.andengine.engine.Engine getEngine() { return this.mEngine; } public boolean isGamePaused() { return this.mGamePaused; } public boolean isGameRunning() { return !this.mGamePaused; } public boolean isGameLoaded() { return this.mGameCreated; } public VertexBufferObjectManager getVertexBufferObjectManager() { return this.mEngine.getVertexBufferObjectManager(); } public TextureManager getTextureManager() { return this.mEngine.getTextureManager(); } public FontManager getFontManager() { return this.mEngine.getFontManager(); } public ShaderProgramManager getShaderProgramManager() { return this.mEngine.getShaderProgramManager(); } public SoundManager getSoundManager() throws IllegalStateException { return this.mEngine.getSoundManager(); } public MusicManager getMusicManager() throws IllegalStateException { return this.mEngine.getMusicManager(); } // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override public Engine onCreateEngine() { return new BaseWallpaperGLEngine(this); } // =========================================================== // Methods // =========================================================== protected void onTap(final int pX, final int pY) { this.mEngine.onTouch(null, MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, pX, pY, 0)); } protected void onDrop(final int pX, final int pY) { } protected void onOffsetsChanged(final float pXOffset, final float pYOffset, final float pXOffsetStep, final float pYOffsetStep, final int pXPixelOffset, final int pYPixelOffset) { } protected void applyEngineOptions() { } protected boolean enableVibrator() { return this.mEngine.enableVibrator(this); } protected boolean enableAccelerationSensor(final IAccelerationListener pAccelerationListener) { return this.mEngine.enableAccelerationSensor(this, pAccelerationListener); } protected boolean enableOrientationSensor(final IOrientationListener pOrientationListener) { return this.mEngine.enableOrientationSensor(this, pOrientationListener); } // =========================================================== // Inner and Anonymous Classes // =========================================================== protected class BaseWallpaperGLEngine extends GLEngine { // =========================================================== // Constants // =========================================================== // =========================================================== // Fields // =========================================================== private EngineRenderer mEngineRenderer; private ConfigChooser mConfigChooser; // =========================================================== // Constructors // =========================================================== public BaseWallpaperGLEngine(final IRendererListener pRendererListener) { if(this.mConfigChooser == null) { this.mConfigChooser = new ConfigChooser(BaseLiveWallpaperService.this.mEngine.getEngineOptions().getRenderOptions().isMultiSampling()); } this.setEGLConfigChooser(this.mConfigChooser); this.mEngineRenderer = new EngineRenderer(BaseLiveWallpaperService.this.mEngine, this.mConfigChooser, pRendererListener); this.setRenderer(this.mEngineRenderer); this.setRenderMode(GLEngine.RENDERMODE_CONTINUOUSLY); } // =========================================================== // Getter & Setter // =========================================================== // =========================================================== // Methods for/from SuperClass/Interfaces // =========================================================== @Override public Bundle onCommand(final String pAction, final int pX, final int pY, final int pZ, final Bundle pExtras, final boolean pResultRequested) { if(pAction.equals(WallpaperManager.COMMAND_TAP)) { BaseLiveWallpaperService.this.onTap(pX, pY); } else if (pAction.equals(WallpaperManager.COMMAND_DROP)) { BaseLiveWallpaperService.this.onDrop(pX, pY); } return super.onCommand(pAction, pX, pY, pZ, pExtras, pResultRequested); } @Override public void onOffsetsChanged(final float pXOffset, final float pYOffset, final float pXOffsetStep, final float pYOffsetStep, final int pXPixelOffset, final int pYPixelOffset) { BaseLiveWallpaperService.this.onOffsetsChanged(pXOffset, pYOffset, pXOffsetStep, pYOffsetStep, pXPixelOffset, pYPixelOffset); } @Override public void onResume() { super.onResume(); BaseLiveWallpaperService.this.getEngine().onReloadResources(); BaseLiveWallpaperService.this.onResume(); } @Override public void onPause() { super.onPause(); BaseLiveWallpaperService.this.onPause(); } @Override public void onDestroy() { super.onDestroy(); this.mEngineRenderer = null; } // =========================================================== // Methods // =========================================================== // =========================================================== // Inner and Anonymous Classes // =========================================================== } }