Skip to content

Commit 6ee6637

Browse files
committed
added life cycle methods observing, code improvements
1 parent 838682e commit 6ee6637

File tree

1 file changed

+127
-86
lines changed
  • SuperiorPlugin/src/main/java/com/scrappers/superiorExtendedEngine/jmeSurfaceView

1 file changed

+127
-86
lines changed

SuperiorPlugin/src/main/java/com/scrappers/superiorExtendedEngine/jmeSurfaceView/JmeSurfaceView.java

+127-86
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
import android.os.Handler;
99
import android.util.AttributeSet;
1010
import android.widget.RelativeLayout;
11-
11+
import androidx.annotation.NonNull;
12+
import androidx.annotation.Nullable;
13+
import androidx.lifecycle.Lifecycle;
14+
import androidx.lifecycle.LifecycleEventObserver;
15+
import androidx.lifecycle.LifecycleOwner;
1216
import com.jme3.app.LegacyApplication;
1317
import com.jme3.audio.AudioRenderer;
1418
import com.jme3.input.JoyInput;
@@ -17,14 +21,10 @@
1721
import com.jme3.system.SystemListener;
1822
import com.jme3.system.android.JmeAndroidSystem;
1923
import com.jme3.system.android.OGLESContext;
20-
2124
import java.util.concurrent.atomic.AtomicInteger;
2225
import java.util.logging.Level;
2326
import java.util.logging.Logger;
2427

25-
import androidx.annotation.NonNull;
26-
import androidx.annotation.Nullable;
27-
2828
/**
2929
* <b>A RelativeLayout Class Holder that holds a #{{@link GLSurfaceView}} using #{{@link OGLESContext}} as a renderer to render
3030
* a JME game on an android view for custom xmL designs.</b>
@@ -34,7 +34,7 @@
3434
* an image or even play a preface game music of choice.
3535
* @author pavl_g.
3636
*/
37-
public class JmeSurfaceView extends RelativeLayout implements SystemListener , DialogInterface.OnClickListener {
37+
public class JmeSurfaceView extends RelativeLayout implements SystemListener, DialogInterface.OnClickListener, LifecycleEventObserver {
3838

3939
/*using #{@link LegacyApplication} instead of #{@link SimpleApplication} to include all classes extends LegacyApplication*/
4040
private LegacyApplication legacyApplication;
@@ -59,6 +59,7 @@ public class JmeSurfaceView extends RelativeLayout implements SystemListener , D
5959
public static final int NO_DELAY = 1;
6060
private int delayMillis = NO_DELAY;
6161
private static final int TOLERANCE_TIMER = 100;
62+
private boolean showErrorDialog = true;
6263

6364
public JmeSurfaceView(@NonNull Context context) {
6465
super(context);
@@ -80,45 +81,66 @@ public JmeSurfaceView(@NonNull Context context, @Nullable AttributeSet attrs, in
8081
*/
8182
public void startRenderer(int delayMillis) {
8283
this.delayMillis = Math.max(NO_DELAY , delayMillis);
83-
if (legacyApplication != null) {
84-
try {
85-
/*initialize App Settings & start the Game*/
86-
appSettings = new AppSettings(true);
87-
appSettings.setAudioRenderer(audioRendererType);
88-
appSettings.setResolution(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height);
89-
appSettings.setAlphaBits(eglAlphaBits);
90-
appSettings.setDepthBits(eglDepthBits);
91-
appSettings.setSamples(eglSamples);
92-
appSettings.setStencilBits(eglStencilBits);
93-
appSettings.setBitsPerPixel(eglBitsPerPixel);
94-
appSettings.setEmulateKeyboard(emulateKeyBoard);
95-
appSettings.setEmulateMouse(emulateMouse);
96-
appSettings.setUseJoysticks(useJoyStickEvents);
97-
legacyApplication.setSettings(appSettings);
98-
/*start jme game context*/
99-
legacyApplication.start();
100-
/*attach the game to JmE OpenGL.Renderer context */
101-
OGLESContext oglesContext = (OGLESContext) legacyApplication.getContext();
102-
/*create a glSurfaceView that will hold the renderer thread*/
103-
glSurfaceView = oglesContext.createView(JmeSurfaceView.this.getContext());
104-
/*set the current view as the system engine thread view for future uses*/
105-
JmeAndroidSystem.setView(JmeSurfaceView.this);
106-
/*set JME system Listener to initialize game , update , requestClose & destroy on closure*/
107-
oglesContext.setSystemListener(JmeSurfaceView.this);
108-
/* set the glSurfaceView to fit the widget */
109-
glSurfaceView.setLayoutParams(new LayoutParams(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height));
110-
/*post delay the renderer join into the UI thread*/
111-
handler.postDelayed(new RendererThread() , delayMillis);
112-
} catch (Exception e) {
113-
jmeSurfaceViewLogger.log(Level.WARNING , e.getMessage());
114-
showErrorDialog(e , e.getMessage());
115-
if (onExceptionThrown != null) {
116-
onExceptionThrown.onExceptionThrown(e);
117-
}
84+
if (legacyApplication == null) {
85+
throw new IllegalStateException("Cannot build a SurfaceView for a null app, make sure to use setLegacyApplication() to pass in your app !");
86+
}
87+
try {
88+
/*initialize App Settings & start the Game*/
89+
appSettings = new AppSettings(true);
90+
appSettings.setAudioRenderer(audioRendererType);
91+
appSettings.setResolution(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height);
92+
appSettings.setAlphaBits(eglAlphaBits);
93+
appSettings.setDepthBits(eglDepthBits);
94+
appSettings.setSamples(eglSamples);
95+
appSettings.setStencilBits(eglStencilBits);
96+
appSettings.setBitsPerPixel(eglBitsPerPixel);
97+
appSettings.setEmulateKeyboard(emulateKeyBoard);
98+
appSettings.setEmulateMouse(emulateMouse);
99+
appSettings.setUseJoysticks(useJoyStickEvents);
100+
legacyApplication.setSettings(appSettings);
101+
/*start jme game context*/
102+
legacyApplication.start();
103+
/*attach the game to JmE OpenGL.Renderer context */
104+
OGLESContext oglesContext = (OGLESContext) legacyApplication.getContext();
105+
/*create a glSurfaceView that will hold the renderer thread*/
106+
glSurfaceView = oglesContext.createView(JmeSurfaceView.this.getContext());
107+
/*set the current view as the system engine thread view for future uses*/
108+
JmeAndroidSystem.setView(JmeSurfaceView.this);
109+
/*set JME system Listener to initialize game , update , requestClose & destroy on closure*/
110+
oglesContext.setSystemListener(JmeSurfaceView.this);
111+
/* set the glSurfaceView to fit the widget */
112+
glSurfaceView.setLayoutParams(new LayoutParams(JmeSurfaceView.this.getLayoutParams().width , JmeSurfaceView.this.getLayoutParams().height));
113+
/*post delay the renderer join into the UI thread*/
114+
handler.postDelayed(new RendererThread() , delayMillis);
115+
} catch (Exception e) {
116+
jmeSurfaceViewLogger.log(Level.WARNING , e.getMessage());
117+
showErrorDialog(e , e.getMessage());
118+
if (onExceptionThrown != null) {
119+
onExceptionThrown.onExceptionThrown(e);
118120
}
119121
}
120122
}
121123

124+
/**
125+
* A state change observer to the current Activity life cycle.
126+
* @param source the life cycle source, aka the observable object.
127+
* @param event the fired event by the observable object, which is dispatched and sent to the observers.
128+
*/
129+
@Override
130+
public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
131+
switch (event){
132+
case ON_DESTROY:
133+
destroy();
134+
break;
135+
case ON_PAUSE:
136+
loseFocus();
137+
break;
138+
case ON_RESUME:
139+
gainFocus();
140+
break;
141+
}
142+
}
143+
122144
/**
123145
* Custom thread that delays the appearance of the display of jme game on the screen for the sake of initial frame pacing & splash screens.
124146
*/
@@ -132,36 +154,40 @@ private class RendererThread implements Runnable {
132154
public void run() {
133155
/*jme Renderer joins the UIThread at that point*/
134156
JmeSurfaceView.this.addView(glSurfaceView);
157+
//register this Ui Component as an observer to the context of jmeSurfaceView only if this context is a LifeCycleOwner
158+
if(getContext() instanceof LifecycleOwner) {
159+
((LifecycleOwner) getContext()).getLifecycle().addObserver(JmeSurfaceView.this);
160+
}
135161
jmeSurfaceViewLogger.log(Level.CONFIG , "JmeSurfaceView's joined the UI thread.......");
136162
}
137163
}
138164

139165
@Override
140166
public void initialize() {
141-
if (legacyApplication != null) {
142-
legacyApplication.initialize();
143-
/*log for display*/
144-
jmeSurfaceViewLogger.log(Level.INFO , "JmeGame started in GLThread Asynchronously.......");
167+
if (legacyApplication == null) {
168+
return;
145169
}
170+
legacyApplication.initialize();
171+
/*log for display*/
172+
jmeSurfaceViewLogger.log(Level.INFO , "JmeGame started in GLThread Asynchronously.......");
146173
}
147174

148175
@Override
149176
public void reshape(int width , int height) {
150-
if (legacyApplication != null) {
151-
legacyApplication.reshape(width , height);
177+
if (legacyApplication == null) {
178+
return;
152179
}
180+
legacyApplication.reshape(width , height);
153181
}
154182

155183
@Override
156184
public void update() {
157-
if (legacyApplication == null) {
185+
if (legacyApplication == null || glSurfaceView == null) {
158186
return;
159187
}
160-
if (glSurfaceView != null) {
161-
legacyApplication.update();
162-
}
188+
legacyApplication.update();
163189
int timeToPlay = synthesizedTime.addAndGet(1);
164-
if (timeToPlay == (delayMillis>100 ? (delayMillis-TOLERANCE_TIMER) : delayMillis)) {
190+
if (timeToPlay == (delayMillis > 100 ? (delayMillis - TOLERANCE_TIMER) : delayMillis)) {
165191
((Activity)getContext()).runOnUiThread(() -> {
166192
jmeSurfaceViewLogger.log(Level.INFO,"SplashScreen Dismissed , User Delay completed with 0 errors.......");
167193
if (onRendererCompleted != null) {
@@ -173,51 +199,56 @@ public void update() {
173199

174200
@Override
175201
public void requestClose(boolean esc) {
176-
if (legacyApplication != null) {
177-
legacyApplication.requestClose(esc);
202+
if (legacyApplication == null) {
203+
return;
178204
}
205+
legacyApplication.requestClose(esc);
179206
}
180207

181208
@Override
182209
public void gainFocus() {
183-
if (legacyApplication != null) {
184-
/*resume the audio*/
185-
AudioRenderer audioRenderer = legacyApplication.getAudioRenderer();
186-
if (audioRenderer != null) {
187-
audioRenderer.resumeAll();
188-
}
189-
/*resume the sensors (aka joysticks)*/
190-
if (legacyApplication.getContext() != null) {
191-
JoyInput joyInput = legacyApplication.getContext().getJoyInput();
192-
if (joyInput != null) {
193-
if (joyInput instanceof AndroidSensorJoyInput) {
194-
AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput;
195-
androidJoyInput.resumeSensors();
196-
}
210+
if (legacyApplication == null || glSurfaceView == null) {
211+
return;
212+
}
213+
glSurfaceView.onResume();
214+
/*resume the audio*/
215+
AudioRenderer audioRenderer = legacyApplication.getAudioRenderer();
216+
if (audioRenderer != null) {
217+
audioRenderer.resumeAll();
218+
}
219+
/*resume the sensors (aka joysticks)*/
220+
if (legacyApplication.getContext() != null) {
221+
JoyInput joyInput = legacyApplication.getContext().getJoyInput();
222+
if (joyInput != null) {
223+
if (joyInput instanceof AndroidSensorJoyInput) {
224+
AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput;
225+
androidJoyInput.resumeSensors();
197226
}
198-
legacyApplication.gainFocus();
199227
}
228+
legacyApplication.gainFocus();
200229
}
201230
setGLThreadPaused(false);
202231
}
203232

204233
@Override
205234
public void loseFocus() {
206-
if (legacyApplication != null) {
207-
/*pause the audio*/
208-
legacyApplication.loseFocus();
209-
AudioRenderer audioRenderer = legacyApplication.getAudioRenderer();
210-
if (audioRenderer != null) {
211-
audioRenderer.pauseAll();
212-
}
213-
/*pause the sensors (aka joysticks)*/
214-
if (legacyApplication.getContext() != null) {
215-
JoyInput joyInput = legacyApplication.getContext().getJoyInput();
216-
if (joyInput != null) {
217-
if (joyInput instanceof AndroidSensorJoyInput) {
218-
AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput;
219-
androidJoyInput.pauseSensors();
220-
}
235+
if (legacyApplication == null || glSurfaceView == null) {
236+
return;
237+
}
238+
glSurfaceView.onPause();
239+
/*pause the audio*/
240+
legacyApplication.loseFocus();
241+
AudioRenderer audioRenderer = legacyApplication.getAudioRenderer();
242+
if (audioRenderer != null) {
243+
audioRenderer.pauseAll();
244+
}
245+
/*pause the sensors (aka joysticks)*/
246+
if (legacyApplication.getContext() != null) {
247+
JoyInput joyInput = legacyApplication.getContext().getJoyInput();
248+
if (joyInput != null) {
249+
if (joyInput instanceof AndroidSensorJoyInput) {
250+
AndroidSensorJoyInput androidJoyInput = (AndroidSensorJoyInput) joyInput;
251+
androidJoyInput.pauseSensors();
221252
}
222253
}
223254
}
@@ -236,8 +267,7 @@ public void handleError(String errorMsg , Throwable throwable) {
236267
@Override
237268
public void destroy() {
238269
if (legacyApplication != null) {
239-
legacyApplication.stop(isGLThreadPaused());
240-
legacyApplication.destroy();
270+
legacyApplication.stop(!isGLThreadPaused());
241271
}
242272
}
243273

@@ -247,6 +277,9 @@ public void destroy() {
247277
* @param message the string message.
248278
*/
249279
protected void showErrorDialog(Throwable throwable , String message) {
280+
if(!isShowErrorDialog()){
281+
return;
282+
}
250283
((Activity)getContext()).runOnUiThread(() -> {
251284
AlertDialog alertDialog = new AlertDialog.Builder(getContext()).create();
252285
alertDialog.setTitle(new StringBuffer(String.valueOf(throwable)));
@@ -258,6 +291,14 @@ protected void showErrorDialog(Throwable throwable , String message) {
258291
});
259292
}
260293

294+
public void setShowErrorDialog(boolean showErrorDialog) {
295+
this.showErrorDialog = showErrorDialog;
296+
}
297+
298+
public boolean isShowErrorDialog() {
299+
return showErrorDialog;
300+
}
301+
261302
@Override
262303
public void onClick(DialogInterface dialog , int which) {
263304
switch (which) {

0 commit comments

Comments
 (0)