aboutsummaryrefslogtreecommitdiff
path: root/engine/src/core/com/jme3/app/SimpleApplication.java
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/core/com/jme3/app/SimpleApplication.java')
-rw-r--r--engine/src/core/com/jme3/app/SimpleApplication.java277
1 files changed, 277 insertions, 0 deletions
diff --git a/engine/src/core/com/jme3/app/SimpleApplication.java b/engine/src/core/com/jme3/app/SimpleApplication.java
new file mode 100644
index 0000000..c79ce83
--- /dev/null
+++ b/engine/src/core/com/jme3/app/SimpleApplication.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2009-2010 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.app.state.AppState;
+import com.jme3.font.BitmapFont;
+import com.jme3.font.BitmapText;
+import com.jme3.input.FlyByCamera;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.ActionListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.queue.RenderQueue.Bucket;
+import com.jme3.scene.Node;
+import com.jme3.scene.Spatial.CullHint;
+import com.jme3.system.AppSettings;
+import com.jme3.system.JmeContext.Type;
+import com.jme3.system.JmeSystem;
+import com.jme3.util.BufferUtils;
+
+/**
+ * <code>SimpleApplication</code> extends the {@link com.jme3.app.Application}
+ * class to provide default functionality like a first-person camera,
+ * and an accessible root node that is updated and rendered regularly.
+ * Additionally, <code>SimpleApplication</code> will display a statistics view
+ * using the {@link com.jme3.app.StatsView} class. It will display
+ * the current frames-per-second value on-screen in addition to the statistics.
+ * Several keys have special functionality in <code>SimpleApplication</code>:<br/>
+ *
+ * <table>
+ * <tr><td>Esc</td><td>- Close the application</td></tr>
+ * <tr><td>C</td><td>- Display the camera position and rotation in the console.</td></tr>
+ * <tr><td>M</td><td>- Display memory usage in the console.</td></tr>
+ * </table>
+ */
+public abstract class SimpleApplication extends Application {
+
+ public static final String INPUT_MAPPING_EXIT = "SIMPLEAPP_Exit";
+ public static final String INPUT_MAPPING_CAMERA_POS = DebugKeysAppState.INPUT_MAPPING_CAMERA_POS;
+ public static final String INPUT_MAPPING_MEMORY = DebugKeysAppState.INPUT_MAPPING_MEMORY;
+ public static final String INPUT_MAPPING_HIDE_STATS = "SIMPLEAPP_HideStats";
+
+ protected Node rootNode = new Node("Root Node");
+ protected Node guiNode = new Node("Gui Node");
+ protected BitmapText fpsText;
+ protected BitmapFont guiFont;
+ protected FlyByCamera flyCam;
+ protected boolean showSettings = true;
+ private AppActionListener actionListener = new AppActionListener();
+
+ private class AppActionListener implements ActionListener {
+
+ public void onAction(String name, boolean value, float tpf) {
+ if (!value) {
+ return;
+ }
+
+ if (name.equals(INPUT_MAPPING_EXIT)) {
+ stop();
+ }else if (name.equals(INPUT_MAPPING_HIDE_STATS)){
+ if (stateManager.getState(StatsAppState.class) != null) {
+ stateManager.getState(StatsAppState.class).toggleStats();
+ }
+ }
+ }
+ }
+
+ public SimpleApplication() {
+ this( new StatsAppState(), new FlyCamAppState(), new DebugKeysAppState() );
+ }
+
+ public SimpleApplication( AppState... initialStates ) {
+ super();
+
+ if (initialStates != null) {
+ for (AppState a : initialStates) {
+ if (a != null) {
+ stateManager.attach(a);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void start() {
+ // set some default settings in-case
+ // settings dialog is not shown
+ boolean loadSettings = false;
+ if (settings == null) {
+ setSettings(new AppSettings(true));
+ loadSettings = true;
+ }
+
+ // show settings dialog
+ if (showSettings) {
+ if (!JmeSystem.showSettingsDialog(settings, loadSettings)) {
+ return;
+ }
+ }
+ //re-setting settings they can have been merged from the registry.
+ setSettings(settings);
+ super.start();
+ }
+
+ /**
+ * Retrieves flyCam
+ * @return flyCam Camera object
+ *
+ */
+ public FlyByCamera getFlyByCamera() {
+ return flyCam;
+ }
+
+ /**
+ * Retrieves guiNode
+ * @return guiNode Node object
+ *
+ */
+ public Node getGuiNode() {
+ return guiNode;
+ }
+
+ /**
+ * Retrieves rootNode
+ * @return rootNode Node object
+ *
+ */
+ public Node getRootNode() {
+ return rootNode;
+ }
+
+ public boolean isShowSettings() {
+ return showSettings;
+ }
+
+ /**
+ * Toggles settings window to display at start-up
+ * @param showSettings Sets true/false
+ *
+ */
+ public void setShowSettings(boolean showSettings) {
+ this.showSettings = showSettings;
+ }
+
+ @Override
+ public void initialize() {
+ super.initialize();
+
+ // Several things rely on having this
+ guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
+
+ guiNode.setQueueBucket(Bucket.Gui);
+ guiNode.setCullHint(CullHint.Never);
+ viewPort.attachScene(rootNode);
+ guiViewPort.attachScene(guiNode);
+
+ if (inputManager != null) {
+
+ // We have to special-case the FlyCamAppState because too
+ // many SimpleApplication subclasses expect it to exist in
+ // simpleInit(). But at least it only gets initialized if
+ // the app state is added.
+ if (stateManager.getState(FlyCamAppState.class) != null) {
+ flyCam = new FlyByCamera(cam);
+ flyCam.setMoveSpeed(1f); // odd to set this here but it did it before
+ stateManager.getState(FlyCamAppState.class).setCamera( flyCam );
+ }
+
+ if (context.getType() == Type.Display) {
+ inputManager.addMapping(INPUT_MAPPING_EXIT, new KeyTrigger(KeyInput.KEY_ESCAPE));
+ }
+
+ if (stateManager.getState(StatsAppState.class) != null) {
+ inputManager.addMapping(INPUT_MAPPING_HIDE_STATS, new KeyTrigger(KeyInput.KEY_F5));
+ inputManager.addListener(actionListener, INPUT_MAPPING_HIDE_STATS);
+ }
+
+ inputManager.addListener(actionListener, INPUT_MAPPING_EXIT);
+ }
+
+ if (stateManager.getState(StatsAppState.class) != null) {
+ // Some of the tests rely on having access to fpsText
+ // for quick display. Maybe a different way would be better.
+ stateManager.getState(StatsAppState.class).setFont(guiFont);
+ fpsText = stateManager.getState(StatsAppState.class).getFpsText();
+ }
+
+ // call user code
+ simpleInitApp();
+ }
+
+ @Override
+ public void update() {
+ super.update(); // makes sure to execute AppTasks
+ if (speed == 0 || paused) {
+ return;
+ }
+
+ float tpf = timer.getTimePerFrame() * speed;
+
+ // update states
+ stateManager.update(tpf);
+
+ // simple update and root node
+ simpleUpdate(tpf);
+
+ rootNode.updateLogicalState(tpf);
+ guiNode.updateLogicalState(tpf);
+
+ rootNode.updateGeometricState();
+ guiNode.updateGeometricState();
+
+ // Moving this here to make sure it is always done.
+ // Now the sets are cleared every frame (guaranteed)
+ // and more than one viewer can access the data. This
+ // used to be cleared by StatsView but then only StatsView
+ // could get accurate counts.
+ renderer.getStatistics().clearFrame();
+
+ // render states
+ stateManager.render(renderManager);
+ renderManager.render(tpf, context.isRenderable());
+ simpleRender(renderManager);
+ stateManager.postRender();
+ }
+
+ public void setDisplayFps(boolean show) {
+ if (stateManager.getState(StatsAppState.class) != null) {
+ stateManager.getState(StatsAppState.class).setDisplayFps(show);
+ }
+ }
+
+ public void setDisplayStatView(boolean show) {
+ if (stateManager.getState(StatsAppState.class) != null) {
+ stateManager.getState(StatsAppState.class).setDisplayStatView(show);
+ }
+ }
+
+ public abstract void simpleInitApp();
+
+ public void simpleUpdate(float tpf) {
+ }
+
+ public void simpleRender(RenderManager rm) {
+ }
+}