Added basic JME import dialog to model viewer. With the latest version
of LWJGL, the AWT canvas releases its OpenGL context after rendering. Rather than redesign all event handling to take place in the update method, I put in a hack to grab the context back. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4200 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -6,6 +6,7 @@ commons-io.jar
|
||||
commons-lang.jar
|
||||
commons-logging.jar
|
||||
jme-awt.jar
|
||||
jme-effects.jar
|
||||
jme-bui.jar
|
||||
jme-model.jar
|
||||
jme-sound.jar
|
||||
|
||||
@@ -7,6 +7,7 @@ m.title = Three Rings Model Viewer
|
||||
|
||||
m.file_menu = File
|
||||
m.file_load = Load Model...
|
||||
m.file_import = Import JME File...
|
||||
m.file_quit = Quit
|
||||
|
||||
m.view_menu = View
|
||||
@@ -25,6 +26,9 @@ m.mode_skin = Skin
|
||||
m.load_title = Select Model to Load
|
||||
m.load_filter = Model Files (*.properties, *.dat)
|
||||
|
||||
m.import_title = Select File to Import
|
||||
m.import_filter = JME Files (*.jme)
|
||||
|
||||
m.anim_select = Animations:
|
||||
m.anim_start = Start
|
||||
m.anim_stop = Stop
|
||||
@@ -36,6 +40,10 @@ m.loaded_model = Loaded {0}
|
||||
m.load_error = Error loading {0}: {1}
|
||||
m.invalid_type = Invalid file type.
|
||||
|
||||
m.import = JME File: {0}
|
||||
m.scale = Scale
|
||||
m.respawn_particles = Respawn Particles
|
||||
|
||||
m.rotate_light = Rotate Light
|
||||
m.azimuth = Azimuth:
|
||||
m.elevation = Elevation:
|
||||
|
||||
@@ -22,16 +22,20 @@
|
||||
package com.threerings.jme;
|
||||
|
||||
import java.awt.Canvas;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
import java.awt.event.ComponentEvent;
|
||||
|
||||
import org.lwjgl.LWJGLException;
|
||||
|
||||
import com.jme.renderer.Renderer;
|
||||
import com.jme.renderer.lwjgl.LWJGLRenderer;
|
||||
import com.jme.scene.Node;
|
||||
import com.jme.system.DisplaySystem;
|
||||
import com.jmex.awt.JMECanvas;
|
||||
import com.jmex.awt.JMECanvasImplementor;
|
||||
import com.jmex.awt.lwjgl.LWJGLCanvas;
|
||||
|
||||
import com.jmex.bui.CanvasRootNode;
|
||||
|
||||
@@ -44,7 +48,15 @@ public class JmeCanvasApp extends JmeApp
|
||||
public JmeCanvasApp (int width, int height)
|
||||
{
|
||||
_display = DisplaySystem.getDisplaySystem("LWJGL");
|
||||
_canvas = _display.createCanvas(width, height);
|
||||
|
||||
// create a throwaway canvas so that the display system knows it's
|
||||
// created, then create our custom canvas
|
||||
_display.createCanvas(width, height);
|
||||
try {
|
||||
_canvas = createCanvas();
|
||||
} catch (LWJGLException e) {
|
||||
Log.warning("Failed to create LWJGL canvas [error=" + e + "].");
|
||||
}
|
||||
((JMECanvas)_canvas).setImplementor(_winimp);
|
||||
_canvas.setBounds(0, 0, width, height);
|
||||
_canvas.addComponentListener(new ComponentAdapter() {
|
||||
@@ -91,7 +103,28 @@ public class JmeCanvasApp extends JmeApp
|
||||
{
|
||||
return EventQueue.isDispatchThread();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates and returns the LWJGL canvas instance.
|
||||
*/
|
||||
protected Canvas createCanvas ()
|
||||
throws LWJGLException
|
||||
{
|
||||
// LWJGL's canvas releases the context after painting. we make it
|
||||
// current again, because we want it valid when we process events.
|
||||
return new LWJGLCanvas() {
|
||||
public void update (Graphics g) {
|
||||
super.update(g);
|
||||
try {
|
||||
makeCurrent();
|
||||
} catch (LWJGLException e) {
|
||||
Log.warning("Failed to make context current [error=" +
|
||||
e + "].");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected DisplaySystem createDisplay ()
|
||||
{
|
||||
|
||||
@@ -89,7 +89,9 @@ import com.jme.scene.state.ZBufferState;
|
||||
import com.jme.system.JmeException;
|
||||
import com.jme.util.LoggingSystem;
|
||||
import com.jme.util.TextureManager;
|
||||
import com.jme.util.export.binary.BinaryImporter;
|
||||
import com.jme.util.geom.Debugger;
|
||||
import com.jmex.effects.particles.ParticleMesh;
|
||||
|
||||
import com.samskivert.swing.GroupLayout;
|
||||
import com.samskivert.swing.Spacer;
|
||||
@@ -168,6 +170,16 @@ public class ModelViewer extends JmeCanvasApp
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_L, KeyEvent.CTRL_MASK));
|
||||
file.add(load);
|
||||
|
||||
Action importAction = new AbstractAction(_msg.get("m.file_import")) {
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
showImportDialog();
|
||||
}
|
||||
};
|
||||
importAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_I);
|
||||
importAction.putValue(Action.ACCELERATOR_KEY,
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK));
|
||||
file.add(importAction);
|
||||
|
||||
file.addSeparator();
|
||||
Action quit = new AbstractAction(_msg.get("m.file_quit")) {
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
@@ -492,7 +504,7 @@ public class ModelViewer extends JmeCanvasApp
|
||||
if (file.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
String path = file.toString();
|
||||
String path = file.toString().toLowerCase();
|
||||
return path.endsWith(".properties") ||
|
||||
path.endsWith(".dat");
|
||||
}
|
||||
@@ -632,6 +644,54 @@ public class ModelViewer extends JmeCanvasApp
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the import particle system dialog.
|
||||
*/
|
||||
protected void showImportDialog ()
|
||||
{
|
||||
if (_ichooser == null) {
|
||||
_ichooser = new JFileChooser();
|
||||
_ichooser.setDialogTitle(_msg.get("m.import_title"));
|
||||
_ichooser.setFileFilter(new FileFilter() {
|
||||
public boolean accept (File file) {
|
||||
if (file.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
String path = file.toString().toLowerCase();
|
||||
return path.endsWith(".jme");
|
||||
}
|
||||
public String getDescription () {
|
||||
return _msg.get("m.import_filter");
|
||||
}
|
||||
});
|
||||
File dir = new File(_config.getValue("import_dir", "."));
|
||||
if (dir.exists()) {
|
||||
_ichooser.setCurrentDirectory(dir);
|
||||
}
|
||||
}
|
||||
if (_ichooser.showOpenDialog(_frame) == JFileChooser.APPROVE_OPTION) {
|
||||
importFile(_ichooser.getSelectedFile());
|
||||
}
|
||||
_config.setValue("import_dir",
|
||||
_ichooser.getCurrentDirectory().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to import the specified file as a JME binary scene.
|
||||
*/
|
||||
protected void importFile (File file)
|
||||
{
|
||||
try {
|
||||
new ImportDialog(file,
|
||||
(Spatial)BinaryImporter.getInstance().load(
|
||||
file)).setVisible(true);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
_status.setText(_msg.get("m.load_error", file, e));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the model's animation speed based on the position of the
|
||||
* animation speed slider.
|
||||
@@ -678,6 +738,9 @@ public class ModelViewer extends JmeCanvasApp
|
||||
/** The model file chooser. */
|
||||
protected JFileChooser _chooser;
|
||||
|
||||
/** The import file chooser. */
|
||||
protected JFileChooser _ichooser;
|
||||
|
||||
/** The desired animation mode. */
|
||||
protected Model.AnimationMode _animMode;
|
||||
|
||||
@@ -730,6 +793,84 @@ public class ModelViewer extends JmeCanvasApp
|
||||
}
|
||||
};
|
||||
|
||||
/** Allows users to manipulate an imported JME file. */
|
||||
protected class ImportDialog extends JDialog
|
||||
implements ChangeListener
|
||||
{
|
||||
public ImportDialog (File file, Spatial spatial)
|
||||
{
|
||||
super(_frame, _msg.get("m.import", file), false);
|
||||
_spatial = spatial;
|
||||
|
||||
// rotate from y-up to z-up and set initial scale
|
||||
_spatial.getLocalRotation().fromAngleNormalAxis(FastMath.HALF_PI,
|
||||
Vector3f.UNIT_X);
|
||||
_spatial.setLocalScale(0.025f);
|
||||
|
||||
JPanel cpanel = GroupLayout.makeVBox();
|
||||
getContentPane().add(cpanel, BorderLayout.CENTER);
|
||||
|
||||
JPanel spanel = new JPanel();
|
||||
spanel.add(new JLabel(_msg.get("m.scale")));
|
||||
spanel.add(_scale = new JSlider(0, 1000, 250));
|
||||
_scale.addChangeListener(this);
|
||||
cpanel.add(spanel);
|
||||
|
||||
JPanel bpanel = new JPanel();
|
||||
bpanel.add(new JButton(new AbstractAction(
|
||||
_msg.get("m.respawn_particles")) {
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
forceRespawn(_spatial);
|
||||
}
|
||||
}));
|
||||
bpanel.add(new JButton(new AbstractAction(_msg.get("m.close")) {
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
setVisible(false);
|
||||
}
|
||||
}));
|
||||
getContentPane().add(bpanel, BorderLayout.SOUTH);
|
||||
pack();
|
||||
}
|
||||
|
||||
// documentation inherited from interface ChangeListener
|
||||
public void stateChanged (ChangeEvent e)
|
||||
{
|
||||
_spatial.setLocalScale(_scale.getValue() * 0.0001f);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void setVisible (boolean visible)
|
||||
{
|
||||
super.setVisible(visible);
|
||||
if (visible && _spatial.getParent() == null) {
|
||||
_ctx.getGeometry().attachChild(_spatial);
|
||||
} else if (!visible && _spatial.getParent() != null) {
|
||||
_ctx.getGeometry().detachChild(_spatial);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively forces all particles to respawn.
|
||||
*/
|
||||
protected void forceRespawn (Spatial spatial)
|
||||
{
|
||||
if (spatial instanceof ParticleMesh) {
|
||||
((ParticleMesh)spatial).forceRespawn();
|
||||
} else if (spatial instanceof Node) {
|
||||
Node node = (Node)spatial;
|
||||
for (int ii = 0, nn = node.getQuantity(); ii < nn; ii++) {
|
||||
forceRespawn(node.getChild(ii));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The imported scene. */
|
||||
protected Spatial _spatial;
|
||||
|
||||
/** The scale slider. */
|
||||
protected JSlider _scale;
|
||||
}
|
||||
|
||||
/** Allows users to move the directional light around. */
|
||||
protected class RotateLightDialog extends JDialog
|
||||
implements ChangeListener
|
||||
@@ -773,12 +914,6 @@ public class ModelViewer extends JmeCanvasApp
|
||||
-FastMath.sin(el));
|
||||
}
|
||||
|
||||
// documentation inherited from interface ActionListener
|
||||
public void actionPerformed (ActionEvent e)
|
||||
{
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
/** Azimuth and elevation sliders. */
|
||||
protected JSlider _azimuth, _elevation;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user