From 9f6ebfb7b2ebcb61bd1224e441dfb3856ae84c28 Mon Sep 17 00:00:00 2001 From: Scrappers Date: Sat, 27 Mar 2021 13:32:31 -0500 Subject: [PATCH 1/7] Added JmeSurfaceView.java class , for embedding jme-game in a custom xml UI design. --- jme3-android/build.gradle | 3 + .../java/com/jme3/app/JmeSurfaceView.java | 482 ++++++++++++++++++ 2 files changed, 485 insertions(+) create mode 100644 jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java diff --git a/jme3-android/build.gradle b/jme3-android/build.gradle index 98a2b37a0a..2dd879493d 100644 --- a/jme3-android/build.gradle +++ b/jme3-android/build.gradle @@ -5,6 +5,9 @@ if (!hasProperty('mainClass')) { } dependencies { + //added annotations used by JmeSurfaceView. + implementation 'com.android.support:support-annotations:28.0.0' + implementation 'org.jetbrains:annotations:20.1.0' compile project(':jme3-core') compile project(':jme3-plugins') compileOnly 'android:android' diff --git a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java new file mode 100644 index 0000000000..3414e42528 --- /dev/null +++ b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java @@ -0,0 +1,482 @@ +package com.jme3.app; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.opengl.GLSurfaceView; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +import com.jme3.audio.AudioRenderer; +import com.jme3.input.JoyInput; +import com.jme3.input.android.AndroidSensorJoyInput; +import com.jme3.system.AppSettings; +import com.jme3.system.SystemListener; +import com.jme3.system.android.JmeAndroidSystem; +import com.jme3.system.android.OGLESContext; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * A RelativeLayout Class Holder that holds a #{{@link GLSurfaceView}} using #{{@link OGLESContext}} as a renderer to render + * a JME game on an android view for custom xmL designs. + * + * @apiNote the main idea of #{@link JmeSurfaceView} class is to start a jMonkeyEngine application in a SystemListener#{@link SystemListener} context in a GL_ES thread , + * then the GLSurfaceView holding the GL_ES thread joins the UI thread with a delay of user's choice using a #{@link Handler} , during the delay , the game runs normally in the GL_ES thread(but without coming up on the UI) + * and the user has the ability to handle a couple of actions asynchronously as displaying a progress bar on a SplashScreen or + * an image or even play a preface game music of choice. + * + * @author pavl_g. + */ +public class JmeSurfaceView extends RelativeLayout implements SystemListener,DialogInterface.OnClickListener { + + /*using #{@link LegacyApplication} instead of #{@link SimpleApplication} to include all classes extends LegacyApplication*/ + private LegacyApplication legacyApplication; + protected String audioRendererType = AppSettings.ANDROID_OPENAL_SOFT; + private static final Logger jmeSurfaceViewLogger=Logger.getLogger("JmeSurfaceView"); + private AppSettings appSettings; + private int eglBitsPerPixel = 24; + private int eglAlphaBits = 0; + private int eglDepthBits = 16; + private int eglSamples = 0; + private int eglStencilBits = 0; + private int frameRate = -1; + private boolean emulateKeyBoard=true; + private boolean emulateMouse=true; + private boolean useJoyStickEvents=true; + private boolean isGLThreadPaused; + private final Handler handler=new Handler(); + private GLSurfaceView glSurfaceView; + private OnRendererCompleted onRendererCompleted; + private final AtomicInteger synthesizedTime=new AtomicInteger(); + private OnExceptionThrown onExceptionThrown; + private int delayMillis=0; + private static final int TOLERANCE_TIMER=100; + + public JmeSurfaceView(@NonNull Context context) { + super(context); + } + public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + /** + * starts the jmeRenderer on a GlSurfaceView attached to a RelativeLayout + * @param delayMillis delay of the appearance of jme game on the screen , this doesn't delay the renderer though. + */ + public synchronized void startRenderer(int delayMillis) { + this.delayMillis=delayMillis; + if ( legacyApplication != null ){ + try { + /*initialize App Settings & start the Game*/ + appSettings = new AppSettings(true); + appSettings.setAudioRenderer(audioRendererType); + appSettings.setResolution(JmeSurfaceView.this.getLayoutParams().width, JmeSurfaceView.this.getLayoutParams().height); + appSettings.setAlphaBits(eglAlphaBits); + appSettings.setDepthBits(eglDepthBits); + appSettings.setSamples(eglSamples); + appSettings.setStencilBits(eglStencilBits); + appSettings.setBitsPerPixel(eglBitsPerPixel); + appSettings.setEmulateKeyboard(emulateKeyBoard); + appSettings.setEmulateMouse(emulateMouse); + appSettings.setUseJoysticks(useJoyStickEvents); + legacyApplication.setSettings(appSettings); + /*start jme game context*/ + legacyApplication.start(); + /*attach the game to JmE OpenGL.Renderer context */ + OGLESContext oglesContext = (OGLESContext) legacyApplication.getContext(); + /*create a glSurfaceView that will hold the renderer thread*/ + glSurfaceView = oglesContext.createView(JmeSurfaceView.this.getContext()); + /*set the current view as the system engine thread view for future uses*/ + JmeAndroidSystem.setView(JmeSurfaceView.this); + /*set JME system Listener to initialize game , update , requestClose & destroy on closure*/ + oglesContext.setSystemListener(JmeSurfaceView.this); + /* set the glSurfaceView to fit the widget */ + glSurfaceView.setLayoutParams(new LayoutParams(JmeSurfaceView.this.getLayoutParams().width, JmeSurfaceView.this.getLayoutParams().height)); + /*post delay the renderer join into the UI thread*/ + handler.postDelayed(new RendererThread(),delayMillis); + } catch (Exception e) { + showErrorDialog(e,e.getMessage()); + if( onExceptionThrown !=null){ + onExceptionThrown.Throw(e); + jmeSurfaceViewLogger.log(Level.WARNING,e.getMessage()); + } + } + } + } + + /** + * Custom thread that delays the appearance of the display of jme game on the screen for the sake of initial frame pacing & splash screens. + */ + private class RendererThread implements Runnable{ + @Override + public synchronized void run() { + /*jme Renderer joins the UIThread at that point*/ + JmeSurfaceView.this.addView(glSurfaceView); + jmeSurfaceViewLogger.log(Level.CONFIG,"JmeSurfaceView's joined the UI thread......."); + } + } + + @Override + public synchronized void initialize() { + if( legacyApplication !=null){ + legacyApplication.enqueue(() -> legacyApplication.initialize()); + /*log for display*/ + jmeSurfaceViewLogger.log(Level.INFO,"JmeGame started in GLThread Asynchronously......"); + } + } + + @Override + public void reshape(int width, int height) { + if( legacyApplication !=null){ + legacyApplication.reshape(width, height); + } + } + + @Override + public synchronized void update() { + if( legacyApplication ==null){ + return; + } + if ( glSurfaceView != null ){ + legacyApplication.update(); + } + int timeToPlay=synthesizedTime.addAndGet(1); + if(timeToPlay==(delayMillis>100?(delayMillis-TOLERANCE_TIMER) :delayMillis)){ + ((Activity)getContext()).runOnUiThread(() -> { + jmeSurfaceViewLogger.log(Level.INFO,"SplashScreen Dismissed , User Delay completed with 0 errors......."); + if ( onRendererCompleted != null ){ + onRendererCompleted.onRenderCompletion(legacyApplication); + } + }); + } + } + + @Override + public void requestClose(boolean esc) { + if( legacyApplication !=null){ + legacyApplication.enqueue(() -> legacyApplication.requestClose(esc)); + } + } + + @Override + public void gainFocus() { + if ( legacyApplication != null) { + /*resume the audio*/ + AudioRenderer audioRenderer = legacyApplication.getAudioRenderer(); + if (audioRenderer != null) { + audioRenderer.resumeAll(); + } + /*resume the sensors (aka joysticks)*/ + if ( legacyApplication.getContext() != null) { + JoyInput joyInput = legacyApplication.getContext().getJoyInput(); + if (joyInput != null) { + if (joyInput instanceof AndroidSensorJoyInput ) { + AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; + androidJoyInput.resumeSensors(); + } + } + legacyApplication.gainFocus(); + } + } + setGLThreadPaused(false); + } + + @Override + public void loseFocus() { + if ( legacyApplication != null) { + /*pause the audio*/ + legacyApplication.loseFocus(); + AudioRenderer audioRenderer = legacyApplication.getAudioRenderer(); + if (audioRenderer != null) { + audioRenderer.pauseAll(); + } + /*pause the sensors (aka joysticks)*/ + if ( legacyApplication.getContext() != null) { + JoyInput joyInput = legacyApplication.getContext().getJoyInput(); + if (joyInput != null) { + if (joyInput instanceof AndroidSensorJoyInput) { + AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; + androidJoyInput.pauseSensors(); + } + } + } + } + setGLThreadPaused(true); + } + + @Override + public void handleError(String errorMsg, Throwable t) { + System.out.println(errorMsg); + } + + @Override + public void destroy() { + if ( legacyApplication != null) { + legacyApplication.stop(isGLThreadPaused()); + legacyApplication.destroy(); + } + } + + /** + * Displays an error dialog with a throwable message(error/exception) & with 2 buttons. + * @param throwable the throwable stack. + * @param message the string message. + */ + public void showErrorDialog(Throwable throwable,String message){ + ((Activity)getContext()).runOnUiThread(()->{ + AlertDialog alertDialog=new AlertDialog.Builder(getContext()).create(); + alertDialog.setTitle(new StringBuffer(String.valueOf(throwable))); + alertDialog.setMessage(message); + alertDialog.setCancelable(true); + alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE,"EXIT",this); + alertDialog.setButton(DialogInterface.BUTTON_POSITIVE,"DISMISS", this); + alertDialog.show(); + }); + } + @Override + public void onClick(DialogInterface dialog, int which) { + switch (which){ + case DialogInterface.BUTTON_NEGATIVE: + dialog.dismiss(); + ((Activity)getContext()).finish(); + break; + case DialogInterface.BUTTON_POSITIVE: + dialog.dismiss(); + break; + } + } + /** + * sets the jme game instance that will be engaged into the {@link SystemListener}. + * @param legacyApplication your jme game instance. + */ + public void setLegacyApplication(@NonNull LegacyApplication legacyApplication) { + this.legacyApplication = legacyApplication; + } + /** + * gets the jme app instance + * @return legacyApplication instance representing your game enclosure. + */ + public LegacyApplication getLegacyApplication() { + return legacyApplication; + } + /** + * sets the appSettings instance. + * @param appSettings the custom appSettings instance + */ + public void setAppSettings(@NonNull AppSettings appSettings) { + this.appSettings = appSettings; + } + /** + * gets the game window settings. + * @return app settings instance. + */ + public AppSettings getAppSettings() { + return appSettings; + } + /** + * sets the memory representing each pixel in bits. + * @param eglBitsPerPixel the bits for each pixel. + */ + public void setEglBitsPerPixel(int eglBitsPerPixel) { + this.eglBitsPerPixel = eglBitsPerPixel; + } + /** + * gets the bits/pixel for Embedded gL + * @return integer representing it. + */ + public int getEglBitsPerPixel() { + return eglBitsPerPixel; + } + + /** + * sets the memory representing the alpha of embedded gl in bits. + * @param eglAlphaBits the alpha bits. + */ + public void setEglAlphaBits(int eglAlphaBits) { + this.eglAlphaBits = eglAlphaBits; + } + /** + * gets the Embedded gL alpha(opacity) bits. + * @return integer representing it. + */ + public int getEglAlphaBits() { + return eglAlphaBits; + } + /** + * sets the EGL depth in bits. + * the depth buffer or Z-buffer is basically coupled with stencil buffer , + * usually 8bits stencilBuffer + 24bits depthBuffer = 32bits shared memory. + * @param eglDepthBits the depth bits. + * @see JmeSurfaceView#setEglStencilBits(int). + */ + public void setEglDepthBits(int eglDepthBits) { + this.eglDepthBits = eglDepthBits; + } + /** + * gets the memory representing the EGL depth in bits. + * @return the depth bits. + */ + public int getEglDepthBits() { + return eglDepthBits; + } + /** + * Sets the number of samples to use for multi-sampling. + * Leave 0 (default) to disable multi-sampling. + * Set to 2 or 4 to enable multi-sampling. + * @param eglSamples embedded gl samples bits to set. + */ + public void setEglSamples(int eglSamples) { + this.eglSamples = eglSamples; + } + /** + * get the number of samples to use for multi-sampling. + * @return number of samples to use for multi-sampling. + */ + public int getEglSamples() { + return eglSamples; + } + /** + * Set the number of stencil buffer bits. + * Stencil buffer is used in depth-based shadow maps & shadow rendering as it limits rendering, + * it's coupled with Z-buffer or depth buffer,usually 8bits stencilBuffer + 24bits depthBuffer = 32bits shared memory. + * (default = 0) + * @param eglStencilBits the desired number of stencil bits. + * @see JmeSurfaceView#setEglDepthBits(int). + */ + public void setEglStencilBits(int eglStencilBits) { + this.eglStencilBits = eglStencilBits; + } + /** + * gets the number of stencil buffer bits. + * @return the stencil buffer bits. + */ + public int getEglStencilBits() { + return eglStencilBits; + } + /** + * limits the frame rate (fps) in the second. + * @param frameRate the limitation in integers. + */ + public void setFrameRate(int frameRate) { + this.frameRate = frameRate; + } + /** + * gets the limited FrameRate level for egl config. + * @implNote + * @return the limit frameRate in integers. + */ + public int getFrameRate() { + return frameRate; + } + /** + * sets the audioRenderer type. + * {@link AppSettings#ANDROID_OPENAL_SOFT}. + * @param audioRendererType string representing audioRenderer type. + */ + public void setAudioRendererType(String audioRendererType) { + this.audioRendererType = audioRendererType; + } + /** + * gets the audio renderer in String. + * @return string representing audio renderer framework. + */ + public String getAudioRendererType() { + return audioRendererType; + } + /** + * enables keyboard interfacing. + * @param emulateKeyBoard true to enable keyboard interfacing. + */ + public void setEmulateKeyBoard(boolean emulateKeyBoard) { + this.emulateKeyBoard = emulateKeyBoard; + } + /** + * checks if the keyboard interfacing is enabled. + * @return true if the keyboard interfacing is enabled. + */ + public boolean isEmulateKeyBoard() { + return emulateKeyBoard; + } + /** + * enables mouse interfacing. + * @param emulateMouse true to enable the mouse interfacing. + */ + public void setEmulateMouse(boolean emulateMouse) { + this.emulateMouse = emulateMouse; + } + /** + * checks whether the mouse interfacing is enabled or not. + * @return true if the mouse interfacing is enabled. + */ + public boolean isEmulateMouse() { + return emulateMouse; + } + /** + * enable joystick interfacing for a jme-game + * @param useJoyStickEvents true to enable the joystick interfacing. + */ + public void setUseJoyStickEvents(boolean useJoyStickEvents) { + this.useJoyStickEvents = useJoyStickEvents; + } + /** + * checks whether joystick interfacing is enabled or not. + * @return true if the joystick interfacing is enabled. + */ + public boolean isUseJoyStickEvents() { + return useJoyStickEvents; + } + /** + * sets GL Thread paused. + * @param GLThreadPaused true if you want to pause the GLThread. + */ + protected void setGLThreadPaused(boolean GLThreadPaused) { + isGLThreadPaused = GLThreadPaused; + } + /** + * checks whether the GLThread is paused or not. + * @return true/false + */ + public boolean isGLThreadPaused() { + return isGLThreadPaused; + } + /** + * Embedded interface class(abstract) to listen for the moment when when the GL thread holding the #{@link JmeSurfaceView} + * joins the UI thread , after asynchronous rendering. + * @see JmeSurfaceView#setOnRendererCompleted(OnRendererCompleted). + */ + public interface OnRendererCompleted{ + void onRenderCompletion(LegacyApplication application); + } + /** + * sets the listener for the completion of rendering , ie :: when the GL thread holding the #{@link JmeSurfaceView} + * joins the UI thread , after asynchronous rendering. + * @param onRendererCompleted an instance of the interface #{@link OnRendererCompleted}. + */ + public void setOnRendererCompleted(OnRendererCompleted onRendererCompleted) { + this.onRendererCompleted = onRendererCompleted; + } + /** + * Embedded interface designed to listen to exceptions & fire when an exception is thrown. + * @see JmeSurfaceView#setOnExceptionThrown(OnExceptionThrown). + */ + public interface OnExceptionThrown{ + void Throw(Throwable e); + } + /** + * sets the listener that will fire when an exception is thrown. + * @param onExceptionThrown an instance of the interface #{@link OnExceptionThrown}. + */ + public void setOnExceptionThrown(OnExceptionThrown onExceptionThrown) { + this.onExceptionThrown = onExceptionThrown; + } +} \ No newline at end of file From a49b7b9014b08e343fea79d55f814db8e8bafe6b Mon Sep 17 00:00:00 2001 From: Scrappers-glitch <60224159+Scrappers-glitch@users.noreply.github.com> Date: Sun, 28 Mar 2021 06:47:49 -0500 Subject: [PATCH 2/7] Removal of white spaces Removal of white spaces between if...else conditions & class methods. --- .../java/com/jme3/app/JmeSurfaceView.java | 48 +++++++------------ 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java index 3414e42528..79400b8d10 100644 --- a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java +++ b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java @@ -9,7 +9,6 @@ import android.support.annotation.NonNull; import android.util.AttributeSet; import android.widget.RelativeLayout; - import com.jme3.audio.AudioRenderer; import com.jme3.input.JoyInput; import com.jme3.input.android.AndroidSensorJoyInput; @@ -18,7 +17,6 @@ import com.jme3.system.android.JmeAndroidSystem; import com.jme3.system.android.OGLESContext; import org.jetbrains.annotations.Nullable; - import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; @@ -26,7 +24,6 @@ /** * A RelativeLayout Class Holder that holds a #{{@link GLSurfaceView}} using #{{@link OGLESContext}} as a renderer to render * a JME game on an android view for custom xmL designs. - * * @apiNote the main idea of #{@link JmeSurfaceView} class is to start a jMonkeyEngine application in a SystemListener#{@link SystemListener} context in a GL_ES thread , * then the GLSurfaceView holding the GL_ES thread joins the UI thread with a delay of user's choice using a #{@link Handler} , during the delay , the game runs normally in the GL_ES thread(but without coming up on the UI) * and the user has the ability to handle a couple of actions asynchronously as displaying a progress bar on a SplashScreen or @@ -113,7 +110,6 @@ public synchronized void startRenderer(int delayMillis) { } } } - /** * Custom thread that delays the appearance of the display of jme game on the screen for the sake of initial frame pacing & splash screens. */ @@ -125,7 +121,6 @@ public synchronized void run() { jmeSurfaceViewLogger.log(Level.CONFIG,"JmeSurfaceView's joined the UI thread......."); } } - @Override public synchronized void initialize() { if( legacyApplication !=null){ @@ -134,53 +129,49 @@ public synchronized void initialize() { jmeSurfaceViewLogger.log(Level.INFO,"JmeGame started in GLThread Asynchronously......"); } } - @Override public void reshape(int width, int height) { if( legacyApplication !=null){ legacyApplication.reshape(width, height); } } - @Override public synchronized void update() { - if( legacyApplication ==null){ + if(legacyApplication==null){ return; } - if ( glSurfaceView != null ){ + if (glSurfaceView!=null){ legacyApplication.update(); } int timeToPlay=synthesizedTime.addAndGet(1); if(timeToPlay==(delayMillis>100?(delayMillis-TOLERANCE_TIMER) :delayMillis)){ ((Activity)getContext()).runOnUiThread(() -> { jmeSurfaceViewLogger.log(Level.INFO,"SplashScreen Dismissed , User Delay completed with 0 errors......."); - if ( onRendererCompleted != null ){ + if (onRendererCompleted!=null){ onRendererCompleted.onRenderCompletion(legacyApplication); } }); } } - @Override public void requestClose(boolean esc) { - if( legacyApplication !=null){ + if(legacyApplication!=null){ legacyApplication.enqueue(() -> legacyApplication.requestClose(esc)); } } - @Override public void gainFocus() { - if ( legacyApplication != null) { + if (legacyApplication!=null){ /*resume the audio*/ AudioRenderer audioRenderer = legacyApplication.getAudioRenderer(); - if (audioRenderer != null) { + if (audioRenderer!=null){ audioRenderer.resumeAll(); } /*resume the sensors (aka joysticks)*/ - if ( legacyApplication.getContext() != null) { + if (legacyApplication.getContext()!=null){ JoyInput joyInput = legacyApplication.getContext().getJoyInput(); - if (joyInput != null) { - if (joyInput instanceof AndroidSensorJoyInput ) { + if (joyInput!=null){ + if (joyInput instanceof AndroidSensorJoyInput){ AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; androidJoyInput.resumeSensors(); } @@ -190,21 +181,20 @@ public void gainFocus() { } setGLThreadPaused(false); } - @Override public void loseFocus() { - if ( legacyApplication != null) { + if (legacyApplication!=null){ /*pause the audio*/ legacyApplication.loseFocus(); AudioRenderer audioRenderer = legacyApplication.getAudioRenderer(); - if (audioRenderer != null) { + if (audioRenderer!=null){ audioRenderer.pauseAll(); } /*pause the sensors (aka joysticks)*/ - if ( legacyApplication.getContext() != null) { + if (legacyApplication.getContext()!=null){ JoyInput joyInput = legacyApplication.getContext().getJoyInput(); - if (joyInput != null) { - if (joyInput instanceof AndroidSensorJoyInput) { + if (joyInput!=null){ + if (joyInput instanceof AndroidSensorJoyInput){ AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; androidJoyInput.pauseSensors(); } @@ -213,20 +203,17 @@ public void loseFocus() { } setGLThreadPaused(true); } - @Override - public void handleError(String errorMsg, Throwable t) { + public void handleError(String errorMsg,Throwable t) { System.out.println(errorMsg); } - @Override public void destroy() { - if ( legacyApplication != null) { + if (legacyApplication!=null){ legacyApplication.stop(isGLThreadPaused()); legacyApplication.destroy(); } } - /** * Displays an error dialog with a throwable message(error/exception) & with 2 buttons. * @param throwable the throwable stack. @@ -297,7 +284,6 @@ public void setEglBitsPerPixel(int eglBitsPerPixel) { public int getEglBitsPerPixel() { return eglBitsPerPixel; } - /** * sets the memory representing the alpha of embedded gl in bits. * @param eglAlphaBits the alpha bits. @@ -479,4 +465,4 @@ public interface OnExceptionThrown{ public void setOnExceptionThrown(OnExceptionThrown onExceptionThrown) { this.onExceptionThrown = onExceptionThrown; } -} \ No newline at end of file +} From e302f09bec341eb9ba0e52f84d285686e314fb65 Mon Sep 17 00:00:00 2001 From: Scrappers-glitch <60224159+Scrappers-glitch@users.noreply.github.com> Date: Sun, 28 Mar 2021 06:49:04 -0500 Subject: [PATCH 3/7] Removal of white spaces --- jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java index 79400b8d10..e2f0fce835 100644 --- a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java +++ b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java @@ -62,7 +62,6 @@ public JmeSurfaceView(@NonNull Context context) { public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } - public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -72,7 +71,7 @@ public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, in */ public synchronized void startRenderer(int delayMillis) { this.delayMillis=delayMillis; - if ( legacyApplication != null ){ + if (legacyApplication!=null){ try { /*initialize App Settings & start the Game*/ appSettings = new AppSettings(true); From 25a687dd174cbbda38478aed491ceb5e86744971 Mon Sep 17 00:00:00 2001 From: Scrappers Date: Fri, 2 Apr 2021 14:03:28 -0500 Subject: [PATCH 4/7] Cleaning up (formatting errors/jme copyright) --- jme3-android/build.gradle | 3 +- .../java/com/jme3/app/JmeSurfaceView.java | 211 +++++++++++------- .../java/com/jme3/app/OnExceptionThrown.java | 44 ++++ .../com/jme3/app/OnRendererCompleted.java | 49 ++++ 4 files changed, 227 insertions(+), 80 deletions(-) create mode 100644 jme3-android/src/main/java/com/jme3/app/OnExceptionThrown.java create mode 100644 jme3-android/src/main/java/com/jme3/app/OnRendererCompleted.java diff --git a/jme3-android/build.gradle b/jme3-android/build.gradle index 2dd879493d..7e198ef159 100644 --- a/jme3-android/build.gradle +++ b/jme3-android/build.gradle @@ -6,8 +6,7 @@ if (!hasProperty('mainClass')) { dependencies { //added annotations used by JmeSurfaceView. - implementation 'com.android.support:support-annotations:28.0.0' - implementation 'org.jetbrains:annotations:20.1.0' + implementation 'androidx.appcompat:appcompat:1.2.0' compile project(':jme3-core') compile project(':jme3-plugins') compileOnly 'android:android' diff --git a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java index 3414e42528..ed2b81b6a2 100644 --- a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java +++ b/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java @@ -1,3 +1,34 @@ +/* + * Copyright (c) 2009-2020 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ package com.jme3.app; import android.app.Activity; @@ -6,10 +37,10 @@ import android.content.DialogInterface; import android.opengl.GLSurfaceView; import android.os.Handler; -import android.support.annotation.NonNull; import android.util.AttributeSet; import android.widget.RelativeLayout; - +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.jme3.audio.AudioRenderer; import com.jme3.input.JoyInput; import com.jme3.input.android.AndroidSensorJoyInput; @@ -17,29 +48,26 @@ import com.jme3.system.SystemListener; import com.jme3.system.android.JmeAndroidSystem; import com.jme3.system.android.OGLESContext; -import org.jetbrains.annotations.Nullable; - import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; /** - * A RelativeLayout Class Holder that holds a #{{@link GLSurfaceView}} using #{{@link OGLESContext}} as a renderer to render - * a JME game on an android view for custom xmL designs. - * - * @apiNote the main idea of #{@link JmeSurfaceView} class is to start a jMonkeyEngine application in a SystemListener#{@link SystemListener} context in a GL_ES thread , + * A RelativeLayout Class Holder that holds a #{{@link GLSurfaceView}} using #{{@link OGLESContext}} as a renderer to render + * a JME game on an android view for custom xmL designs. + * @apiNote The main idea of #{@link JmeSurfaceView} class is to start a jMonkeyEngine application in a SystemListener#{@link SystemListener} context in a GL_ES thread , * then the GLSurfaceView holding the GL_ES thread joins the UI thread with a delay of user's choice using a #{@link Handler} , during the delay , the game runs normally in the GL_ES thread(but without coming up on the UI) * and the user has the ability to handle a couple of actions asynchronously as displaying a progress bar on a SplashScreen or * an image or even play a preface game music of choice. * * @author pavl_g. */ -public class JmeSurfaceView extends RelativeLayout implements SystemListener,DialogInterface.OnClickListener { +public class JmeSurfaceView extends RelativeLayout implements SystemListener , DialogInterface.OnClickListener { /*using #{@link LegacyApplication} instead of #{@link SimpleApplication} to include all classes extends LegacyApplication*/ private LegacyApplication legacyApplication; protected String audioRendererType = AppSettings.ANDROID_OPENAL_SOFT; - private static final Logger jmeSurfaceViewLogger=Logger.getLogger("JmeSurfaceView"); + private static final Logger jmeSurfaceViewLogger = Logger.getLogger("JmeSurfaceView"); private AppSettings appSettings; private int eglBitsPerPixel = 24; private int eglAlphaBits = 0; @@ -47,21 +75,23 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener,Dia private int eglSamples = 0; private int eglStencilBits = 0; private int frameRate = -1; - private boolean emulateKeyBoard=true; - private boolean emulateMouse=true; - private boolean useJoyStickEvents=true; + private boolean emulateKeyBoard = true; + private boolean emulateMouse = true; + private boolean useJoyStickEvents = true; private boolean isGLThreadPaused; - private final Handler handler=new Handler(); + private final Handler handler = new Handler(); private GLSurfaceView glSurfaceView; private OnRendererCompleted onRendererCompleted; - private final AtomicInteger synthesizedTime=new AtomicInteger(); + private final AtomicInteger synthesizedTime = new AtomicInteger(); private OnExceptionThrown onExceptionThrown; - private int delayMillis=0; - private static final int TOLERANCE_TIMER=100; + public static final int NO_DELAY = 1; + private int delayMillis = NO_DELAY; + private static final int TOLERANCE_TIMER = 100; public JmeSurfaceView(@NonNull Context context) { super(context); } + public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @@ -69,18 +99,20 @@ public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs) { public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } + /** - * starts the jmeRenderer on a GlSurfaceView attached to a RelativeLayout + * starts the jmeRenderer on a GlSurfaceView attached to a RelativeLayout. * @param delayMillis delay of the appearance of jme game on the screen , this doesn't delay the renderer though. + * @apiNote use #{@link JmeSurfaceView#NO_DELAY} to disable the delay. */ - public synchronized void startRenderer(int delayMillis) { - this.delayMillis=delayMillis; - if ( legacyApplication != null ){ + public void startRenderer(int delayMillis) { + this.delayMillis = delayMillis; + if (legacyApplication != null) { try { /*initialize App Settings & start the Game*/ appSettings = new AppSettings(true); appSettings.setAudioRenderer(audioRendererType); - appSettings.setResolution(JmeSurfaceView.this.getLayoutParams().width, JmeSurfaceView.this.getLayoutParams().height); + appSettings.setResolution(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height); appSettings.setAlphaBits(eglAlphaBits); appSettings.setDepthBits(eglDepthBits); appSettings.setSamples(eglSamples); @@ -101,14 +133,14 @@ public synchronized void startRenderer(int delayMillis) { /*set JME system Listener to initialize game , update , requestClose & destroy on closure*/ oglesContext.setSystemListener(JmeSurfaceView.this); /* set the glSurfaceView to fit the widget */ - glSurfaceView.setLayoutParams(new LayoutParams(JmeSurfaceView.this.getLayoutParams().width, JmeSurfaceView.this.getLayoutParams().height)); + glSurfaceView.setLayoutParams(new LayoutParams(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height)); /*post delay the renderer join into the UI thread*/ - handler.postDelayed(new RendererThread(),delayMillis); + handler.postDelayed(new RendererThread() , delayMillis); } catch (Exception e) { - showErrorDialog(e,e.getMessage()); - if( onExceptionThrown !=null){ - onExceptionThrown.Throw(e); - jmeSurfaceViewLogger.log(Level.WARNING,e.getMessage()); + jmeSurfaceViewLogger.log(Level.WARNING , e.getMessage()); + showErrorDialog(e , e.getMessage()); + if (onExceptionThrown != null) { + onExceptionThrown.onExceptionThrown(e); } } } @@ -117,45 +149,50 @@ public synchronized void startRenderer(int delayMillis) { /** * Custom thread that delays the appearance of the display of jme game on the screen for the sake of initial frame pacing & splash screens. */ - private class RendererThread implements Runnable{ + private class RendererThread implements Runnable { + /** + * Delays the #{@link GLSurfaceView} add on the UI thread. + * @see JmeSurfaceView#NO_DELAY + * @see JmeSurfaceView#startRenderer(int) + */ @Override - public synchronized void run() { + public void run() { /*jme Renderer joins the UIThread at that point*/ JmeSurfaceView.this.addView(glSurfaceView); - jmeSurfaceViewLogger.log(Level.CONFIG,"JmeSurfaceView's joined the UI thread......."); + jmeSurfaceViewLogger.log(Level.CONFIG , "JmeSurfaceView's joined the UI thread......."); } } @Override - public synchronized void initialize() { - if( legacyApplication !=null){ - legacyApplication.enqueue(() -> legacyApplication.initialize()); + public void initialize() { + if (legacyApplication != null) { + legacyApplication.initialize(); /*log for display*/ - jmeSurfaceViewLogger.log(Level.INFO,"JmeGame started in GLThread Asynchronously......"); + jmeSurfaceViewLogger.log(Level.INFO , "JmeGame started in GLThread Asynchronously......."); } } @Override - public void reshape(int width, int height) { - if( legacyApplication !=null){ - legacyApplication.reshape(width, height); + public void reshape(int width , int height) { + if (legacyApplication != null) { + legacyApplication.reshape(width , height); } } @Override - public synchronized void update() { - if( legacyApplication ==null){ + public void update() { + if (legacyApplication == null) { return; } - if ( glSurfaceView != null ){ + if (glSurfaceView != null) { legacyApplication.update(); } - int timeToPlay=synthesizedTime.addAndGet(1); - if(timeToPlay==(delayMillis>100?(delayMillis-TOLERANCE_TIMER) :delayMillis)){ + int timeToPlay = synthesizedTime.addAndGet(1); + if (timeToPlay == (delayMillis>100 ? (delayMillis-TOLERANCE_TIMER) : delayMillis)) { ((Activity)getContext()).runOnUiThread(() -> { jmeSurfaceViewLogger.log(Level.INFO,"SplashScreen Dismissed , User Delay completed with 0 errors......."); - if ( onRendererCompleted != null ){ - onRendererCompleted.onRenderCompletion(legacyApplication); + if (onRendererCompleted != null) { + onRendererCompleted.onRenderCompletion(legacyApplication , legacyApplication.getContext().getSettings()); } }); } @@ -163,24 +200,24 @@ public synchronized void update() { @Override public void requestClose(boolean esc) { - if( legacyApplication !=null){ - legacyApplication.enqueue(() -> legacyApplication.requestClose(esc)); + if (legacyApplication != null) { + legacyApplication.requestClose(esc); } } @Override public void gainFocus() { - if ( legacyApplication != null) { + if (legacyApplication != null) { /*resume the audio*/ AudioRenderer audioRenderer = legacyApplication.getAudioRenderer(); if (audioRenderer != null) { audioRenderer.resumeAll(); } /*resume the sensors (aka joysticks)*/ - if ( legacyApplication.getContext() != null) { + if (legacyApplication.getContext() != null) { JoyInput joyInput = legacyApplication.getContext().getJoyInput(); if (joyInput != null) { - if (joyInput instanceof AndroidSensorJoyInput ) { + if (joyInput instanceof AndroidSensorJoyInput) { AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput; androidJoyInput.resumeSensors(); } @@ -193,7 +230,7 @@ public void gainFocus() { @Override public void loseFocus() { - if ( legacyApplication != null) { + if (legacyApplication != null) { /*pause the audio*/ legacyApplication.loseFocus(); AudioRenderer audioRenderer = legacyApplication.getAudioRenderer(); @@ -201,7 +238,7 @@ public void loseFocus() { audioRenderer.pauseAll(); } /*pause the sensors (aka joysticks)*/ - if ( legacyApplication.getContext() != null) { + if (legacyApplication.getContext() != null) { JoyInput joyInput = legacyApplication.getContext().getJoyInput(); if (joyInput != null) { if (joyInput instanceof AndroidSensorJoyInput) { @@ -215,13 +252,17 @@ public void loseFocus() { } @Override - public void handleError(String errorMsg, Throwable t) { - System.out.println(errorMsg); + public void handleError(String errorMsg , Throwable throwable) { + jmeSurfaceViewLogger.log(Level.WARNING , throwable.getMessage()); + showErrorDialog(throwable , throwable.getMessage()); + if (onExceptionThrown != null) { + onExceptionThrown.onExceptionThrown(throwable); + } } @Override public void destroy() { - if ( legacyApplication != null) { + if (legacyApplication != null) { legacyApplication.stop(isGLThreadPaused()); legacyApplication.destroy(); } @@ -232,20 +273,21 @@ public void destroy() { * @param throwable the throwable stack. * @param message the string message. */ - public void showErrorDialog(Throwable throwable,String message){ - ((Activity)getContext()).runOnUiThread(()->{ - AlertDialog alertDialog=new AlertDialog.Builder(getContext()).create(); + protected void showErrorDialog(Throwable throwable , String message) { + ((Activity)getContext()).runOnUiThread(() -> { + AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create(); alertDialog.setTitle(new StringBuffer(String.valueOf(throwable))); alertDialog.setMessage(message); alertDialog.setCancelable(true); - alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE,"EXIT",this); - alertDialog.setButton(DialogInterface.BUTTON_POSITIVE,"DISMISS", this); + alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE , "EXIT" , this); + alertDialog.setButton(DialogInterface.BUTTON_POSITIVE , "DISMISS", this); alertDialog.show(); }); } + @Override - public void onClick(DialogInterface dialog, int which) { - switch (which){ + public void onClick(DialogInterface dialog , int which) { + switch (which) { case DialogInterface.BUTTON_NEGATIVE: dialog.dismiss(); ((Activity)getContext()).finish(); @@ -255,6 +297,7 @@ public void onClick(DialogInterface dialog, int which) { break; } } + /** * sets the jme game instance that will be engaged into the {@link SystemListener}. * @param legacyApplication your jme game instance. @@ -262,6 +305,7 @@ public void onClick(DialogInterface dialog, int which) { public void setLegacyApplication(@NonNull LegacyApplication legacyApplication) { this.legacyApplication = legacyApplication; } + /** * gets the jme app instance * @return legacyApplication instance representing your game enclosure. @@ -269,6 +313,7 @@ public void setLegacyApplication(@NonNull LegacyApplication legacyApplication) { public LegacyApplication getLegacyApplication() { return legacyApplication; } + /** * sets the appSettings instance. * @param appSettings the custom appSettings instance @@ -276,6 +321,7 @@ public LegacyApplication getLegacyApplication() { public void setAppSettings(@NonNull AppSettings appSettings) { this.appSettings = appSettings; } + /** * gets the game window settings. * @return app settings instance. @@ -283,6 +329,7 @@ public void setAppSettings(@NonNull AppSettings appSettings) { public AppSettings getAppSettings() { return appSettings; } + /** * sets the memory representing each pixel in bits. * @param eglBitsPerPixel the bits for each pixel. @@ -290,6 +337,7 @@ public AppSettings getAppSettings() { public void setEglBitsPerPixel(int eglBitsPerPixel) { this.eglBitsPerPixel = eglBitsPerPixel; } + /** * gets the bits/pixel for Embedded gL * @return integer representing it. @@ -305,6 +353,7 @@ public int getEglBitsPerPixel() { public void setEglAlphaBits(int eglAlphaBits) { this.eglAlphaBits = eglAlphaBits; } + /** * gets the Embedded gL alpha(opacity) bits. * @return integer representing it. @@ -312,6 +361,7 @@ public void setEglAlphaBits(int eglAlphaBits) { public int getEglAlphaBits() { return eglAlphaBits; } + /** * sets the EGL depth in bits. * the depth buffer or Z-buffer is basically coupled with stencil buffer , @@ -322,6 +372,7 @@ public int getEglAlphaBits() { public void setEglDepthBits(int eglDepthBits) { this.eglDepthBits = eglDepthBits; } + /** * gets the memory representing the EGL depth in bits. * @return the depth bits. @@ -329,6 +380,7 @@ public void setEglDepthBits(int eglDepthBits) { public int getEglDepthBits() { return eglDepthBits; } + /** * Sets the number of samples to use for multi-sampling. * Leave 0 (default) to disable multi-sampling. @@ -338,6 +390,7 @@ public int getEglDepthBits() { public void setEglSamples(int eglSamples) { this.eglSamples = eglSamples; } + /** * get the number of samples to use for multi-sampling. * @return number of samples to use for multi-sampling. @@ -345,6 +398,7 @@ public void setEglSamples(int eglSamples) { public int getEglSamples() { return eglSamples; } + /** * Set the number of stencil buffer bits. * Stencil buffer is used in depth-based shadow maps & shadow rendering as it limits rendering, @@ -356,6 +410,7 @@ public int getEglSamples() { public void setEglStencilBits(int eglStencilBits) { this.eglStencilBits = eglStencilBits; } + /** * gets the number of stencil buffer bits. * @return the stencil buffer bits. @@ -363,6 +418,7 @@ public void setEglStencilBits(int eglStencilBits) { public int getEglStencilBits() { return eglStencilBits; } + /** * limits the frame rate (fps) in the second. * @param frameRate the limitation in integers. @@ -370,6 +426,7 @@ public int getEglStencilBits() { public void setFrameRate(int frameRate) { this.frameRate = frameRate; } + /** * gets the limited FrameRate level for egl config. * @implNote @@ -378,6 +435,7 @@ public void setFrameRate(int frameRate) { public int getFrameRate() { return frameRate; } + /** * sets the audioRenderer type. * {@link AppSettings#ANDROID_OPENAL_SOFT}. @@ -386,6 +444,7 @@ public int getFrameRate() { public void setAudioRendererType(String audioRendererType) { this.audioRendererType = audioRendererType; } + /** * gets the audio renderer in String. * @return string representing audio renderer framework. @@ -393,6 +452,7 @@ public void setAudioRendererType(String audioRendererType) { public String getAudioRendererType() { return audioRendererType; } + /** * enables keyboard interfacing. * @param emulateKeyBoard true to enable keyboard interfacing. @@ -400,6 +460,7 @@ public String getAudioRendererType() { public void setEmulateKeyBoard(boolean emulateKeyBoard) { this.emulateKeyBoard = emulateKeyBoard; } + /** * checks if the keyboard interfacing is enabled. * @return true if the keyboard interfacing is enabled. @@ -407,6 +468,7 @@ public void setEmulateKeyBoard(boolean emulateKeyBoard) { public boolean isEmulateKeyBoard() { return emulateKeyBoard; } + /** * enables mouse interfacing. * @param emulateMouse true to enable the mouse interfacing. @@ -414,6 +476,7 @@ public boolean isEmulateKeyBoard() { public void setEmulateMouse(boolean emulateMouse) { this.emulateMouse = emulateMouse; } + /** * checks whether the mouse interfacing is enabled or not. * @return true if the mouse interfacing is enabled. @@ -421,6 +484,7 @@ public void setEmulateMouse(boolean emulateMouse) { public boolean isEmulateMouse() { return emulateMouse; } + /** * enable joystick interfacing for a jme-game * @param useJoyStickEvents true to enable the joystick interfacing. @@ -428,6 +492,7 @@ public boolean isEmulateMouse() { public void setUseJoyStickEvents(boolean useJoyStickEvents) { this.useJoyStickEvents = useJoyStickEvents; } + /** * checks whether joystick interfacing is enabled or not. * @return true if the joystick interfacing is enabled. @@ -435,6 +500,7 @@ public void setUseJoyStickEvents(boolean useJoyStickEvents) { public boolean isUseJoyStickEvents() { return useJoyStickEvents; } + /** * sets GL Thread paused. * @param GLThreadPaused true if you want to pause the GLThread. @@ -442,6 +508,7 @@ public boolean isUseJoyStickEvents() { protected void setGLThreadPaused(boolean GLThreadPaused) { isGLThreadPaused = GLThreadPaused; } + /** * checks whether the GLThread is paused or not. * @return true/false @@ -449,29 +516,16 @@ protected void setGLThreadPaused(boolean GLThreadPaused) { public boolean isGLThreadPaused() { return isGLThreadPaused; } + /** - * Embedded interface class(abstract) to listen for the moment when when the GL thread holding the #{@link JmeSurfaceView} - * joins the UI thread , after asynchronous rendering. - * @see JmeSurfaceView#setOnRendererCompleted(OnRendererCompleted). - */ - public interface OnRendererCompleted{ - void onRenderCompletion(LegacyApplication application); - } - /** - * sets the listener for the completion of rendering , ie :: when the GL thread holding the #{@link JmeSurfaceView} + * sets the listener for the completion of rendering , ie : when the GL thread holding the #{@link JmeSurfaceView} * joins the UI thread , after asynchronous rendering. * @param onRendererCompleted an instance of the interface #{@link OnRendererCompleted}. */ public void setOnRendererCompleted(OnRendererCompleted onRendererCompleted) { this.onRendererCompleted = onRendererCompleted; } - /** - * Embedded interface designed to listen to exceptions & fire when an exception is thrown. - * @see JmeSurfaceView#setOnExceptionThrown(OnExceptionThrown). - */ - public interface OnExceptionThrown{ - void Throw(Throwable e); - } + /** * sets the listener that will fire when an exception is thrown. * @param onExceptionThrown an instance of the interface #{@link OnExceptionThrown}. @@ -479,4 +533,5 @@ public interface OnExceptionThrown{ public void setOnExceptionThrown(OnExceptionThrown onExceptionThrown) { this.onExceptionThrown = onExceptionThrown; } + } \ No newline at end of file diff --git a/jme3-android/src/main/java/com/jme3/app/OnExceptionThrown.java b/jme3-android/src/main/java/com/jme3/app/OnExceptionThrown.java new file mode 100644 index 0000000000..b59d7c5576 --- /dev/null +++ b/jme3-android/src/main/java/com/jme3/app/OnExceptionThrown.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2009-2020 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package com.jme3.app; + +/** + * Embedded interface designed to listen to exceptions & fire when an exception is thrown. + * @see JmeSurfaceView#setOnExceptionThrown(OnExceptionThrown). + */ +public interface OnExceptionThrown { + /** + * Listens for a thrown exception or a thrown error. + * @param e the exception or the error that is throwable. + */ + void onExceptionThrown(Throwable e); +} diff --git a/jme3-android/src/main/java/com/jme3/app/OnRendererCompleted.java b/jme3-android/src/main/java/com/jme3/app/OnRendererCompleted.java new file mode 100644 index 0000000000..e0f9a5d8c3 --- /dev/null +++ b/jme3-android/src/main/java/com/jme3/app/OnRendererCompleted.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2009-2020 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT OWNER 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. + */ +package com.jme3.app; + +import com.jme3.system.AppSettings; + +/** + * Embedded interface class(abstract) to listen for the moment when when the GL thread holding the #{@link JmeSurfaceView} + * joins the UI thread , after asynchronous rendering. + * @see JmeSurfaceView#setOnRendererCompleted(OnRendererCompleted). + */ +public interface OnRendererCompleted { + /** + * Listens for the the moment when when the GL thread holding the #{@link JmeSurfaceView} + * joins the UI thread , after asynchronous rendering. + * @param application the current jme game instance. + * @param appSettings the current window settings of the running jme game. + */ + void onRenderCompletion(LegacyApplication application , AppSettings appSettings); +} From 016e60c612e32a6d310b5065f0be9234b086bf30 Mon Sep 17 00:00:00 2001 From: Scrappers Date: Fri, 2 Apr 2021 14:26:27 -0500 Subject: [PATCH 5/7] Moved the class files into an independent package --- .../java/com/jme3/app/{ => jmeSurfaceView}/JmeSurfaceView.java | 3 ++- .../com/jme3/app/{ => jmeSurfaceView}/OnExceptionThrown.java | 2 +- .../com/jme3/app/{ => jmeSurfaceView}/OnRendererCompleted.java | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) rename jme3-android/src/main/java/com/jme3/app/{ => jmeSurfaceView}/JmeSurfaceView.java (99%) rename jme3-android/src/main/java/com/jme3/app/{ => jmeSurfaceView}/OnExceptionThrown.java (98%) rename jme3-android/src/main/java/com/jme3/app/{ => jmeSurfaceView}/OnRendererCompleted.java (96%) diff --git a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java similarity index 99% rename from jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java rename to jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java index ed2b81b6a2..552a67865e 100644 --- a/jme3-android/src/main/java/com/jme3/app/JmeSurfaceView.java +++ b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.app; +package com.jme3.app.jmeSurfaceView; import android.app.Activity; import android.app.AlertDialog; @@ -41,6 +41,7 @@ import android.widget.RelativeLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.jme3.app.LegacyApplication; import com.jme3.audio.AudioRenderer; import com.jme3.input.JoyInput; import com.jme3.input.android.AndroidSensorJoyInput; diff --git a/jme3-android/src/main/java/com/jme3/app/OnExceptionThrown.java b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnExceptionThrown.java similarity index 98% rename from jme3-android/src/main/java/com/jme3/app/OnExceptionThrown.java rename to jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnExceptionThrown.java index b59d7c5576..fe11b5fd4b 100644 --- a/jme3-android/src/main/java/com/jme3/app/OnExceptionThrown.java +++ b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnExceptionThrown.java @@ -29,7 +29,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.app; +package com.jme3.app.jmeSurfaceView; /** * Embedded interface designed to listen to exceptions & fire when an exception is thrown. diff --git a/jme3-android/src/main/java/com/jme3/app/OnRendererCompleted.java b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnRendererCompleted.java similarity index 96% rename from jme3-android/src/main/java/com/jme3/app/OnRendererCompleted.java rename to jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnRendererCompleted.java index e0f9a5d8c3..10c9681f85 100644 --- a/jme3-android/src/main/java/com/jme3/app/OnRendererCompleted.java +++ b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnRendererCompleted.java @@ -29,8 +29,9 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.jme3.app; +package com.jme3.app.jmeSurfaceView; +import com.jme3.app.LegacyApplication; import com.jme3.system.AppSettings; /** From 2e46ada014c6eb1c7c717328773f11e404ea2e7b Mon Sep 17 00:00:00 2001 From: Scrappers Date: Fri, 2 Apr 2021 16:59:55 -0500 Subject: [PATCH 6/7] Handled the user delay for zero & negative numbers --- .../java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java index 552a67865e..f53c9cbbc3 100644 --- a/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java +++ b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java @@ -104,10 +104,11 @@ public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, in /** * starts the jmeRenderer on a GlSurfaceView attached to a RelativeLayout. * @param delayMillis delay of the appearance of jme game on the screen , this doesn't delay the renderer though. - * @apiNote use #{@link JmeSurfaceView#NO_DELAY} to disable the delay. + * @apiNote use #{@link JmeSurfaceView#NO_DELAY} to disable the delay , + * any values less than 1ms#{@link JmeSurfaceView#NO_DELAY} would be ignored & the delay would be disabled. */ public void startRenderer(int delayMillis) { - this.delayMillis = delayMillis; + this.delayMillis = Math.max(NO_DELAY , delayMillis); if (legacyApplication != null) { try { /*initialize App Settings & start the Game*/ From 6a4459fc2dcb0a3905ec85f59cf6835ca8efefe5 Mon Sep 17 00:00:00 2001 From: Scrappers Date: Tue, 6 Apr 2021 00:25:33 -0500 Subject: [PATCH 7/7] Cleaning up 2 --- .../app/jmeSurfaceView/JmeSurfaceView.java | 40 +++++++++---------- .../jmeSurfaceView/OnRendererCompleted.java | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java index f53c9cbbc3..687e67a594 100644 --- a/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java +++ b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/JmeSurfaceView.java @@ -63,7 +63,7 @@ * * @author pavl_g. */ -public class JmeSurfaceView extends RelativeLayout implements SystemListener , DialogInterface.OnClickListener { +public class JmeSurfaceView extends RelativeLayout implements SystemListener, DialogInterface.OnClickListener { /*using #{@link LegacyApplication} instead of #{@link SimpleApplication} to include all classes extends LegacyApplication*/ private LegacyApplication legacyApplication; @@ -108,13 +108,13 @@ public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, in * any values less than 1ms#{@link JmeSurfaceView#NO_DELAY} would be ignored & the delay would be disabled. */ public void startRenderer(int delayMillis) { - this.delayMillis = Math.max(NO_DELAY , delayMillis); + this.delayMillis = Math.max(NO_DELAY, delayMillis); if (legacyApplication != null) { try { /*initialize App Settings & start the Game*/ appSettings = new AppSettings(true); appSettings.setAudioRenderer(audioRendererType); - appSettings.setResolution(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height); + appSettings.setResolution(JmeSurfaceView.this.getLayoutParams().width, JmeSurfaceView.this.getLayoutParams().height); appSettings.setAlphaBits(eglAlphaBits); appSettings.setDepthBits(eglDepthBits); appSettings.setSamples(eglSamples); @@ -135,12 +135,12 @@ public void startRenderer(int delayMillis) { /*set JME system Listener to initialize game , update , requestClose & destroy on closure*/ oglesContext.setSystemListener(JmeSurfaceView.this); /* set the glSurfaceView to fit the widget */ - glSurfaceView.setLayoutParams(new LayoutParams(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height)); + glSurfaceView.setLayoutParams(new LayoutParams(JmeSurfaceView.this.getLayoutParams().width, JmeSurfaceView.this.getLayoutParams().height)); /*post delay the renderer join into the UI thread*/ - handler.postDelayed(new RendererThread() , delayMillis); + handler.postDelayed(new RendererThread(), delayMillis); } catch (Exception e) { - jmeSurfaceViewLogger.log(Level.WARNING , e.getMessage()); - showErrorDialog(e , e.getMessage()); + jmeSurfaceViewLogger.log(Level.WARNING, e.getMessage()); + showErrorDialog(e, e.getMessage()); if (onExceptionThrown != null) { onExceptionThrown.onExceptionThrown(e); } @@ -161,7 +161,7 @@ private class RendererThread implements Runnable { public void run() { /*jme Renderer joins the UIThread at that point*/ JmeSurfaceView.this.addView(glSurfaceView); - jmeSurfaceViewLogger.log(Level.CONFIG , "JmeSurfaceView's joined the UI thread......."); + jmeSurfaceViewLogger.log(Level.CONFIG, "JmeSurfaceView's joined the UI thread......."); } } @@ -170,14 +170,14 @@ public void initialize() { if (legacyApplication != null) { legacyApplication.initialize(); /*log for display*/ - jmeSurfaceViewLogger.log(Level.INFO , "JmeGame started in GLThread Asynchronously......."); + jmeSurfaceViewLogger.log(Level.INFO, "JmeGame started in GLThread Asynchronously......."); } } @Override - public void reshape(int width , int height) { + public void reshape(int width, int height) { if (legacyApplication != null) { - legacyApplication.reshape(width , height); + legacyApplication.reshape(width, height); } } @@ -192,9 +192,9 @@ public void update() { int timeToPlay = synthesizedTime.addAndGet(1); if (timeToPlay == (delayMillis>100 ? (delayMillis-TOLERANCE_TIMER) : delayMillis)) { ((Activity)getContext()).runOnUiThread(() -> { - jmeSurfaceViewLogger.log(Level.INFO,"SplashScreen Dismissed , User Delay completed with 0 errors......."); + jmeSurfaceViewLogger.log(Level.INFO, "SplashScreen Dismissed, User Delay completed with 0 errors......."); if (onRendererCompleted != null) { - onRendererCompleted.onRenderCompletion(legacyApplication , legacyApplication.getContext().getSettings()); + onRendererCompleted.onRenderCompletion(legacyApplication, legacyApplication.getContext().getSettings()); } }); } @@ -254,9 +254,9 @@ public void loseFocus() { } @Override - public void handleError(String errorMsg , Throwable throwable) { - jmeSurfaceViewLogger.log(Level.WARNING , throwable.getMessage()); - showErrorDialog(throwable , throwable.getMessage()); + public void handleError(String errorMsg, Throwable throwable) { + jmeSurfaceViewLogger.log(Level.WARNING, throwable.getMessage()); + showErrorDialog(throwable, throwable.getMessage()); if (onExceptionThrown != null) { onExceptionThrown.onExceptionThrown(throwable); } @@ -275,20 +275,20 @@ public void destroy() { * @param throwable the throwable stack. * @param message the string message. */ - protected void showErrorDialog(Throwable throwable , String message) { + protected void showErrorDialog(Throwable throwable, String message) { ((Activity)getContext()).runOnUiThread(() -> { AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create(); alertDialog.setTitle(new StringBuffer(String.valueOf(throwable))); alertDialog.setMessage(message); alertDialog.setCancelable(true); - alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE , "EXIT" , this); - alertDialog.setButton(DialogInterface.BUTTON_POSITIVE , "DISMISS", this); + alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "EXIT", this); + alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "DISMISS", this); alertDialog.show(); }); } @Override - public void onClick(DialogInterface dialog , int which) { + public void onClick(DialogInterface dialog, int which) { switch (which) { case DialogInterface.BUTTON_NEGATIVE: dialog.dismiss(); diff --git a/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnRendererCompleted.java b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnRendererCompleted.java index 10c9681f85..369c32e447 100644 --- a/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnRendererCompleted.java +++ b/jme3-android/src/main/java/com/jme3/app/jmeSurfaceView/OnRendererCompleted.java @@ -46,5 +46,5 @@ public interface OnRendererCompleted { * @param application the current jme game instance. * @param appSettings the current window settings of the running jme game. */ - void onRenderCompletion(LegacyApplication application , AppSettings appSettings); + void onRenderCompletion(LegacyApplication application, AppSettings appSettings); }