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
3737import com .jme3 .audio .AudioContext ;
3838import com .jme3 .audio .AudioRenderer ;
3939import com .jme3 .audio .Listener ;
40+ import com .jme3 .input .Input ;
4041import com .jme3 .input .InputManager ;
4142import com .jme3 .input .JoyInput ;
4243import com .jme3 .input .KeyInput ;
5859import com .jme3 .system .SystemListener ;
5960import com .jme3 .system .Timer ;
6061import com .jme3 .util .res .Resources ;
62+
6163import java .net .MalformedURLException ;
6264import java .net .URL ;
6365import java .util .concurrent .Callable ;
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