1 /* 2 * Copyright (c) 2009-2012 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.app; 33 34 import com.jme3.app.state.AbstractAppState; 35 import com.jme3.app.state.AppStateManager; 36 import com.jme3.font.BitmapFont; 37 import com.jme3.font.BitmapText; 38 import com.jme3.renderer.RenderManager; 39 import com.jme3.scene.Node; 40 import com.jme3.scene.Spatial.CullHint; 41 42 43 /** 44 * Displays stats in SimpleApplication's GUI node or 45 * using the node and font parameters provided. 46 * 47 * @author Paul Speed 48 */ 49 public class StatsAppState extends AbstractAppState { 50 51 private Application app; 52 protected StatsView statsView; 53 protected boolean showSettings = true; 54 private boolean showFps = true; 55 private boolean showStats = true; 56 57 protected Node guiNode; 58 protected float secondCounter = 0.0f; 59 protected int frameCounter = 0; 60 protected BitmapText fpsText; 61 protected BitmapFont guiFont; 62 StatsAppState()63 public StatsAppState() { 64 } 65 StatsAppState( Node guiNode, BitmapFont guiFont )66 public StatsAppState( Node guiNode, BitmapFont guiFont ) { 67 this.guiNode = guiNode; 68 this.guiFont = guiFont; 69 } 70 71 /** 72 * Called by SimpleApplication to provide an early font 73 * so that the fpsText can be created before init. This 74 * is because several applications expect to directly access 75 * fpsText... unfortunately. 76 */ setFont( BitmapFont guiFont )77 void setFont( BitmapFont guiFont ) { 78 this.guiFont = guiFont; 79 this.fpsText = new BitmapText(guiFont, false); 80 } 81 getFpsText()82 public BitmapText getFpsText() { 83 return fpsText; 84 } 85 getStatsView()86 public StatsView getStatsView() { 87 return statsView; 88 } 89 getSecondCounter()90 public float getSecondCounter() { 91 return secondCounter; 92 } 93 toggleStats()94 public void toggleStats() { 95 setDisplayFps( !showFps ); 96 setDisplayStatView( !showStats ); 97 } 98 setDisplayFps(boolean show)99 public void setDisplayFps(boolean show) { 100 showFps = show; 101 if (fpsText != null) { 102 fpsText.setCullHint(show ? CullHint.Never : CullHint.Always); 103 } 104 } 105 setDisplayStatView(boolean show)106 public void setDisplayStatView(boolean show) { 107 showStats = show; 108 if (statsView != null ) { 109 statsView.setEnabled(show); 110 statsView.setCullHint(show ? CullHint.Never : CullHint.Always); 111 } 112 } 113 114 @Override initialize(AppStateManager stateManager, Application app)115 public void initialize(AppStateManager stateManager, Application app) { 116 super.initialize(stateManager, app); 117 this.app = app; 118 119 if (app instanceof SimpleApplication) { 120 SimpleApplication simpleApp = (SimpleApplication)app; 121 if (guiNode == null) 122 guiNode = simpleApp.guiNode; 123 if (guiFont == null ) 124 guiFont = simpleApp.guiFont; 125 } 126 127 if (guiNode == null) { 128 throw new RuntimeException( "No guiNode specific and cannot be automatically determined." ); 129 } 130 131 if (guiFont == null) { 132 guiFont = app.getAssetManager().loadFont("Interface/Fonts/Default.fnt"); 133 } 134 135 loadFpsText(); 136 loadStatsView(); 137 } 138 139 /** 140 * Attaches FPS statistics to guiNode and displays it on the screen. 141 * 142 */ loadFpsText()143 public void loadFpsText() { 144 if (fpsText == null) { 145 fpsText = new BitmapText(guiFont, false); 146 } 147 148 fpsText.setLocalTranslation(0, fpsText.getLineHeight(), 0); 149 fpsText.setText("Frames per second"); 150 fpsText.setCullHint(showFps ? CullHint.Never : CullHint.Always); 151 guiNode.attachChild(fpsText); 152 } 153 154 /** 155 * Attaches Statistics View to guiNode and displays it on the screen 156 * above FPS statistics line. 157 * 158 */ loadStatsView()159 public void loadStatsView() { 160 statsView = new StatsView("Statistics View", 161 app.getAssetManager(), 162 app.getRenderer().getStatistics()); 163 // move it up so it appears above fps text 164 statsView.setLocalTranslation(0, fpsText.getLineHeight(), 0); 165 statsView.setEnabled(showStats); 166 statsView.setCullHint(showStats ? CullHint.Never : CullHint.Always); 167 guiNode.attachChild(statsView); 168 } 169 170 @Override setEnabled(boolean enabled)171 public void setEnabled(boolean enabled) { 172 super.setEnabled(enabled); 173 174 if (enabled) { 175 fpsText.setCullHint(showFps ? CullHint.Never : CullHint.Always); 176 statsView.setEnabled(showStats); 177 statsView.setCullHint(showStats ? CullHint.Never : CullHint.Always); 178 } else { 179 fpsText.setCullHint(CullHint.Always); 180 statsView.setEnabled(false); 181 statsView.setCullHint(CullHint.Always); 182 } 183 } 184 185 @Override update(float tpf)186 public void update(float tpf) { 187 if (showFps) { 188 secondCounter += app.getTimer().getTimePerFrame(); 189 frameCounter ++; 190 if (secondCounter >= 1.0f) { 191 int fps = (int) (frameCounter / secondCounter); 192 fpsText.setText("Frames per second: " + fps); 193 secondCounter = 0.0f; 194 frameCounter = 0; 195 } 196 } 197 } 198 199 @Override cleanup()200 public void cleanup() { 201 super.cleanup(); 202 203 guiNode.detachChild(statsView); 204 guiNode.detachChild(fpsText); 205 } 206 207 208 } 209