From 4c18bfaecb8ff6fc46ef1f27f35a282aa99de592 Mon Sep 17 00:00:00 2001 From: "PSp..om" Date: Fri, 17 Feb 2012 01:12:10 +0000 Subject: [PATCH] Moved the stats view stuff out into an app state that is added automatically as part of simple app construction. git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9159 75d07b2b-3a1a-0410-a2c5-0572b91ccdca --- .../core/com/jme3/app/SimpleApplication.java | 86 ++++---- .../src/core/com/jme3/app/StatsAppState.java | 198 ++++++++++++++++++ engine/src/core/com/jme3/app/StatsView.java | 2 +- 3 files changed, 235 insertions(+), 51 deletions(-) create mode 100644 engine/src/core/com/jme3/app/StatsAppState.java diff --git a/engine/src/core/com/jme3/app/SimpleApplication.java b/engine/src/core/com/jme3/app/SimpleApplication.java index ce4632e79..e296abb3e 100644 --- a/engine/src/core/com/jme3/app/SimpleApplication.java +++ b/engine/src/core/com/jme3/app/SimpleApplication.java @@ -31,6 +31,7 @@ */ 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; @@ -72,14 +73,10 @@ public abstract class SimpleApplication extends Application { protected Node rootNode = new Node("Root Node"); protected Node guiNode = new Node("Gui Node"); - protected float secondCounter = 0.0f; - protected int frameCounter = 0; protected BitmapText fpsText; protected BitmapFont guiFont; - protected StatsView statsView; protected FlyByCamera flyCam; protected boolean showSettings = true; - private boolean showFps = true; private AppActionListener actionListener = new AppActionListener(); private class AppActionListener implements ActionListener { @@ -103,15 +100,22 @@ public abstract class SimpleApplication extends Application { } else if (name.equals(INPUT_MAPPING_MEMORY)) { BufferUtils.printCurrentDirectMemory(null); }else if (name.equals(INPUT_MAPPING_HIDE_STATS)){ - boolean show = showFps; - setDisplayFps(!show); - setDisplayStatView(!show); + if (stateManager.getState(StatsAppState.class) != null) { + stateManager.getState(StatsAppState.class).toggleStats(); + } } } } public SimpleApplication() { + this( new StatsAppState() ); + } + + public SimpleApplication( AppState... initialStates ) { super(); + for (AppState a : initialStates) { + stateManager.attach(a); + } } @Override @@ -175,38 +179,12 @@ public abstract class SimpleApplication extends Application { this.showSettings = showSettings; } - /** - * Attaches FPS statistics to guiNode and displays it on the screen. - * - */ - public void loadFPSText() { - guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); - fpsText = new BitmapText(guiFont, false); - fpsText.setLocalTranslation(0, fpsText.getLineHeight(), 0); - fpsText.setText("Frames per second"); - guiNode.attachChild(fpsText); - } - - /** - * Attaches Statistics View to guiNode and displays it on the screen - * above FPS statistics line. - * - */ - public void loadStatsView() { - statsView = new StatsView("Statistics View", assetManager, renderer.getStatistics()); -// move it up so it appears above fps text - statsView.setLocalTranslation(0, fpsText.getLineHeight(), 0); - guiNode.attachChild(statsView); - } - @Override public void initialize() { super.initialize(); guiNode.setQueueBucket(Bucket.Gui); guiNode.setCullHint(CullHint.Never); - loadFPSText(); - loadStatsView(); viewPort.attachScene(rootNode); guiViewPort.attachScene(guiNode); @@ -221,12 +199,20 @@ public abstract class SimpleApplication extends Application { inputManager.addMapping(INPUT_MAPPING_CAMERA_POS, new KeyTrigger(KeyInput.KEY_C)); inputManager.addMapping(INPUT_MAPPING_MEMORY, new KeyTrigger(KeyInput.KEY_M)); - inputManager.addMapping(INPUT_MAPPING_HIDE_STATS, new KeyTrigger(KeyInput.KEY_F5)); + if (stateManager.getState(StatsAppState.class) != null) { + inputManager.addMapping(INPUT_MAPPING_HIDE_STATS, new KeyTrigger(KeyInput.KEY_F5)); + } inputManager.addListener(actionListener, INPUT_MAPPING_EXIT, INPUT_MAPPING_CAMERA_POS, INPUT_MAPPING_MEMORY, INPUT_MAPPING_HIDE_STATS); } + 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. + fpsText = stateManager.getState(StatsAppState.class).getFpsText(); + } + // call user code simpleInitApp(); } @@ -240,42 +226,42 @@ public abstract class SimpleApplication extends Application { float tpf = timer.getTimePerFrame() * speed; - if (showFps) { - secondCounter += timer.getTimePerFrame(); - frameCounter ++; - if (secondCounter >= 1.0f) { - int fps = (int) (frameCounter / secondCounter); - fpsText.setText("Frames per second: " + fps); - secondCounter = 0.0f; - frameCounter = 0; - } - } - // 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(); + stateManager.postRender(); } public void setDisplayFps(boolean show) { - showFps = show; - fpsText.setCullHint(show ? CullHint.Never : CullHint.Always); + if (stateManager.getState(StatsAppState.class) != null) { + stateManager.getState(StatsAppState.class).setDisplayFps(show); + } } public void setDisplayStatView(boolean show) { - statsView.setEnabled(show); - statsView.setCullHint(show ? CullHint.Never : CullHint.Always); + if (stateManager.getState(StatsAppState.class) != null) { + stateManager.getState(StatsAppState.class).setDisplayStatView(show); + } } public abstract void simpleInitApp(); diff --git a/engine/src/core/com/jme3/app/StatsAppState.java b/engine/src/core/com/jme3/app/StatsAppState.java new file mode 100644 index 000000000..cf0f04749 --- /dev/null +++ b/engine/src/core/com/jme3/app/StatsAppState.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2009-2012 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.AbstractAppState; +import com.jme3.app.state.AppStateManager; +import com.jme3.font.BitmapFont; +import com.jme3.font.BitmapText; +import com.jme3.renderer.RenderManager; +import com.jme3.scene.Node; +import com.jme3.scene.Spatial.CullHint; + + +/** + * Displays stats in SimpleApplication's GUI node or + * using the node and font parameters provided. + * + * @author Paul Speed + */ +public class StatsAppState extends AbstractAppState { + + private Application app; + protected StatsView statsView; + protected boolean showSettings = true; + private boolean showFps = true; + private boolean showStats = true; + + protected Node guiNode; + protected float secondCounter = 0.0f; + protected int frameCounter = 0; + protected BitmapText fpsText; + protected BitmapFont guiFont; + + public StatsAppState() { + } + + public StatsAppState( Node guiNode, BitmapFont guiFont ) { + this.guiNode = guiNode; + this.guiFont = guiFont; + } + + public BitmapText getFpsText() { + return fpsText; + } + + public float getSecondCounter() { + return secondCounter; + } + + public void toggleStats() { + setDisplayFps( !showFps ); + setDisplayStatView( !showStats ); + } + + public void setDisplayFps(boolean show) { + showFps = show; + if (fpsText != null) { + fpsText.setCullHint(show ? CullHint.Never : CullHint.Always); + } + } + + public void setDisplayStatView(boolean show) { + showStats = show; + if (statsView != null ) { + statsView.setEnabled(show); + statsView.setCullHint(show ? CullHint.Never : CullHint.Always); + } + } + + @Override + public void initialize(AppStateManager stateManager, Application app) { + super.initialize(stateManager, app); + this.app = app; + + if (app instanceof SimpleApplication) { + SimpleApplication simpleApp = (SimpleApplication)app; + if (guiNode == null) + guiNode = simpleApp.guiNode; + if (guiFont == null ) + guiFont = simpleApp.guiFont; + } + + if (guiNode == null) { + throw new RuntimeException( "No guiNode specific and cannot be automatically determined." ); + } + + if (guiFont == null) { + guiFont = app.getAssetManager().loadFont("Interface/Fonts/Default.fnt"); + } + + loadFpsText(); + loadStatsView(); + } + + /** + * Attaches FPS statistics to guiNode and displays it on the screen. + * + */ + public void loadFpsText() { + fpsText = new BitmapText(guiFont, false); + fpsText.setLocalTranslation(0, fpsText.getLineHeight(), 0); + fpsText.setText("Frames per second"); + fpsText.setCullHint(showFps ? CullHint.Never : CullHint.Always); + guiNode.attachChild(fpsText); + } + + /** + * Attaches Statistics View to guiNode and displays it on the screen + * above FPS statistics line. + * + */ + public void loadStatsView() { + statsView = new StatsView("Statistics View", + app.getAssetManager(), + app.getRenderer().getStatistics()); + // move it up so it appears above fps text + statsView.setLocalTranslation(0, fpsText.getLineHeight(), 0); + statsView.setEnabled(showStats); + statsView.setCullHint(showStats ? CullHint.Never : CullHint.Always); + guiNode.attachChild(statsView); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + if (enabled) { + fpsText.setCullHint(showFps ? CullHint.Never : CullHint.Always); + statsView.setEnabled(showStats); + statsView.setCullHint(showStats ? CullHint.Never : CullHint.Always); + } else { + fpsText.setCullHint(CullHint.Always); + statsView.setEnabled(false); + statsView.setCullHint(CullHint.Always); + } + } + + @Override + public void update(float tpf) { + if (showFps) { + secondCounter += app.getTimer().getTimePerFrame(); + frameCounter ++; + if (secondCounter >= 1.0f) { + int fps = (int) (frameCounter / secondCounter); + fpsText.setText("Frames per second: " + fps); + secondCounter = 0.0f; + frameCounter = 0; + } + } + } + + @Override + public void render(RenderManager rm) { + } + + @Override + public void postRender(){ + } + + @Override + public void cleanup() { + super.cleanup(); + + guiNode.detachChild(statsView); + guiNode.detachChild(fpsText); + } + + +} diff --git a/engine/src/core/com/jme3/app/StatsView.java b/engine/src/core/com/jme3/app/StatsView.java index a94b4839d..49eeb1395 100644 --- a/engine/src/core/com/jme3/app/StatsView.java +++ b/engine/src/core/com/jme3/app/StatsView.java @@ -108,7 +108,7 @@ public class StatsView extends Node implements Control { // Moved to SimpleApplication to make sure it is // done even if there is no StatsView or the StatsView // is disable. - statistics.clearFrame(); + //statistics.clearFrame(); } public Control cloneForSpatial(Spatial spatial) {