tabledlabelgrapher.java
来自「java 3d game jme 工程开发源代码」· Java 代码 · 共 322 行
JAVA
322 行
/*
* Copyright (c) 2003-2009 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.jme.util.stat.graph;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Iterator;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Line;
import com.jme.scene.Node;
import com.jme.scene.Text;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.BlendState;
import com.jme.system.DisplaySystem;
import com.jme.util.Debug;
import com.jme.util.stat.MultiStatSample;
import com.jme.util.stat.StatCollector;
import com.jme.util.stat.StatType;
import com.jme.util.stat.StatValue;
/**
* @author Joshua Slack
*/
public class TabledLabelGrapher extends AbstractStatGrapher {
public enum ConfigKeys {
TextColor,
Name,
FrameAverage,
Decimals,
FontScale,
ValueScale,
Abbreviate,
}
public static int DEFAULT_DECIMALS = 2;
protected Node graphRoot = new Node("root");
protected int eventCount = 0;
protected int threshold = 1;
protected int columns = 1;
protected Quad bgQuad = new Quad("bgQuad", 1, 1);
protected BlendState defBlendState = null;
private HashMap<StatType, LabelEntry> entries = new HashMap<StatType, LabelEntry>();
private boolean minimalBackground;
private AbstractStatGrapher linkedGraph;
public TabledLabelGrapher(int width, int height) {
super(width, height);
defBlendState = DisplaySystem.getDisplaySystem().getRenderer()
.createBlendState();
defBlendState.setEnabled(true);
defBlendState.setBlendEnabled(true);
defBlendState.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
defBlendState
.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
graphRoot.setRenderState(defBlendState);
bgQuad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
bgQuad.setDefaultColor(ColorRGBA.black.clone());
}
public void statsUpdated() {
if (!isEnabled() || !Debug.updateGraphs)
return;
// Turn off stat collection while we draw this graph.
StatCollector.pause();
// some basic stats:
int texWidth = gWidth;
int texHeight = gHeight;
// On stat event:
// - check if enough events have been triggered to cause an update.
eventCount++;
if (eventCount < threshold) {
return;
} else {
eventCount = 0;
}
int col = 0;
float lastY = texHeight-3, maxY = 0;
float colSize = texWidth/(float)getColumns();
// clear visitations
for (StatType type : entries.keySet()) {
entries.get(type).visited = false;
}
// - We only care about the most recent stats
synchronized (StatCollector.getHistorical()) {
MultiStatSample sample = StatCollector.getHistorical().get(
StatCollector.getHistorical().size() - 1);
// - go through things we are configured for
for (StatType type : config.keySet()) {
StatValue val = sample.values.get(type);
if (val == null) {
if (!StatCollector.hasHistoricalStat(type)) continue;
else val = new StatValue(0,1);
}
LabelEntry entry = entries.get(type);
// Prepare our entry object as needed.
if (entry == null) {
entry = new LabelEntry(type);
entries.put(type, entry);
graphRoot.attachChild(entry.text);
}
entry.visited = true;
// Update text value
double value = getBooleanConfig(type, ConfigKeys.FrameAverage.name(), false) ? val.average : val.val;
entry.text.print(getStringConfig(type, ConfigKeys.Name.name(), type.getStatName()) + " " + stripVal(value, type));
// Set font scale
float scale = getFloatConfig(type, ConfigKeys.FontScale.name(), .80f);
entry.text.setLocalScale(scale);
// See if we have a defained color for this type, otherwise use
// the corresponding color from a linked line grapher, or if
// none, use white.
entry.text.setTextColor(getColorConfig(type, ConfigKeys.TextColor
.name(), linkedGraph != null ? linkedGraph
.getColorConfig(type, LineGrapher.ConfigKeys.Color
.name(), ColorRGBA.white.clone())
: ColorRGBA.white.clone()));
// Update text placement.
float labelHeight = entry.text.getHeight();
if (maxY < labelHeight) {
maxY = labelHeight;
}
entry.text.setLocalTranslation(colSize * col, lastY-labelHeight, 0);
entry.text.updateRenderState();
// Update line key as needed
if (linkedGraph != null && linkedGraph.hasConfig(type) && linkedGraph instanceof TableLinkable) {
// add line keys
entry.lineKey = ((TableLinkable)linkedGraph).updateLineKey(type, entry.lineKey);
if (entry.lineKey.getParent() != graphRoot) {
graphRoot.attachChild(entry.lineKey);
}
entry.lineKey.updateRenderState();
Vector3f tLoc = entry.text.getLocalTranslation();
entry.lineKey.setLocalTranslation(tLoc.x+entry.text.getWidth()+15, tLoc.y+(.5f*entry.text.getHeight()), 0);
}
// update column / row variables
col++;
col %= getColumns();
if (col == 0) {
lastY -= maxY;
maxY = 0;
}
}
for (Iterator<StatType> i = entries.keySet().iterator(); i.hasNext(); ) {
LabelEntry entry = entries.get(i.next());
// - Go through the entries list and remove any that were not
// visited.
if (!entry.visited) {
entry.text.removeFromParent();
entry.lineKey.removeFromParent();
i.remove();
}
}
}
if (minimalBackground) {
texRenderer.getBackgroundColor().a = 0;
lastY-=3;
if (col != 0) {
lastY -= maxY;
}
bgQuad.resize(texWidth, texHeight-lastY);
bgQuad.setRenderState(defBlendState);
bgQuad.updateRenderState();
bgQuad.setLocalTranslation(texWidth/2f, texHeight - (texHeight-lastY)/2f, 0);
// - Draw our bg quad
texRenderer.render(bgQuad, tex);
// - Now, draw to texture via a TextureRenderer
texRenderer.render(graphRoot, tex, false);
} else {
texRenderer.getBackgroundColor().a = 1;
// - Now, draw to texture via a TextureRenderer
texRenderer.render(graphRoot, tex);
}
// Turn stat collection back on.
StatCollector.resume();
}
private String stripVal(double val, StatType type) {
// scale as needed
val = val * getDoubleConfig(type, ConfigKeys.ValueScale.name(), 1.0);
String post = "";
// Break it down if needed.
if (getBooleanConfig(type, ConfigKeys.Abbreviate.name(), true)) {
if ( val >= 1000000 ) {
val /= 1000000;
post = "m";
} else if (val >= 1000) {
val /= 1000;
post = "k";
}
}
int decimals = getIntConfig(type, ConfigKeys.Decimals.name(), DEFAULT_DECIMALS);
if (!"".equals(post) && decimals == 0) {
decimals = 1; // use 1 spot anyway.
}
StringBuilder format = new StringBuilder(decimals > 0 ? "0.0" : "0");
for (int x = 1; x < decimals; x++) {
format.append("0");
}
return new DecimalFormat(format.toString()).format(val) + post;
}
public int getThreshold() {
return threshold;
}
public void setThreshold(int threshold) {
this.threshold = threshold;
}
public int getColumns() {
return columns;
}
public void setColumns(int columns) {
if (columns < 1) {
throw new IllegalArgumentException("columns must be >= 1 ("+columns+")");
}
this.columns = columns;
}
public boolean isMinimalBackground() {
return minimalBackground;
}
public void setMinimalBackground(boolean minimalBackground) {
this.minimalBackground = minimalBackground;
}
public void linkTo(AbstractStatGrapher grapher) {
this.linkedGraph = grapher;
}
class LabelEntry {
Text text;
Line lineKey;
boolean visited;
StatType type;
public LabelEntry(StatType type) {
text = Text.createDefaultTextLabel("label", getStringConfig(type, ConfigKeys.Name.name(), type.getStatName()));
}
}
public void reset() {
synchronized (StatCollector.getHistorical()) {
for (Iterator<StatType> i = entries.keySet().iterator(); i.hasNext(); ) {
LabelEntry entry = entries.get(i.next());
entry.text.removeFromParent();
entry.lineKey.removeFromParent();
i.remove();
}
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?