diff --git a/bin/runjava b/bin/runjava index dee5d0af2..c94991845 100755 --- a/bin/runjava +++ b/bin/runjava @@ -70,7 +70,7 @@ foreach $dir (@dirs) { $classpath = "$classpath:$jlib"; # specify our resource root (the resource manager needs this) -my $rootarg = "-Dresource_url=file:$root/rsrc"; +my $rootarg = "-Dresource_dir=$root/tests/rsrc"; my $pid_file = undef; my $i = 0; diff --git a/src/java/com/threerings/stage/tools/viewer/ViewerApp.java b/src/java/com/threerings/stage/tools/viewer/ViewerApp.java new file mode 100644 index 000000000..ae14c185f --- /dev/null +++ b/src/java/com/threerings/stage/tools/viewer/ViewerApp.java @@ -0,0 +1,224 @@ +// +// $Id: ViewerApp.java 19661 2005-03-09 02:40:29Z andrzej $ + +package com.threerings.stage.tools.viewer; + +import java.awt.DisplayMode; +import java.awt.EventQueue; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; + +import java.io.File; +import java.io.IOException; + +import com.samskivert.swing.util.SwingUtil; +import com.samskivert.util.RuntimeAdjust; + +import com.threerings.resource.ResourceManager; +import com.threerings.util.KeyDispatcher; +import com.threerings.util.KeyboardManager; +import com.threerings.util.MessageManager; + +import com.threerings.media.FrameManager; +import com.threerings.media.IconManager; +import com.threerings.media.image.ColorPository; +import com.threerings.media.image.ImageManager; +import com.threerings.media.sound.SoundManager; +import com.threerings.media.tile.bundle.BundledTileSetRepository; + +import com.threerings.cast.CharacterManager; +import com.threerings.cast.bundle.BundledComponentRepository; +import com.threerings.cast.ComponentRepository; + +import com.threerings.miso.tile.MisoTileManager; + +import com.threerings.stage.Log; +import com.threerings.stage.util.StageContext; + +/** + * The ViewerApp is a scene viewing application that allows for trying out + * Stage scenes in a pseudo-runtime environment. + */ +public class ViewerApp +{ + /** + * Construct and initialize the ViewerApp object. + */ + public ViewerApp (String[] args) + throws IOException + { + // get the graphics environment + GraphicsEnvironment env = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + + // get the target graphics device + GraphicsDevice gd = env.getDefaultScreenDevice(); + Log.info("Graphics device [dev=" + gd + + ", mem=" + gd.getAvailableAcceleratedMemory() + + ", displayChange=" + gd.isDisplayChangeSupported() + + ", fullScreen=" + gd.isFullScreenSupported() + "]."); + + // get the graphics configuration and display mode information + GraphicsConfiguration gc = gd.getDefaultConfiguration(); + DisplayMode dm = gd.getDisplayMode(); + Log.info("Display mode [bits=" + dm.getBitDepth() + + ", wid=" + dm.getWidth() + ", hei=" + dm.getHeight() + + ", refresh=" + dm.getRefreshRate() + "]."); + + _rmgr = new ResourceManager("rsrc"); + _rmgr.initBundles(null, "config/resource/manager.properties", null); + _imgr = new ImageManager(_rmgr, _frame); + _tilemgr = new MisoTileManager(_rmgr, _imgr); + _tilemgr.setTileSetRepository( + new BundledTileSetRepository(_rmgr, _imgr, "tilesets")); + _colpos = ColorPository.loadColorPository(_rmgr); + _crepo = new BundledComponentRepository(_rmgr, _imgr, "components"); + _mesgmgr = new MessageManager("rsrc.i18n"); + _soundmgr = new SoundManager( + _rmgr, "general", "media/stage/feedback/default.wav"); + + _frame = new ViewerFrame(gc); + _framemgr = FrameManager.newInstance(_frame); + + StageContext ctx = new ContextImpl(); + _frame.init(ctx, new CharacterManager(_imgr, _crepo)); + + // grab our argument + _target = (args.length > 0) ? args[0] : null; + + // size and position the window, entering full-screen exclusive + // mode if available and desired + if (gd.isFullScreenSupported() /* && _viewFullScreen.getValue() */) { + Log.info("Entering full-screen exclusive mode."); + gd.setFullScreenWindow(_frame); + } else { + _frame.setSize(640, 575); + SwingUtil.centerWindow(_frame); + } + } + + /** + * The implementation of the {@link StageContext} interface that + * provides handles to the config and manager objects that offer + * commonly used services. + */ + protected class ContextImpl implements StageContext + { + public FrameManager getFrameManager () { + return _framemgr; + } + + public MisoTileManager getTileManager () { + return _tilemgr; + } + + // documentation inherited from interface + public ResourceManager getResourceManager () { + return _rmgr; + } + + // documentation inherited from interface + public ImageManager getImageManager () { + return _imgr; + } + + // documentation inherited from interface + public MessageManager getMessageManager () { + return _mesgmgr; + } + + // documentation inherited from interface + public IconManager getIconManager () { + return null; + } + + // documentation inherited from interface + public SoundManager getSoundManager() { + return _soundmgr; + } + + // documentation inherited from interface + public KeyboardManager getKeyboardManager() { + return null; + } + + // documentation inherited from interface + public ComponentRepository getComponentRepository () { + return _crepo; + } + + // documentation inherited from interface + public ColorPository getColorPository () { + return _colpos; + } + + // documentation inherited from interface + public KeyDispatcher getKeyDispatcher () { + return null; + } + + // documentation inherited from interface + public String xlate (String message) { + return message; + } + + // documentation inherited from interface + public String xlate (String bundle, String message) { + return message; + } + } + + /** + * Run the application. + */ + public void run () + { + // show the window + _frame.setVisible(true); + _framemgr.start(); + + // load up anything specified on the command line + EventQueue.invokeLater(new Runnable() { + public void run () { + if (_target != null) { + _frame.loadScene(_target); + } else { + _frame.openScene(null); + } + } + }); + } + + /** + * Instantiate the application object and start it running. + */ + public static void main (String[] args) + { + try { + ViewerApp app = new ViewerApp(args); + app.run(); + } catch (IOException ioe) { + System.err.println("Error initializing viewer app."); + ioe.printStackTrace(); + } + } + + protected ResourceManager _rmgr; + protected MisoTileManager _tilemgr; + protected ImageManager _imgr; + protected BundledComponentRepository _crepo; + protected ColorPository _colpos; + protected MessageManager _mesgmgr; + protected SoundManager _soundmgr; + + protected FrameManager _framemgr; + protected ViewerFrame _frame; + protected String _target; + +// /** A debug hook that toggles debug rendering of traversable tiles. */ +// protected static RuntimeAdjust.BooleanAdjust _viewFullScreen = +// new RuntimeAdjust.BooleanAdjust( +// "Toggles whether or not the scene viewer uses full screen mode.", +// "stage.viewer.full_screen", ToolPrefs.config, false); +} diff --git a/src/java/com/threerings/stage/tools/viewer/ViewerFrame.java b/src/java/com/threerings/stage/tools/viewer/ViewerFrame.java new file mode 100644 index 000000000..0094613a1 --- /dev/null +++ b/src/java/com/threerings/stage/tools/viewer/ViewerFrame.java @@ -0,0 +1,170 @@ +// +// $Id: ViewerFrame.java 20143 2005-03-30 01:12:48Z mdb $ + +package com.threerings.stage.tools.viewer; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.GraphicsConfiguration; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import java.io.File; + +import javax.swing.JFileChooser; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; +import javax.swing.filechooser.FileFilter; + +import com.samskivert.swing.util.MenuUtil; + +import com.threerings.cast.CharacterManager; +import com.threerings.media.ManagedJFrame; + +import com.threerings.whirled.spot.data.Location; +import com.threerings.whirled.spot.data.Portal; +import com.threerings.whirled.spot.data.SpotSceneModel; + +import com.threerings.stage.Log; +import com.threerings.stage.data.StageScene; +import com.threerings.stage.data.StageSceneModel; +import com.threerings.stage.tools.xml.StageSceneParser; +import com.threerings.stage.util.StageContext; + +/** + * The viewer frame is the main application window. + */ +public class ViewerFrame extends ManagedJFrame +{ + /** + * Creates a frame in which the viewer application can operate. + */ + public ViewerFrame (GraphicsConfiguration gc) + { + super(gc); + + // set up the frame options + setTitle("Scene Viewer"); + setDefaultCloseOperation(EXIT_ON_CLOSE); + + // set the frame and content panel background to black + setBackground(Color.black); + getContentPane().setBackground(Color.black); + + // create the "File" menu + KeyStroke accel = null; + JMenu menuSettings = new JMenu("File"); + + // open... + accel = KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK); + MenuUtil.addMenuItem(menuSettings, "Open scene...", KeyEvent.VK_O, + accel, this, "openScene"); + + // decoys! + MenuUtil.addMenuItem(menuSettings, "Decoys!", this, "getJiggy"); + + // quit + menuSettings.addSeparator(); + accel = KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK); + MenuUtil.addMenuItem(menuSettings, "Quit", KeyEvent.VK_Q, + accel, this, "handleQuit"); + + // create the menu bar + JMenuBar bar = new JMenuBar(); + bar.add(menuSettings); + + // add the menu bar to the frame + setJMenuBar(bar); + } + + /** + * Instructs us to create our scene panel. + */ + public void init (StageContext ctx, CharacterManager charmgr) + { + _panel = new ViewerScenePanel(ctx, charmgr); + getContentPane().add(_panel, BorderLayout.CENTER); + } + + /** + * Callback for opening a new scene. + */ + public void openScene (ActionEvent event) + { +// String where = ToolPrefs.config.getValue( +// "viewer.last_dir", System.getProperty("user.dir")); + String where = System.getProperty("user.dir"); + JFileChooser chooser = new JFileChooser(where); + chooser.setFileFilter(new FileFilter () { + public boolean accept (File f) { + return (f.isDirectory() || f.getName().endsWith(".xml")); + } + public String getDescription () { + return "XML Files"; + } + }); + int result = chooser.showOpenDialog(this); + if (result == JFileChooser.APPROVE_OPTION) { + File filescene = chooser.getSelectedFile(); + loadScene(filescene.getPath()); +// ToolPrefs.config.setValue("viewer.last_dir", filescene.getParent()); + } + } + + public void getJiggy (ActionEvent event) + { + _panel.createDecoys(); + } + + /** + * Handles a request to get the fuck out of dodge. + */ + public void handleQuit (ActionEvent evt) + { + System.exit(0); + } + + public void loadScene (String path) + { + String errmsg = null; + + try { + StageSceneParser parser = new StageSceneParser(); + StageSceneModel model = (StageSceneModel)parser.parseScene(path); + if (model == null) { + errmsg = "No scene found in scene file '" + path + "'."; + + } else { + SpotSceneModel ssmodel = SpotSceneModel.getSceneModel(model); + Location defloc = null; + // find the default entrance to this scene + for (int ii = 0; ii < ssmodel.portals.length; ii++) { + Portal port = ssmodel.portals[ii]; + if (port.portalId == ssmodel.defaultEntranceId) { + defloc = port.getOppLocation(); + break; + } + } + if (defloc == null) { + Log.warning("Scene has no def. entrance '" + path + "'."); + } + + _panel.setScene(new StageScene(model, null), defloc); + } + + } catch (Exception e) { + errmsg = "Error parsing scene file '" + path + "'."; + Log.logStackTrace(e); + } + + if (errmsg != null) { + JOptionPane.showMessageDialog( + this, errmsg, "Load error", JOptionPane.ERROR_MESSAGE); + } + } + + protected ViewerScenePanel _panel; +} diff --git a/src/java/com/threerings/stage/tools/viewer/ViewerScenePanel.java b/src/java/com/threerings/stage/tools/viewer/ViewerScenePanel.java new file mode 100644 index 000000000..97a36879c --- /dev/null +++ b/src/java/com/threerings/stage/tools/viewer/ViewerScenePanel.java @@ -0,0 +1,239 @@ +// +// $Id: ViewerScenePanel.java 20143 2005-03-30 01:12:48Z mdb $ + +package com.threerings.stage.tools.viewer; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +import com.samskivert.swing.Controller; + +import com.threerings.media.util.PerformanceMonitor; +import com.threerings.media.util.PerformanceObserver; +import com.threerings.util.RandomUtil; + +import com.threerings.cast.CharacterDescriptor; +import com.threerings.cast.CharacterManager; +import com.threerings.cast.CharacterSprite; +import com.threerings.cast.ComponentRepository; +import com.threerings.cast.util.CastUtil; + +import com.threerings.media.sprite.PathObserver; +import com.threerings.media.sprite.Sprite; +import com.threerings.media.sprite.SpriteManager; +import com.threerings.media.util.LineSegmentPath; +import com.threerings.media.util.Path; + +import com.threerings.stage.client.StageScenePanel; +import com.threerings.whirled.spot.data.Location; + +import com.threerings.stage.Log; +import com.threerings.stage.data.StageScene; +import com.threerings.stage.util.StageContext; + +public class ViewerScenePanel extends StageScenePanel + implements PerformanceObserver, PathObserver +{ + /** + * Construct the panel and initialize it with a context. + */ + public ViewerScenePanel (StageContext ctx, CharacterManager charmgr) + { + super(ctx, new Controller() { + }); + + _charmgr = charmgr; + + // create the character descriptors + _descUser = CastUtil.getRandomDescriptor( + "female", ctx.getComponentRepository()); + _descDecoy = CastUtil.getRandomDescriptor( + "male", ctx.getComponentRepository()); + + // create the manipulable sprite + _sprite = createSprite(_descUser); + setFollowsPathable(_sprite, CENTER_ON_PATHABLE); + + PerformanceMonitor.register(this, "paint", 1000); + } + + // documentation inherited + public void setScene (StageScene scene, Location defloc) + { + setScene(scene); + + // move all of our sprites to the default entrance + _defloc = defloc; + Point defpos = getScreenCoords(defloc.x, defloc.y); + _sprite.setLocation(defpos.x, defpos.y); + + if (_decoys != null) { + for (int ii = 0; ii < _decoys.length; ii++) { + _decoys[ii].setLocation(defpos.x, defpos.y); + } + createDecoyPaths(); + } + } + + /** + * Creates a new sprite. + */ + protected CharacterSprite createSprite (CharacterDescriptor desc) + { + CharacterSprite s = _charmgr.getCharacter(desc); + if (s != null) { + // start 'em out standing + s.setActionSequence(CharacterSprite.STANDING); + if (_defloc != null) { + Point defpos = getScreenCoords(_defloc.x, _defloc.y); + s.setLocation(defpos.x, defpos.y); + } else { + s.setLocation(300, 300); + } + s.addSpriteObserver(this); + _spritemgr.addSprite(s); + } + + return s; + } + + /** + * Creates the decoy sprites. + */ + public void createDecoys () + { + int decoys = DEFAULT_NUM_DECOYS; + try { + decoys = Integer.parseInt(System.getProperty("decoys")); + } catch (Exception e) { + } + + if (_decoys == null) { + _decoys = new CharacterSprite[decoys]; + for (int ii = 0; ii < decoys; ii++) { + _decoys[ii] = createSprite(_descDecoy); + } + } + + // if we have a scene, create paths for our decoys + createDecoyPaths(); + } + + /** + * Creates paths for the decoy sprites. + */ + protected void createDecoyPaths () + { + if (_decoys != null) { + for (int ii = 0; ii < _decoys.length; ii++) { + if (_decoys[ii] != null) { + createRandomPath(_decoys[ii]); + } + } + } + } + + // documentation inherited + public void paint (Graphics g) + { + super.paint(g); + PerformanceMonitor.tick(this, "paint"); + } + + // documentation inherited + public void checkpoint (String name, int ticks) + { + Log.info(name + " [ticks=" + ticks + "]."); + } + + /** MouseListener interface methods */ + public void mousePressed (MouseEvent e) + { + int x = e.getX(), y = e.getY(); + + switch (e.getModifiers()) { + case MouseEvent.BUTTON1_MASK: + createPath(_sprite, x, y); + break; + + case MouseEvent.BUTTON2_MASK: + if (_decoys != null) { + for (int ii = 0; ii < _decoys.length; ii++) { + createPath(_decoys[ii], x, y); + } + } + break; + } + } + + /** + * Assigns the sprite a path leading to the given destination + * screen coordinates. Returns whether a path was successfully + * assigned. + */ + protected boolean createPath (CharacterSprite s, int x, int y) + { + // get the path from here to there + LineSegmentPath path = (LineSegmentPath)getPath(s, x, y, false); + if (path == null) { + s.cancelMove(); + return false; + } + + // start the sprite moving along the path + path.setVelocity(100f/1000f); + s.move(path); + return true; + } + + /** + * Assigns a new random path to the given sprite. + */ + protected void createRandomPath (CharacterSprite s) + { + int x, y; + do { + x = _vbounds.x + RandomUtil.getInt(_vbounds.width); + y = _vbounds.y + RandomUtil.getInt(_vbounds.height); + } while (!createPath(s, x, y)); + } + + // documentation inherited from interface + public void pathCancelled (Sprite sprite, Path path) + { + // nothing doing + } + + // documentation inherited from interface + public void pathCompleted (Sprite sprite, Path path, long when) + { + if (sprite != _sprite) { + // move the decoy to a new random location + createRandomPath((CharacterSprite)sprite); + } + } + + /** The number of decoy characters milling about. */ + protected static final int DEFAULT_NUM_DECOYS = 10; + + /** The current scene's default entrance. */ + protected Location _defloc; + + /** Provides character sprite data. */ + protected CharacterManager _charmgr; + + /** The character descriptor for the user character. */ + protected CharacterDescriptor _descUser; + + /** The character descriptor for the decoy characters. */ + protected CharacterDescriptor _descDecoy; + + /** The sprite we're manipulating within the view. */ + protected CharacterSprite _sprite; + + /** The test sprites that meander about aimlessly. */ + protected CharacterSprite[] _decoys; +}