[Scene debugging] [Node children debugging]
As I encountered an mystically ever increasing triangle count as I logged out and in into my game, I had to find the reason as to why this was happening.
No visual oddities could be seen ingame so I decided to debug the rootNode content. I remembered from before some code that would dump the contents into
a html-file as a list, but this time it seemed too simple and wouldnt make it simple enough to debug.
So I ended up writing up a simple JFrame containing a JTree that would continuously update, with the ability to pause to browse.
Either way I found this to be useful and I assumed I could throw it up here for anyone needing to do the same in the future.
The code is pretty straightforward, all you need to do is create the object and pass in the application rootNode and call its update method in the update method of the application.
[java]
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import java.awt.EventQueue;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class NodeTreeViewer extends javax.swing.JFrame {
/**
*
*/
private static final long serialVersionUID = 8855945690857269184L;
private final Node rootNode;
private final DefaultMutableTreeNode top = new DefaultMutableTreeNode(
"Scene");
private final DefaultTreeModel model = new DefaultTreeModel(top);
private boolean update = true;
private long lastUpdate = 0;
// Frequency of updates
private final static long UPDATE_SLEEP = 1000;
/**
* Creates new form NodeTreeViewer
*/
public NodeTreeViewer(final Node rootNode) {
this.rootNode = rootNode;
initComponents();
update();
setTitle("Node Tree Viewer");
setVisible(true);
}
final Runnable updateTask = new Runnable() {
@Override
public void run() {
top.removeAllChildren();
addSpatial(top, rootNode);
model.reload();
}
};
public void update() {
if (!update) {
return;
}
if ((System.currentTimeMillis() - lastUpdate) > UPDATE_SLEEP) {
lastUpdate = System.currentTimeMillis();
EventQueue.invokeLater(updateTask);
}
}
private void addSpatial(final DefaultMutableTreeNode treeParent,
final Spatial spatial) {
final DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(
spatial.getName());
if (spatial instanceof Node) {
for (final Spatial n : ((Node) spatial).getChildren()) {
addSpatial(treeNode, n);
}
}
treeParent.add(treeNode);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed"
// <editor-fold defaultstate="collapsed"
// <editor-fold defaultstate="collapsed"
// //GEN-BEGIN:initComponents
private void initComponents() {
mainPanel = new javax.swing.JPanel();
scrollPane = new javax.swing.JScrollPane();
nodeTree = new javax.swing.JTree(model);
pauseToggle = new javax.swing.JToggleButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
scrollPane.setViewportView(nodeTree);
pauseToggle.setText("Pause");
pauseToggle.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(final java.awt.event.ActionEvent evt) {
pauseToggleActionPerformed(evt);
}
});
final javax.swing.GroupLayout mainPanelLayout = new javax.swing.GroupLayout(
mainPanel);
mainPanel.setLayout(mainPanelLayout);
mainPanelLayout.setHorizontalGroup(mainPanelLayout
.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE,
759, Short.MAX_VALUE)
.addComponent(pauseToggle,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));
mainPanelLayout
.setVerticalGroup(mainPanelLayout
.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(
mainPanelLayout
.createSequentialGroup()
.addComponent(scrollPane)
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pauseToggle)));
final javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING).addComponent(
mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));
layout.setVerticalGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING).addComponent(
mainPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));
pack();
}// //GEN-END:initComponents
private void pauseToggleActionPerformed(final java.awt.event.ActionEvent evt) {// GEN-FIRST:event_pauseToggleActionPerformed
if (pauseToggle.isSelected()) {
pauseToggle.setText("Allow updates");
update = false;
} else {
pauseToggle.setText("Pause");
update = true;
}
}// GEN-LAST:event_pauseToggleActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel mainPanel;
private javax.swing.JTree nodeTree;
private javax.swing.JToggleButton pauseToggle;
private javax.swing.JScrollPane scrollPane;
// End of variables declaration//GEN-END:variables
}
[/java]
Netbeans visual builder form (for the layout)
Paste2: NodeTreeViewer.form