Skip to content

Commit 904b899

Browse files
authored
Add isPaused() and setPaused() methods to LegacyApplication
This PR introduces getter and setter methods for the `paused` state in the `LegacyApplication` class. This allows external control and querying of the application's paused status, enhancing flexibility for game state management, especially when the application loses/gains focus. Code Refinements: Minor optimizations and robustness improvements have been implemented. Enhancing the Javadoc documentation across the entire class.
1 parent 9a10591 commit 904b899

1 file changed

Lines changed: 95 additions & 66 deletions

File tree

jme3-core/src/main/java/com/jme3/app/LegacyApplication.java

Lines changed: 95 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2022 jMonkeyEngine
2+
* Copyright (c) 2009-2025 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,7 @@
3737
import com.jme3.audio.AudioContext;
3838
import com.jme3.audio.AudioRenderer;
3939
import com.jme3.audio.Listener;
40+
import com.jme3.input.Input;
4041
import com.jme3.input.InputManager;
4142
import com.jme3.input.JoyInput;
4243
import com.jme3.input.KeyInput;
@@ -58,6 +59,7 @@
5859
import com.jme3.system.SystemListener;
5960
import com.jme3.system.Timer;
6061
import com.jme3.util.res.Resources;
62+
6163
import java.net.MalformedURLException;
6264
import java.net.URL;
6365
import java.util.concurrent.Callable;
@@ -70,7 +72,7 @@
7072
* The <code>LegacyApplication</code> class represents an instance of a
7173
* real-time 3D rendering jME application.
7274
*
73-
* An <code>LegacyApplication</code> provides all the tools that are commonly used in jME3
75+
* A <code>LegacyApplication</code> provides all the tools that are commonly used in jME3
7476
* applications.
7577
*
7678
* jME3 applications *SHOULD NOT EXTEND* this class but extend {@link com.jme3.app.SimpleApplication} instead.
@@ -80,40 +82,45 @@ public class LegacyApplication implements Application, SystemListener {
8082

8183
private static final Logger logger = Logger.getLogger(LegacyApplication.class.getName());
8284

85+
// Core jME3 components
8386
protected AssetManager assetManager;
84-
8587
protected AudioRenderer audioRenderer;
8688
protected Renderer renderer;
8789
protected RenderManager renderManager;
90+
91+
// Viewports
8892
protected ViewPort viewPort;
8993
protected ViewPort guiViewPort;
9094

95+
// System components
9196
protected JmeContext context;
9297
protected AppSettings settings;
93-
protected Timer timer = new NanoTimer();
98+
protected Timer timer = new NanoTimer(); // Default timer
9499
protected Camera cam;
95100
protected Listener listener;
96101

102+
// Input management
97103
protected boolean inputEnabled = true;
98104
protected LostFocusBehavior lostFocusBehavior = LostFocusBehavior.ThrottleOnLostFocus;
99-
protected float speed = 1f;
100-
protected boolean paused = false;
101105
protected MouseInput mouseInput;
102106
protected KeyInput keyInput;
103107
protected JoyInput joyInput;
104108
protected TouchInput touchInput;
105109
protected InputManager inputManager;
106-
protected AppStateManager stateManager;
107110

111+
// Application state and performance
112+
protected float speed = 1f;
113+
protected boolean paused = false;
114+
protected AppStateManager stateManager;
108115
protected AppProfiler prof;
109116

117+
// Task queue for main thread operations
110118
private final ConcurrentLinkedQueue<AppTask<?>> taskQueue = new ConcurrentLinkedQueue<>();
111119

112120
/**
113121
* Create a new instance of <code>LegacyApplication</code>.
114122
*/
115123
public LegacyApplication() {
116-
this((AppState[]) null);
117124
}
118125

119126
/**
@@ -200,13 +207,20 @@ public void setPauseOnLostFocus(boolean pauseOnLostFocus) {
200207
@Deprecated
201208
public void setAssetManager(AssetManager assetManager) {
202209
if (this.assetManager != null) {
203-
throw new IllegalStateException("Can only set asset manager" + " before initialization.");
210+
throw new IllegalStateException("Can only set asset manager before initialization.");
204211
}
205212

206213
this.assetManager = assetManager;
207214
}
208215

216+
/**
217+
* Initializes the asset manager based on settings or platform defaults.
218+
*/
209219
private void initAssetManager() {
220+
if (assetManager != null) {
221+
return; // Already initialized or set externally
222+
}
223+
210224
URL assetCfgUrl = null;
211225

212226
if (settings != null) {
@@ -220,11 +234,7 @@ private void initAssetManager() {
220234
if (assetCfgUrl == null) {
221235
assetCfgUrl = Resources.getResource(assetCfg);
222236
if (assetCfgUrl == null) {
223-
logger.log(
224-
Level.SEVERE,
225-
"Unable to access AssetConfigURL in asset config:{0}",
226-
assetCfg
227-
);
237+
logger.log(Level.SEVERE, "Unable to access AssetConfigURL in asset config: {0}", assetCfg);
228238
return;
229239
}
230240
}
@@ -233,9 +243,7 @@ private void initAssetManager() {
233243
if (assetCfgUrl == null) {
234244
assetCfgUrl = JmeSystem.getPlatformAssetConfigURL();
235245
}
236-
if (assetManager == null) {
237-
assetManager = JmeSystem.newAssetManager(assetCfgUrl);
238-
}
246+
assetManager = JmeSystem.newAssetManager(assetCfgUrl);
239247
}
240248

241249
/**
@@ -251,17 +259,16 @@ private void initAssetManager() {
251259
@Override
252260
public void setSettings(AppSettings settings) {
253261
this.settings = settings;
254-
if (context != null && settings.useInput() != inputEnabled) {
255-
// may need to create or destroy input based
256-
// on settings change
257-
inputEnabled = !inputEnabled;
262+
boolean newUseInput = settings.useInput();
263+
if (context != null && newUseInput != inputEnabled) {
264+
inputEnabled = newUseInput;
258265
if (inputEnabled) {
259266
initInput();
260267
} else {
261268
destroyInput();
262269
}
263270
} else {
264-
inputEnabled = settings.useInput();
271+
inputEnabled = newUseInput;
265272
}
266273
}
267274

@@ -288,6 +295,9 @@ public Timer getTimer() {
288295
return timer;
289296
}
290297

298+
/**
299+
* Initializes display-related components from the context.
300+
*/
291301
private void initDisplay() {
292302
// acquire important objects
293303
// from the context
@@ -301,6 +311,9 @@ private void initDisplay() {
301311
renderer = context.getRenderer();
302312
}
303313

314+
/**
315+
* Initializes audio renderer and listener if audio is enabled in settings.
316+
*/
304317
private void initAudio() {
305318
if (settings.getAudioRenderer() != null && context.getType() != Type.Headless) {
306319
audioRenderer = JmeSystem.newAudioRenderer(settings);
@@ -325,7 +338,6 @@ private void initCamera() {
325338
cam.lookAt(new Vector3f(0f, 0f, 0f), Vector3f.UNIT_Y);
326339

327340
renderManager = new RenderManager(renderer);
328-
//Remy - 09/14/2010 set the timer in the renderManager
329341
renderManager.setTimer(timer);
330342

331343
if (prof != null) {
@@ -342,36 +354,37 @@ private void initCamera() {
342354
}
343355

344356
/**
345-
* Initializes mouse and keyboard input. Also
346-
* initializes joystick input if joysticks are enabled in the
347-
* AppSettings.
357+
* Initializes mouse, keyboard, and optionally joystick/touch input based on context and settings.
348358
*/
349359
private void initInput() {
360+
// Retrieve and initialize all available input devices
350361
mouseInput = context.getMouseInput();
351-
if (mouseInput != null) {
352-
mouseInput.initialize();
353-
}
362+
initializeInputDevice(mouseInput);
354363

355364
keyInput = context.getKeyInput();
356-
if (keyInput != null) {
357-
keyInput.initialize();
358-
}
365+
initializeInputDevice(keyInput);
359366

360367
touchInput = context.getTouchInput();
361-
if (touchInput != null) {
362-
touchInput.initialize();
363-
}
368+
initializeInputDevice(touchInput);
364369

365370
if (settings.useJoysticks()) {
366371
joyInput = context.getJoyInput();
367-
if (joyInput != null) {
368-
joyInput.initialize();
369-
}
372+
initializeInputDevice(joyInput);
370373
}
371374

375+
// Create the InputManager with the initialized devices
372376
inputManager = new InputManager(mouseInput, keyInput, joyInput, touchInput);
373377
}
374378

379+
private void initializeInputDevice(Input input) {
380+
if (input != null) {
381+
input.initialize();
382+
}
383+
}
384+
385+
/**
386+
* Initializes the application state manager.
387+
*/
375388
private void initStateManager() {
376389
stateManager = new AppStateManager(this);
377390

@@ -501,10 +514,12 @@ public void start(JmeContext.Type contextType, boolean waitFor) {
501514
}
502515

503516
if (settings == null) {
517+
logger.log(Level.INFO, "AppSettings not set, creating default settings.");
504518
settings = new AppSettings(true);
505519
}
506520

507-
logger.log(Level.FINE, "Starting application: {0}", getClass().getName());
521+
logger.log(Level.FINE, "Starting application: {0} with context type {1}",
522+
new Object[]{getClass().getName(), contextType});
508523
context = JmeSystem.newContext(settings, contextType);
509524
context.setSystemListener(this);
510525
context.create(waitFor);
@@ -554,12 +569,11 @@ public void createCanvas() {
554569
}
555570

556571
if (settings == null) {
572+
logger.log(Level.INFO, "AppSettings not set, creating default settings.");
557573
settings = new AppSettings(true);
558574
}
559575

560-
if (logger.isLoggable(Level.FINE)) {
561-
logger.log(Level.FINE, "Starting application: {0}", getClass().getName());
562-
}
576+
logger.log(Level.FINE, "Starting application as canvas: {0}", getClass().getName());
563577
context = JmeSystem.newContext(settings, JmeContext.Type.Canvas);
564578
context.setSystemListener(this);
565579
}
@@ -657,10 +671,7 @@ public void stop(boolean waitFor) {
657671
*/
658672
@Override
659673
public void initialize() {
660-
if (assetManager == null) {
661-
initAssetManager();
662-
}
663-
674+
initAssetManager();
664675
initDisplay();
665676
initCamera();
666677

@@ -669,10 +680,7 @@ public void initialize() {
669680
}
670681
initAudio();
671682

672-
// update timer so that the next delta is not too large
673-
// timer.update();
674683
timer.reset();
675-
// user code here
676684
}
677685

678686
/**
@@ -766,7 +774,6 @@ public <V> Future<V> enqueue(Callable<V> callable) {
766774
* @param runnable The runnable to run in the main jME3 thread
767775
*/
768776
@Override
769-
@SuppressWarnings("unchecked")
770777
public void enqueue(Runnable runnable) {
771778
enqueue(new RunnableWrapper(runnable));
772779
}
@@ -797,10 +804,12 @@ public void update() {
797804
}
798805
runQueuedTasks();
799806

807+
// Skip further updates if paused or speed is zero
800808
if (speed == 0 || paused) {
801809
return;
802810
}
803811

812+
// Update the application's timer
804813
timer.update();
805814

806815
if (inputEnabled) {
@@ -819,24 +828,21 @@ public void update() {
819828
// user code here
820829
}
821830

831+
/**
832+
* Destroys all initialized input devices.
833+
*/
822834
protected void destroyInput() {
823-
if (mouseInput != null) {
824-
mouseInput.destroy();
825-
}
826-
827-
if (keyInput != null) {
828-
keyInput.destroy();
829-
}
830-
831-
if (joyInput != null) {
832-
joyInput.destroy();
833-
}
835+
destroyInputDevice(mouseInput);
836+
destroyInputDevice(keyInput);
837+
destroyInputDevice(joyInput);
838+
destroyInputDevice(touchInput);
839+
inputManager = null;
840+
}
834841

835-
if (touchInput != null) {
836-
touchInput.destroy();
842+
private void destroyInputDevice(Input input) {
843+
if (input != null) {
844+
input.destroy();
837845
}
838-
839-
inputManager = null;
840846
}
841847

842848
/**
@@ -853,6 +859,7 @@ public void destroy() {
853859
}
854860

855861
timer.reset();
862+
logger.log(Level.FINE, "Application destroyed: {0}", getClass().getName());
856863
}
857864

858865
/**
@@ -864,12 +871,15 @@ public ViewPort getGuiViewPort() {
864871
return guiViewPort;
865872
}
866873

874+
/**
875+
* @return The main scene viewport.
876+
*/
867877
@Override
868878
public ViewPort getViewPort() {
869879
return viewPort;
870880
}
871881

872-
private class RunnableWrapper implements Callable {
882+
private static class RunnableWrapper implements Callable<Object> {
873883

874884
private final Runnable runnable;
875885

@@ -905,4 +915,23 @@ public Displays getDisplays() {
905915
public int getPrimaryDisplay() {
906916
return context.getPrimaryDisplay();
907917
}
918+
919+
/**
920+
* Returns true if the application is currently paused.
921+
*
922+
* @return true if the application is paused, false otherwise.
923+
*/
924+
public boolean isPaused() {
925+
return paused;
926+
}
927+
928+
/**
929+
* Sets the paused state of the application.
930+
* If true, the application's update loop will be skipped.
931+
*
932+
* @param paused True to pause the application, false to unpause.
933+
*/
934+
public void setPaused(boolean paused) {
935+
this.paused = paused;
936+
}
908937
}

0 commit comments

Comments
 (0)