diff --git a/src/java/com/threerings/media/VirtualMediaPanel.java b/src/java/com/threerings/media/VirtualMediaPanel.java index a6fa6b8ac..0856a1833 100644 --- a/src/java/com/threerings/media/VirtualMediaPanel.java +++ b/src/java/com/threerings/media/VirtualMediaPanel.java @@ -1,5 +1,5 @@ // -// $Id: VirtualMediaPanel.java,v 1.14 2003/04/12 01:26:29 mdb Exp $ +// $Id: VirtualMediaPanel.java,v 1.15 2003/04/17 19:21:16 mdb Exp $ package com.threerings.media; @@ -224,9 +224,19 @@ public class VirtualMediaPanel extends MediaPanel // between here and the call to paint() for this tick don't // booch everything _vbounds.x = _nx; _vbounds.y = _ny; + + // let derived classes react if they so desire + viewLocationDidChange(_vbounds.x, _vbounds.y); } } + /** + * Called during our tick when we have adjusted the view location. + */ + protected void viewLocationDidChange (int nx, int ny) + { + } + /** * Implements the standard pathable tracking support. Derived classes * may wish to override this if they desire custom tracking diff --git a/src/java/com/threerings/miso/MisoConfig.java b/src/java/com/threerings/miso/MisoConfig.java index 6566d5495..004f7edfe 100644 --- a/src/java/com/threerings/miso/MisoConfig.java +++ b/src/java/com/threerings/miso/MisoConfig.java @@ -1,10 +1,12 @@ // -// $Id: MisoConfig.java,v 1.1 2002/03/28 22:32:32 mdb Exp $ +// $Id: MisoConfig.java,v 1.2 2003/04/17 19:21:16 mdb Exp $ package com.threerings.miso; import com.samskivert.util.Config; +import com.threerings.miso.util.MisoSceneMetrics; + /** * Provides access to the Miso configuration. */ @@ -12,4 +14,53 @@ public class MisoConfig { /** Provides access to configuration data for this package. */ public static Config config = new Config("rsrc/config/miso/miso"); + + /** + * Creates scene metrics with information obtained from the deployed + * config file. + */ + public static MisoSceneMetrics getSceneMetrics () + { + return new MisoSceneMetrics( + config.getValue(TILE_WIDTH_KEY, DEF_TILE_WIDTH), + config.getValue(TILE_HEIGHT_KEY, DEF_TILE_HEIGHT), + config.getValue(FINE_GRAN_KEY, DEF_FINE_GRAN), + config.getValue(SCENE_VWIDTH_KEY, DEF_SCENE_VWIDTH), + config.getValue(SCENE_VHEIGHT_KEY, DEF_SCENE_VHEIGHT), + config.getValue(SCENE_OFFSET_Y_KEY, DEF_OFFSET_Y)); + } + + /** The config key for tile width in pixels. */ + protected static final String TILE_WIDTH_KEY = "tile_width"; + + /** The config key for tile height in pixels. */ + protected static final String TILE_HEIGHT_KEY = "tile_height"; + + /** The config key for tile fine coordinate granularity. */ + protected static final String FINE_GRAN_KEY = "fine_granularity"; + + /** The config key for scene view width in tile count. */ + protected static final String SCENE_VWIDTH_KEY = "scene_view_width"; + + /** The config key for scene view height in tile count. */ + protected static final String SCENE_VHEIGHT_KEY = "scene_view_height"; + + /** The config key for scene width in tile count. */ + protected static final String SCENE_WIDTH_KEY = "scene_width"; + + /** The config key for scene height in tile count. */ + protected static final String SCENE_HEIGHT_KEY = "scene_height"; + + /** The config key for scene origin vertical offset in tile count. */ + protected static final String SCENE_OFFSET_Y_KEY = "scene_offset_y"; + + /** Default scene view parameters. */ + protected static final int DEF_TILE_WIDTH = 64; + protected static final int DEF_TILE_HEIGHT = 48; + protected static final int DEF_FINE_GRAN = 4; + protected static final int DEF_SCENE_VWIDTH = 10; + protected static final int DEF_SCENE_VHEIGHT = 12; + protected static final int DEF_SCENE_WIDTH = 22; + protected static final int DEF_SCENE_HEIGHT = 22; + protected static final int DEF_OFFSET_Y = -5; } diff --git a/src/java/com/threerings/miso/client/DirtyItemList.java b/src/java/com/threerings/miso/client/DirtyItemList.java index 8fc30477c..d053bd516 100644 --- a/src/java/com/threerings/miso/client/DirtyItemList.java +++ b/src/java/com/threerings/miso/client/DirtyItemList.java @@ -1,5 +1,5 @@ // -// $Id: DirtyItemList.java,v 1.24 2003/04/07 23:32:47 mdb Exp $ +// $Id: DirtyItemList.java,v 1.25 2003/04/17 19:21:16 mdb Exp $ package com.threerings.miso.client; @@ -13,15 +13,14 @@ import java.awt.Shape; import java.util.ArrayList; import java.util.Comparator; -import com.samskivert.util.RuntimeAdjust; import com.samskivert.util.SortableArrayList; import com.samskivert.util.StringUtil; import com.threerings.media.Log; import com.threerings.media.sprite.Sprite; import com.threerings.media.tile.ObjectTile; + import com.threerings.miso.MisoPrefs; -import com.threerings.miso.client.util.IsoUtil; /** * The dirty item list keeps track of dirty sprites and object tiles @@ -33,9 +32,8 @@ public class DirtyItemList * Creates a dirt item list that will handle dirty items for the * specified view. */ - public DirtyItemList (IsoSceneView view) + public DirtyItemList () { - _view = view; } /** @@ -49,7 +47,7 @@ public class DirtyItemList public void appendDirtySprite (Sprite sprite, int tx, int ty) { DirtyItem item = getDirtyItem(); - item.init(sprite, null, null, tx, ty); + item.init(sprite, tx, ty); _items.add(item); } @@ -58,13 +56,11 @@ public class DirtyItemList * item list. * * @param scene the scene object that is dirty. - * @param footprint the footprint of the object tile if it should be - * rendered, null otherwise. */ - public void appendDirtyObject (DisplayObjectInfo info, Shape footprint) + public void appendDirtyObject (SceneObject scobj) { DirtyItem item = getDirtyItem(); - item.init(info, info.bounds, footprint, info.x, info.y); + item.init(scobj, scobj.info.x, scobj.info.y); _items.add(item); } @@ -257,13 +253,6 @@ public class DirtyItemList /** The dirtied object; one of either a sprite or an object tile. */ public Object obj; - /** The bounds of the dirty item if it's an object tile. */ - public Rectangle bounds; - - /** The footprint of the dirty item if it's an object tile and - * we're drawing footprints. */ - public Shape footprint; - /** The origin tile coordinates. */ public int ox, oy; @@ -276,12 +265,9 @@ public class DirtyItemList /** * Initializes a dirty item. */ - public void init (Object obj, Rectangle bounds, Shape footprint, - int x, int y) + public void init (Object obj, int x, int y) { this.obj = obj; - this.bounds = bounds; - this.footprint = footprint; this.ox = x; this.oy = y; @@ -290,8 +276,8 @@ public class DirtyItemList // rightmost tiles are equivalent lx = rx = ox; ly = ry = oy; - if (obj instanceof DisplayObjectInfo) { - ObjectTile tile = ((DisplayObjectInfo)obj).tile; + if (obj instanceof SceneObject) { + ObjectTile tile = ((SceneObject)obj).tile; lx -= (tile.getBaseWidth() - 1); ry -= (tile.getBaseHeight() - 1); } @@ -304,47 +290,10 @@ public class DirtyItemList */ public void paint (Graphics2D gfx) { - // if there's a footprint, paint that - if (footprint != null) { - gfx.setColor(Color.black); - gfx.draw(footprint); - } - - // paint the item if (obj instanceof Sprite) { ((Sprite)obj).paint(gfx); - } else if (!_hideObjects.getValue()) { - ((DisplayObjectInfo)obj).tile.paint(gfx, bounds.x, bounds.y); - } - - // and paint the object's spot if it has one - if (footprint != null && obj instanceof DisplayObjectInfo) { - DisplayObjectInfo info = (DisplayObjectInfo)obj; - if (info.tile.hasSpot()) { - // get the spot's center coordinate - Point fpos = _view.getObjectSpot(info); - Point spos = _view.getScreenCoords(fpos.x, fpos.y); - - // translate the origin to center on the portal - gfx.translate(spos.x, spos.y); - - // rotate to reflect the spot orientation - double rot = (Math.PI / 4.0f) * - info.tile.getSpotOrient(); - gfx.rotate(rot); - - // draw the spot triangle - gfx.setColor(Color.green); - gfx.fill(_spotTri); - - // outline the triangle in black - gfx.setColor(Color.black); - gfx.draw(_spotTri); - - // restore the original transform - gfx.rotate(-rot); - gfx.translate(-spos.x, -spos.y); - } + } else { + ((SceneObject)obj).paint(gfx); } } @@ -363,8 +312,8 @@ public class DirtyItemList */ public int getRenderPriority () { - if (obj instanceof DisplayObjectInfo) { - return ((DisplayObjectInfo)obj).getPriority(); + if (obj instanceof SceneObject) { + return ((SceneObject)obj).getPriority(); } else { return 0; } @@ -378,7 +327,6 @@ public class DirtyItemList public void clear () { obj = null; - bounds = null; } // documentation inherited @@ -475,11 +423,11 @@ public class DirtyItemList // if the two objects are scene objects and they overlap, we // compare them solely based on their human assigned priority - if ((da.obj instanceof DisplayObjectInfo) && - (db.obj instanceof DisplayObjectInfo)) { - DisplayObjectInfo soa = (DisplayObjectInfo)da.obj; - DisplayObjectInfo sob = (DisplayObjectInfo)db.obj; - if (IsoUtil.objectFootprintsOverlap(soa, sob)) { + if ((da.obj instanceof SceneObject) && + (db.obj instanceof SceneObject)) { + SceneObject soa = (SceneObject)da.obj; + SceneObject sob = (SceneObject)db.obj; + if (soa.objectFootprintOverlaps(sob)) { int result = soa.getPriority() - sob.getPriority(); if (DEBUG_COMPARE) { String items = DirtyItemList.toString(da, db); @@ -674,9 +622,6 @@ public class DirtyItemList } } - /** The view for which we're managing dirty items. */ - protected IsoSceneView _view; - /** The list of dirty items. */ protected SortableArrayList _items = new SortableArrayList(); @@ -695,16 +640,6 @@ public class DirtyItemList /** Unused dirty items. */ protected ArrayList _freelist = new ArrayList(); - /** The triangle used to render an object's spot. */ - protected static Polygon _spotTri; - - static { - _spotTri = new Polygon(); - _spotTri.addPoint(-3, -3); - _spotTri.addPoint(3, -3); - _spotTri.addPoint(0, 3); - }; - /** Whether to log debug info when comparing pairs of dirty items. */ protected static final boolean DEBUG_COMPARE = false; @@ -733,10 +668,4 @@ public class DirtyItemList ((DirtyItem)o2).getRearDepth()); } }; - - /** A debug hook that toggles debug rendering of object footprints. */ - protected static RuntimeAdjust.BooleanAdjust _hideObjects = - new RuntimeAdjust.BooleanAdjust( - "Turns off the rendering of objects in the scene.", - "narya.miso.hide_objects", MisoPrefs.config, false); } diff --git a/src/java/com/threerings/miso/client/DisplayMisoScene.java b/src/java/com/threerings/miso/client/DisplayMisoScene.java deleted file mode 100644 index 2acfb30b6..000000000 --- a/src/java/com/threerings/miso/client/DisplayMisoScene.java +++ /dev/null @@ -1,45 +0,0 @@ -// -// $Id: DisplayMisoScene.java,v 1.12 2003/04/12 02:14:52 mdb Exp $ - -package com.threerings.miso.client; - -import com.threerings.media.tile.Tile; - -import com.threerings.miso.client.util.AStarPathUtil; -import com.threerings.miso.data.MisoScene; -import com.threerings.miso.tile.BaseTile; - -/** - * Extends the {@link MisoScene} with functionality needed only by - * entities that plan to display a miso scene. - */ -public interface DisplayMisoScene - extends MisoScene, AStarPathUtil.TraversalPred -{ - /** - * This will be called before the scene is displayed to give it a - * chance to look up its image data and prepare itself for display. - */ - public void init (); - - /** - * Returns the base tile at the specified coordinates. - */ - public BaseTile getBaseTile (int x, int y); - - /** - * Returns the fringe tile at the specified coordinates. - */ - public Tile getFringeTile (int x, int y); - - /** - * Returns true if the supplied traverser can traverse the specified - * tile coordinate. The traverser is whatever object is passed along - * to the path finder when a path is being computed. - * - *
Scene implementations which support custom traversal based on - * the type of the traverser will want to reflect the traverser's - * class and act acordingly. - */ - public boolean canTraverse (Object traverser, int x, int y); -} diff --git a/src/java/com/threerings/miso/client/DisplayObjectInfo.java b/src/java/com/threerings/miso/client/DisplayObjectInfo.java deleted file mode 100644 index 300fe7089..000000000 --- a/src/java/com/threerings/miso/client/DisplayObjectInfo.java +++ /dev/null @@ -1,87 +0,0 @@ -// -// $Id: DisplayObjectInfo.java,v 1.8 2003/02/12 05:37:19 mdb Exp $ - -package com.threerings.miso.client; - -import java.awt.Rectangle; - -import com.threerings.media.tile.ObjectTile; -import com.threerings.miso.data.ObjectInfo; - -/** - * Used to track information about an object in the scene. - */ -public class DisplayObjectInfo extends ObjectInfo -{ - /** A reference to the object tile itself. */ - public ObjectTile tile; - - /** The object's bounding rectangle. This will be filled in - * automatically by the scene view when the object is used. */ - public Rectangle bounds; - - /** - * Convenience constructor. - */ - public DisplayObjectInfo (int tileId, int x, int y) - { - super(tileId, x, y); - } - - /** - * Convenience constructor. - */ - public DisplayObjectInfo (ObjectInfo source) - { - super(source); - } - - /** - * Provides this display object with a reference to its object tile - * when it becomes available. This must be called before the tile is - * used in any sort of display circumstances. - */ - public void setObjectTile (ObjectTile tile) - { - this.tile = tile; - } - - /** - * Returns the render priority of this object tile. - */ - public int getPriority () - { - // if we have no specified priority return our object tile's - // default priority - return (priority == 0 && tile != null) ? tile.getPriority() : priority; - } - - /** - * Overrides the render priority of this object. - */ - public void setPriority (byte priority) - { - this.priority = (byte)Math.max( - Byte.MIN_VALUE, Math.min(Byte.MAX_VALUE, priority)); - } - - /** - * Indicate to the scene object that it is being hovered over. - * - * @return true if the object should be repainted. - */ - public boolean setHovered (boolean hovered) - { - return false; - } - - /** - * Handles the toString-ification of all public members. Derived - * classes can override and include non-public members if desired. - */ - protected void toString (StringBuffer buf) - { - super.toString(buf); - buf.append(", rprio=").append(getPriority()); - } -} diff --git a/src/java/com/threerings/miso/client/IsoSceneView.java b/src/java/com/threerings/miso/client/IsoSceneView.java deleted file mode 100644 index c87f8137a..000000000 --- a/src/java/com/threerings/miso/client/IsoSceneView.java +++ /dev/null @@ -1,796 +0,0 @@ -// -// $Id: IsoSceneView.java,v 1.137 2003/04/12 02:14:52 mdb Exp $ - -package com.threerings.miso.client; - -import java.awt.AlphaComposite; -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Composite; -import java.awt.EventQueue; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Graphics2D; -import java.awt.Graphics; -import java.awt.Point; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.Shape; -import java.awt.Stroke; -import java.awt.event.MouseEvent; - -import java.util.ArrayList; -import java.util.List; - -import com.samskivert.util.HashIntMap; -import com.samskivert.util.RuntimeAdjust; -import com.samskivert.util.StringUtil; - -import com.threerings.media.RegionManager; - -import com.threerings.media.sprite.Sprite; -import com.threerings.media.sprite.SpriteManager; -import com.threerings.media.util.Path; - -import com.threerings.media.tile.ObjectTile; -import com.threerings.media.tile.Tile; - -import com.threerings.miso.Log; -import com.threerings.miso.MisoPrefs; -import com.threerings.miso.client.DirtyItemList.DirtyItem; -import com.threerings.miso.client.util.AStarPathUtil; -import com.threerings.miso.client.util.IsoUtil; -import com.threerings.miso.client.util.ObjectSet; -import com.threerings.miso.tile.BaseTile; - -/** - * The iso scene view provides an isometric view of a particular scene. It - * presently supports scrolling in a limited form. Object tiles are not - * handled properly, nor is mouse highlighting. Those should only be used - * if the view will not be scrolled. - */ -public class IsoSceneView implements SceneView -{ - /** Instructs the scene view never to draw highlights around object - * tiles. */ - public static final int HIGHLIGHT_NEVER = 0; - - /** Instructs the scene view to highlight only object tiles that have - * a non-empty action string. */ - public static final int HIGHLIGHT_WITH_ACTION = 1; - - /** Instructs the scene view to highlight every object tile, - * regardless of whether it has a valid action string. */ - public static final int HIGHLIGHT_ALWAYS = 2; - - /** Instructs the scene view to highlight whatever tile the mouse is - * over, regardless of whether or not it is an object tile. This is - * generally only useful in an editor rather than a game. */ - public static final int HIGHLIGHT_ALL = 3; - - /** - * Constructs an iso scene view. - * - * @param spritemgr the sprite manager. - * @param model the data model. - * @param remgr the region manager that is collecting invalid regions - * for this view. - */ - public IsoSceneView (SpriteManager spritemgr, IsoSceneViewModel model, - RegionManager remgr) - { - // save off references - _spritemgr = spritemgr; - _model = model; - _remgr = remgr; - - // handy rectangle - _tbounds = new Rectangle(0, 0, _model.tilewid, _model.tilehei); - } - - /** - * Configures the scene view to highlight object tiles either never - * ({@link #HIGHLIGHT_NEVER}), only when an object tile has an - * associated action string ({@link #HIGHLIGHT_WITH_ACTION}), or - * always ({@link #HIGHLIGHT_ALWAYS}). It is also possible to - * configure the view to highlight whatever tile is under the cursor, - * even if it's not an object tile which is done in the {@link - * #HIGHLIGHT_ALL} mode. - */ - public void setHighlightMode (int hmode) - { - _hmode = hmode; - } - - // documentation inherited - public void setScene (DisplayMisoScene scene) - { - _scene = scene; - _scene.init(); - - // obtain a list of the objects in the scene and generate records - // for each of them that contain precomputed metrics - refreshObjectList(); - - // invalidate the entire screen as there's a new scene in town; - // making sure we're on the AWT thread - if (EventQueue.isDispatchThread()) { - invalidate(); - } else { - EventQueue.invokeLater(new Runnable() { - public void run () { - invalidate(); - } - }); - } - } - - /** - * Big fat HACKola: checks the display scene for new objects that - * weren't there last time around and adds info for them into the - * scene. - */ - public void refreshObjectList () - { - _objects.clear(); - - // grab all available objects - Rectangle rect = new Rectangle(Short.MIN_VALUE, Short.MIN_VALUE, - 2*Short.MAX_VALUE, 2*Short.MAX_VALUE); - _scene.getObjects(rect, _objects); - addAdditionalObjects(_objects); - - // and fill in the new objects' bounds - int ocount = _objects.size(); - for (int ii = 0; ii < ocount; ii++) { - DisplayObjectInfo scobj = (DisplayObjectInfo)_objects.get(ii); - if (scobj.bounds == null) { - scobj.bounds = IsoUtil.getObjectBounds(_model, scobj); - } - } - } - - // documentation inherited - public DisplayMisoScene getScene () - { - return _scene; - } - - /** - * Invalidate the entire visible scene view. - */ - public void invalidate () - { - _remgr.invalidateRegion(_model.bounds); - } - - /** - * Returns the location associated with the specified object's "spot" - * in fine coordinates or null if the object has no spot. - */ - public Point getObjectSpot (DisplayObjectInfo info) - { - if (info.tile.hasSpot()) { - return IsoUtil.tilePlusFineToFull( - _model, info.x, info.y, info.tile.getSpotX(), - info.tile.getSpotY(), new Point()); - } else { - return null; - } - } - - // documentation inherited from interface - public void paint (Graphics2D gfx, Rectangle dirtyRect) - { - if (_scene == null) { - Log.warning("Scene view painted with null scene."); - return; - } - - // render any intersecting tiles - renderTiles(gfx, dirtyRect); - - // render anything that goes on top of the tiles - renderBaseDecorations(gfx, dirtyRect); - - // render our dirty sprites and objects - renderDirtyItems(gfx, dirtyRect); - - // draw sprite paths - if (_pathsDebug.getValue()) { - _spritemgr.renderSpritePaths(gfx); - } - - // paint our highlighted tile (if any) - paintHighlights(gfx, dirtyRect); - - // paint any extra goodies - paintExtras(gfx, dirtyRect); - } - - /** - * Paints the highlighted tile. - * - * @param gfx the graphics context. - */ - protected void paintHighlights (Graphics2D gfx, Rectangle clip) - { - // if we're not highlighting anything, bail now - if (_hmode == HIGHLIGHT_NEVER) { - return; - } - - Polygon hpoly = null; - - // if we have a hover object, do some business - if (_hobject != null && _hobject instanceof DisplayObjectInfo) { - DisplayObjectInfo scobj = (DisplayObjectInfo)_hobject; - if (scobj.action != null || _hmode == HIGHLIGHT_ALWAYS) { - hpoly = IsoUtil.getObjectFootprint(_model, scobj); - } - } - - // if we had no valid hover object, but we're in HIGHLIGHT_ALWAYS, - // go for the tile outline - if (hpoly == null && _hmode == HIGHLIGHT_ALWAYS) { - hpoly = IsoUtil.getTilePolygon(_model, _hcoords.x, _hcoords.y); - } - - if (hpoly != null) { - // set the desired stroke and color - Stroke ostroke = gfx.getStroke(); - gfx.setStroke(_hstroke); - gfx.setColor(Color.green); - - // draw the outline - gfx.draw(hpoly); - - // restore the original stroke - gfx.setStroke(ostroke); - } - } - - /** - * A function where derived classes can paint extra stuff while we've - * got the clipping region set up. - */ - protected void paintExtras (Graphics2D gfx, Rectangle clip) - { - // nothing for now - } - - /** - * Renders the base and fringe layer tiles that intersect the - * specified clipping rectangle. - */ - protected void renderTiles (Graphics2D gfx, Rectangle clip) - { - // if we're showing coordinates, we need to do some setting up - int thw = 0, thh = 0, fhei = 0; - FontMetrics fm = null; - if (_coordsDebug.getValue()) { - fm = gfx.getFontMetrics(_font); - fhei = fm.getAscent(); - thw = _model.tilehwid; - thh = _model.tilehhei; - gfx.setFont(_font); - } - - // determine which tiles intersect this clipping region: this is - // going to be nearly incomprehensible without some sort of - // diagram; i'll do what i can to comment it, but you'll want to - // print out a scene diagram (docs/miso/scene.ps) and start making - // notes if you want to follow along - - // obtain our upper left tile - Point tpos = IsoUtil.screenToTile(_model, clip.x, clip.y, new Point()); - - // determine which quadrant of the upper left tile we occupy - Point spos = IsoUtil.tileToScreen(_model, tpos.x, tpos.y, new Point()); - boolean left = (clip.x - spos.x < _model.tilehwid); - boolean top = (clip.y - spos.y < _model.tilehhei); - - // set up our tile position counters - int dx, dy; - if (left) { - dx = 0; dy = 1; - } else { - dx = 1; dy = 0; - } - - // if we're in the top-half of the tile we need to move up a row, - // either forward or back depending on whether we're in the left - // or right half of the tile - if (top) { - if (left) { - tpos.x -= 1; - } else { - tpos.y -= 1; - } - // we'll need to start zig-zagging the other way as well - dx = 1 - dx; - dy = 1 - dy; - } - - // these will bound our loops - int rightx = clip.x + clip.width, bottomy = clip.y + clip.height; - -// Log.info("Preparing to render [tpos=" + StringUtil.toString(tpos) + -// ", left=" + left + ", top=" + top + -// ", clip=" + StringUtil.toString(clip) + -// ", spos=" + StringUtil.toString(spos) + -// "]."); - - // obtain the coordinates of the tile that starts the first row - // and loop through, rendering the intersecting tiles - IsoUtil.tileToScreen(_model, tpos.x, tpos.y, spos); - while (spos.y < bottomy) { - // set up our row counters - int tx = tpos.x, ty = tpos.y; - _tbounds.x = spos.x; - _tbounds.y = spos.y; - -// Log.info("Rendering row [tx=" + tx + ", ty=" + ty + "]."); - - // render the tiles in this row - while (_tbounds.x < rightx) { - // draw the base and fringe tile images - try { - Tile tile; - boolean passable = true; - - if ((tile = _scene.getBaseTile(tx, ty)) != null) { - tile.paint(gfx, _tbounds.x, _tbounds.y); - passable = ((BaseTile)tile).isPassable(); - - // highlight impassable tiles - if (_traverseDebug.getValue() && !passable) { - fillTile(gfx, tx, ty, Color.yellow); - } - - } else { - // draw black where there are no tiles - Polygon poly = IsoUtil.getTilePolygon(_model, tx, ty); - gfx.setColor(Color.black); - gfx.fill(poly); - } - - if ((tile = _scene.getFringeTile(tx, ty)) != null) { - tile.paint(gfx, _tbounds.x, _tbounds.y); - } - - // highlight passable non-traversable tiles - if (_traverseDebug.getValue() && passable && - !_scene.canTraverse(null, tx, ty)) { - fillTile(gfx, tx, ty, Color.green); - } - - } catch (ArrayIndexOutOfBoundsException e) { - Log.warning("Whoops, booched it [tx=" + tx + - ", ty=" + ty + ", tb.x=" + _tbounds.x + - ", rightx=" + rightx + "]."); - } - - // if we're showing coordinates, do that - if (_coordsDebug.getValue()) { - gfx.setColor(Color.white); - - // get the top-left screen coordinates of the tile - int sx = _tbounds.x, sy = _tbounds.y; - - // draw x-coordinate - String str = String.valueOf(tx); - int xpos = sx + thw - (fm.stringWidth(str) / 2); - gfx.drawString(str, xpos, sy + thh); - - // draw y-coordinate - str = String.valueOf(ty); - xpos = sx + thw - (fm.stringWidth(str) / 2); - gfx.drawString(str, xpos, sy + thh + fhei); - - // draw the tile polygon as well - gfx.draw(IsoUtil.getTilePolygon(_model, tx, ty)); - } - - // move one tile to the right - tx += 1; ty -= 1; - _tbounds.x += _model.tilewid; - } - - // update our tile coordinates - tpos.x += dx; dx = 1-dx; - tpos.y += dy; dy = 1-dy; - - // obtain the screen coordinates of the next starting tile - IsoUtil.tileToScreen(_model, tpos.x, tpos.y, spos); - } - } - - /** - * Fills the specified tile with the given color at 50% alpha. - * Intended for debug-only tile highlighting purposes. - */ - protected void fillTile ( - Graphics2D gfx, int tx, int ty, Color color) - { - Composite ocomp = gfx.getComposite(); - gfx.setComposite(ALPHA_FILL_TILE); - Polygon poly = IsoUtil.getTilePolygon(_model, tx, ty); - gfx.setColor(color); - gfx.fill(poly); - gfx.setComposite(ocomp); - } - - /** - * A function where derived classes can paint things after the base - * tiles have been rendered but before anything else has been rendered - * (so that whatever is painted appears to be on the ground). - */ - protected void renderBaseDecorations (Graphics2D gfx, Rectangle clip) - { - // nothing for now - } - - /** - * Renders the dirty sprites and objects in the scene to the given - * graphics context. - */ - protected void renderDirtyItems (Graphics2D gfx, Rectangle clip) - { - // if we don't yet have a scene, do nothing - if (_scene == null) { - return; - } - - // add any sprites impacted by the dirty rectangle - _dirtySprites.clear(); - _spritemgr.getIntersectingSprites(_dirtySprites, clip); - int size = _dirtySprites.size(); - for (int ii = 0; ii < size; ii++) { - Sprite sprite = (Sprite)_dirtySprites.get(ii); - Rectangle bounds = sprite.getBounds(); - if (!bounds.intersects(clip)) { - continue; - } - appendDirtySprite(_dirtyItems, sprite); - // Log.info("Dirtied item: " + sprite); - } - - // add any objects impacted by the dirty rectangle - int ocount = _objects.size(); - for (int ii = 0; ii < ocount; ii++) { - DisplayObjectInfo scobj = (DisplayObjectInfo)_objects.get(ii); - if (!scobj.bounds.intersects(clip)) { - continue; - } - - // compute the footprint if we're rendering those - Polygon foot = null; - if (_fprintDebug.getValue()) { - foot = IsoUtil.getObjectFootprint(_model, scobj); - } - - _dirtyItems.appendDirtyObject(scobj, foot); - // Log.info("Dirtied item: Object(" + - // scobj.x + ", " + scobj.y + ")"); - } - -// Log.info("renderDirtyItems [items=" + _dirtyItems.size() + "]."); - - // sort the dirty sprites and objects visually back-to-front; - // paint them and be done - _dirtyItems.sort(); - _dirtyItems.paintAndClear(gfx); - } - - /** - * Computes the tile coordinates of the supplied sprite and appends it - * to the supplied dirty item list. - */ - protected void appendDirtySprite (DirtyItemList list, Sprite sprite) - { - IsoUtil.screenToTile(_model, sprite.getX(), sprite.getY(), _tcoords); - list.appendDirtySprite(sprite, _tcoords.x, _tcoords.y); - } - - /** - * A place for subclasses to add any additional scene objects they - * may have. - */ - protected void addAdditionalObjects (ObjectSet set) - { - // nothing by default - } - - // documentation inherited - public Path getPath (Sprite sprite, int x, int y) - { - // make sure we have a scene - if (_scene == null) { - return null; - } - - // get the destination tile coordinates - Point src = IsoUtil.screenToTile( - _model, sprite.getX(), sprite.getY(), new Point()); - Point dest = IsoUtil.screenToTile(_model, x, y, new Point()); - - // TODO: compute this value from the screen size or something - int longestPath = 50; - - // get a reasonable tile path through the scene - List points = AStarPathUtil.getPath( - _scene, sprite, longestPath, src.x, src.y, dest.x, dest.y); - - // construct a path object to guide the sprite on its merry way - return (points == null) ? null : - new TilePath(_model, sprite, points, x, y); - } - - // documentation inherited - public Point getScreenCoords (int x, int y) - { - return IsoUtil.fullToScreen(_model, x, y, new Point()); - } - - // documentation inherited - public Point getFullCoords (int x, int y) - { - return IsoUtil.screenToFull(_model, x, y, new Point()); - } - - // documentation inherited - public Point getTileCoords (int x, int y) - { - return IsoUtil.screenToTile(_model, x, y, new Point()); - } - - // documentation inherited - public boolean mouseMoved (MouseEvent e) - { - int x = e.getX(), y = e.getY(); - boolean repaint = false; - - // update the mouse's tile coordinates - boolean newtile = updateTileCoords(x, y, _hcoords); - // if we're highlighting base tiles, we may need to repaint - if (_hmode == HIGHLIGHT_ALL) { - repaint = (newtile || repaint); - } - - // compute the list of objects over which the mouse is hovering - Object hobject = null; - - // start with the sprites that contain the point - _spritemgr.getHitSprites(_hitSprites, x, y); - int hslen = _hitSprites.size(); - for (int i = 0; i < hslen; i++) { - Sprite sprite = (Sprite)_hitSprites.get(i); - appendDirtySprite(_hitList, sprite); - } - - // add the object tiles that contain the point - getHitObjects(_hitList, x, y); - - // sort the list of hit items by rendering order - _hitList.sort(); - - // the last element in the array is what we want (assuming there - // are any items in the array) - int icount = _hitList.size(); - if (icount > 0) { - DirtyItem item = (DirtyItem)_hitList.get(icount-1); - hobject = item.obj; - } - - repaint |= changeHoverObject(hobject); - - // clear out the hitlists - _hitList.clear(); - _hitSprites.clear(); - - return repaint; - } - - /** - * Change the hover object to the new object. - * - * @return true if we need to repaint the entire scene. Bah! - */ - protected boolean changeHoverObject (Object newHover) - { - if (newHover == _hobject) { - return false; // no change, no repaint - } - - // unhover the old - if (_hobject instanceof DisplayObjectInfo) { - DisplayObjectInfo oldhov = (DisplayObjectInfo) _hobject; - if (oldhov.setHovered(false)) { - _remgr.invalidateRegion(oldhov.bounds); - } - } - - hoverObjectChanged(_hobject, newHover); - // set the new - _hobject = newHover; - - // hover the new - if (_hobject instanceof DisplayObjectInfo) { - DisplayObjectInfo newhov = (DisplayObjectInfo) _hobject; - if (newhov.setHovered(true)) { - _remgr.invalidateRegion(newhov.bounds); - } - } - - return (_hmode != HIGHLIGHT_NEVER); - } - - /** - * A place for subclasses to react to the hover object changing. - * One of the supplied arguments may be null. - */ - protected void hoverObjectChanged (Object oldHover, Object newHover) - { - // nothing by default - } - - /** - * Adds to the supplied dirty item list, all of the object tiles that - * are hit by the specified point (meaning the point is contained - * within their bounds and intersects a non-transparent pixel in the - * actual object image. - */ - protected void getHitObjects (DirtyItemList list, int x, int y) - { - int ocount = _objects.size(); - for (int ii = 0; ii < ocount; ii++) { - DisplayObjectInfo scobj = (DisplayObjectInfo)_objects.get(ii); - Rectangle pbounds = scobj.bounds; - // skip bounding rects that don't contain the point - if (!pbounds.contains(x, y)) { - continue; - } - - // now check that the pixel in the tile image is - // non-transparent at that point - if (!scobj.tile.hitTest(x - pbounds.x, y - pbounds.y)) { - continue; - } - - // we've passed the test, add the object to the list - list.appendDirtyObject(scobj, null); - } - } - - // documentation inherited - public void mouseExited (MouseEvent e) - { - // clear the highlight tracking data - _hcoords.setLocation(-1, -1); - changeHoverObject(null); - } - - // documentation inherited - public Object getHoverObject () - { - return _hobject; - } - - /** - * Returns the tile coordinates of the tile over which the mouse is - * hovering. - */ - public Point getHoverCoords () - { - return _hcoords; - } - - /** - * Converts the supplied screen coordinates into tile coordinates, - * writing the values into the supplied {@link Point} instance and - * returning true if the screen coordinates translated into a - * different set of tile coordinates than were already contained in - * the point (so that the caller can know to update a highlight, for - * example). - * - * @return true if the tile coordinates have changed. - */ - protected boolean updateTileCoords (int sx, int sy, Point tpos) - { - Point npos = IsoUtil.screenToTile(_model, sx, sy, new Point()); - - // make sure the new coordinate is both valid and different - if (_model.isCoordinateValid(npos.x, npos.y) && !tpos.equals(npos)) { - tpos.setLocation(npos.x, npos.y); - return true; - - } else { - return false; - } - } - - /** The sprite manager. */ - protected SpriteManager _spritemgr; - - /** The scene view model data. */ - protected IsoSceneViewModel _model; - - /** Our region manager. */ - protected RegionManager _remgr; - - /** The scene to be displayed. */ - protected DisplayMisoScene _scene; - - /** Information for all of the objects visible in the scene. */ - protected ObjectSet _objects = new ObjectSet(); - - /** The dirty sprites and objects that need to be re-painted. */ - protected DirtyItemList _dirtyItems = new DirtyItemList(this); - - /** The working sprites list used when calculating dirty regions. */ - protected ArrayList _dirtySprites = new ArrayList(); - - /** Used when rendering tiles. */ - protected Rectangle _tbounds; - - /** Used when dirtying sprites. */ - protected Point _tcoords = new Point(); - - /** Used to collect the list of sprites "hit" by a particular mouse - * location. */ - protected List _hitSprites = new ArrayList(); - - /** The list that we use to track and sort the items over which the - * mouse is hovering. */ - protected DirtyItemList _hitList = new DirtyItemList(this); - - /** The highlight mode. */ - protected int _hmode = HIGHLIGHT_NEVER; - - /** Info on the object that the mouse is currently hovering over. */ - protected Object _hobject; - - /** Used to track the tile coordinates over which the mouse is hovering. */ - protected Point _hcoords = new Point(); - - /** The font to draw tile coordinates. */ - protected Font _font = new Font("Arial", Font.PLAIN, 7); - - /** The stroke object used to draw highlighted tiles and coordinates. */ - protected BasicStroke _hstroke = new BasicStroke(2); - - /** A debug hook that toggles debug rendering of traversable tiles. */ - protected static RuntimeAdjust.BooleanAdjust _traverseDebug = - new RuntimeAdjust.BooleanAdjust( - "Toggles debug rendering of traversable and impassable tiles in " + - "the iso scene view.", "narya.miso.iso_traverse_debug_render", - MisoPrefs.config, false); - - /** A debug hook that toggles debug rendering of tile coordinates. */ - protected static RuntimeAdjust.BooleanAdjust _coordsDebug = - new RuntimeAdjust.BooleanAdjust( - "Toggles debug rendering of tile coordinates in the iso scene " + - "view.", "narya.miso.iso_coords_debug_render", - MisoPrefs.config, false); - - /** A debug hook that toggles debug rendering of sprite paths. */ - protected static RuntimeAdjust.BooleanAdjust _pathsDebug = - new RuntimeAdjust.BooleanAdjust( - "Toggles debug rendering of sprite paths in the iso scene view.", - "narya.miso.iso_paths_debug_render", MisoPrefs.config, false); - - /** A debug hook that toggles debug rendering of object footprints. */ - protected static RuntimeAdjust.BooleanAdjust _fprintDebug = - new RuntimeAdjust.BooleanAdjust( - "Toggles debug rendering of object footprints in the iso scene " + - "view.", "narya.miso.iso_fprint_debug_render", - MisoPrefs.config, false); - - /** The stroke used to draw dirty rectangles. */ - protected static final Stroke DIRTY_RECT_STROKE = new BasicStroke(2); - - /** The alpha used to fill tiles for debugging purposes. */ - protected static final Composite ALPHA_FILL_TILE = - AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f); -} diff --git a/src/java/com/threerings/miso/client/IsoSceneViewModel.java b/src/java/com/threerings/miso/client/IsoSceneViewModel.java deleted file mode 100644 index 04e33cf28..000000000 --- a/src/java/com/threerings/miso/client/IsoSceneViewModel.java +++ /dev/null @@ -1,222 +0,0 @@ -// -// $Id: IsoSceneViewModel.java,v 1.29 2003/04/12 02:14:52 mdb Exp $ - -package com.threerings.miso.client; - -import java.awt.Point; -import java.awt.Rectangle; - -import com.threerings.miso.Log; -import com.threerings.miso.MisoConfig; -import com.threerings.miso.client.util.IsoUtil; - -/** - * Provides a holding place for the myriad parameters and bits of data - * that describe the details of an isometric view of a scene. - * - *
The member data are public to facilitate speedy referencing by the - * {@link IsoSceneView} class. The model should only be modified through - * the configuration data provided via {@link MisoConfig} and the accessor - * methods. - */ -public class IsoSceneViewModel -{ - /** Tile dimensions and half-dimensions in the view. */ - public int tilewid, tilehei, tilehwid, tilehhei; - - /** Fine coordinate dimensions. */ - public int finehwid, finehhei; - - /** Number of fine coordinates on each axis within a tile. */ - public int finegran; - - /** Size of the view in tile count. */ - public int scenevwid, scenevhei; - - /** Whether or not this view can extend beyond the bounds defined by - * the view width and height. True if it cannot, false if it can. */ - public boolean bounded = false; - - /** The bounds of the view in screen pixel coordinates. */ - public Rectangle bounds; - - /** The position in pixels at which tile (0, 0) is drawn. */ - public Point origin; - - /** The length of a tile edge in pixels. */ - public float tilelen; - - /** The slope of the x- and y-axis lines. */ - public float slopeX, slopeY; - - /** The length between fine coordinates in pixels. */ - public float finelen; - - /** The y-intercept of the x-axis line within a tile. */ - public float fineBX; - - /** The slope of the x- and y-axis lines within a tile. */ - public float fineSlopeX, fineSlopeY; - - /** - * Construct an iso scene view model with view parameters as - * specified in the given config object. - * - * @param config the config object. - */ - public IsoSceneViewModel () - { - // and the view dimensions - scenevwid = MisoConfig.config.getValue( - SCENE_VWIDTH_KEY, DEF_SCENE_VWIDTH); - scenevhei = MisoConfig.config.getValue( - SCENE_VHEIGHT_KEY, DEF_SCENE_VHEIGHT); - - // get the tile dimensions - tilewid = MisoConfig.config.getValue(TILE_WIDTH_KEY, DEF_TILE_WIDTH); - tilehei = MisoConfig.config.getValue(TILE_HEIGHT_KEY, DEF_TILE_HEIGHT); - - // set the fine coordinate granularity - finegran = MisoConfig.config.getValue(FINE_GRAN_KEY, DEF_FINE_GRAN); - - // precalculate various things - int offy = MisoConfig.config.getValue(SCENE_OFFSET_Y_KEY, DEF_OFFSET_Y); - precalculate(offy); - } - - /** - * Constructs an iso scene view model by directly specifying the - * desired scene configuration parameters. - * - * @param scenewid the total scene width in tiles. - * @param scenehei the total scene height in tiles. - * @param tilewid the width in pixels of the tiles. - * @param tilehei the height in pixels of the tiles. - * @param finegran the number of sub-tile divisions to use for fine - * coordinates. - * @param svwid the width in tiles of the viewport. - * @param svhei the height in tiles of the viewport. - * @param offy the offset of the origin (in tiles) from the top of the - * viewport. - */ - public IsoSceneViewModel (int scenewid, int scenehei, - int tilewid, int tilehei, int finegran, - int svwid, int svhei, int offy) - { - // keep track of this stuff - this.tilewid = tilewid; - this.tilehei = tilehei; - this.finegran = finegran; - this.scenevwid = svwid; - this.scenevhei = svhei; - - // let our flags default to false - - // precalculate various things - precalculate(offy); - } - - /** - * Returns whether the given tile coordinate is a valid coordinate in - * our coordinate system (which allows tile coordinates from 0 to - * 2^15-1). - */ - public boolean isCoordinateValid (int x, int y) - { - return (x >= 0 && x < Short.MAX_VALUE && - y >= 0 && y < Short.MAX_VALUE); - } - - /** - * Returns whether the given full coordinate is a valid coordinate - * within the scene. - */ - public boolean isFullCoordinateValid (int x, int y) - { - int tx = IsoUtil.fullToTile(x), ty = IsoUtil.fullToTile(y); - int fx = IsoUtil.fullToFine(x), fy = IsoUtil.fullToFine(y); - return (isCoordinateValid(tx, ty) && - fx >= 0 && fx < finegran && - fy >= 0 && fy < finegran); - } - - /** - * Pre-calculate various member data that are commonly used in working - * with an isometric view. - */ - protected void precalculate (int offy) - { - // set the desired scene view bounds - bounds = new Rectangle(0, 0, scenevwid * tilewid, scenevhei * tilehei); - - // set the scene display origin - origin = new Point((bounds.width / 2), (offy * tilehei)); - - // pre-calculate tile-related data - precalculateTiles(); - - // calculate the edge length separating each fine coordinate - finelen = tilelen / (float)finegran; - - // calculate the fine-coordinate x-axis line - fineSlopeX = (float)tilehei / (float)tilewid; - fineBX = -(fineSlopeX * (float)tilehwid); - fineSlopeY = -fineSlopeX; - - // calculate the fine coordinate dimensions - finehwid = (int)((float)tilehwid / (float)finegran); - finehhei = (int)((float)tilehhei / (float)finegran); - } - - /** - * Pre-calculate various tile-related member data. - */ - protected void precalculateTiles () - { - // halve the dimensions - tilehwid = (tilewid / 2); - tilehhei = (tilehei / 2); - - // calculate the length of a tile edge in pixels - tilelen = (float) Math.sqrt( - (tilehwid * tilehwid) + (tilehhei * tilehhei)); - - // calculate the slope of the x- and y-axis lines - slopeX = (float)tilehei / (float)tilewid; - slopeY = -slopeX; - } - - /** The config key for tile width in pixels. */ - protected static final String TILE_WIDTH_KEY = "tile_width"; - - /** The config key for tile height in pixels. */ - protected static final String TILE_HEIGHT_KEY = "tile_height"; - - /** The config key for tile fine coordinate granularity. */ - protected static final String FINE_GRAN_KEY = "fine_granularity"; - - /** The config key for scene view width in tile count. */ - protected static final String SCENE_VWIDTH_KEY = "scene_view_width"; - - /** The config key for scene view height in tile count. */ - protected static final String SCENE_VHEIGHT_KEY = "scene_view_height"; - - /** The config key for scene width in tile count. */ - protected static final String SCENE_WIDTH_KEY = "scene_width"; - - /** The config key for scene height in tile count. */ - protected static final String SCENE_HEIGHT_KEY = "scene_height"; - - /** The config key for scene origin vertical offset in tile count. */ - protected static final String SCENE_OFFSET_Y_KEY = "scene_offset_y"; - - /** Default scene view parameters. */ - protected static final int DEF_TILE_WIDTH = 64; - protected static final int DEF_TILE_HEIGHT = 48; - protected static final int DEF_FINE_GRAN = 4; - protected static final int DEF_SCENE_VWIDTH = 10; - protected static final int DEF_SCENE_VHEIGHT = 12; - protected static final int DEF_SCENE_WIDTH = 22; - protected static final int DEF_SCENE_HEIGHT = 22; - protected static final int DEF_OFFSET_Y = -5; -} diff --git a/src/java/com/threerings/miso/client/MisoScenePanel.java b/src/java/com/threerings/miso/client/MisoScenePanel.java new file mode 100644 index 000000000..923992ad2 --- /dev/null +++ b/src/java/com/threerings/miso/client/MisoScenePanel.java @@ -0,0 +1,1420 @@ +// +// $Id: MisoScenePanel.java,v 1.1 2003/04/17 19:21:16 mdb Exp $ + +package com.threerings.miso.client; + +import java.awt.AlphaComposite; +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Component; +import java.awt.Composite; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Stroke; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +import javax.swing.Icon; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Random; + +import com.samskivert.swing.Controller; +import com.samskivert.swing.RadialMenu; +import com.samskivert.util.HashIntMap; +import com.samskivert.util.RuntimeAdjust; +import com.samskivert.util.StringUtil; + +import com.threerings.media.VirtualMediaPanel; +import com.threerings.media.sprite.Sprite; +import com.threerings.media.tile.Tile; +import com.threerings.media.tile.TileManager; +import com.threerings.media.tile.TileSet; +import com.threerings.media.util.Path; + +import com.threerings.miso.Log; +import com.threerings.miso.MisoPrefs; +import com.threerings.miso.client.DirtyItemList.DirtyItem; +import com.threerings.miso.data.MisoSceneModel; +import com.threerings.miso.data.ObjectInfo; +import com.threerings.miso.tile.BaseTile; +import com.threerings.miso.util.AStarPathUtil; +import com.threerings.miso.util.MisoContext; +import com.threerings.miso.util.MisoSceneMetrics; +import com.threerings.miso.util.MisoUtil; +import com.threerings.miso.util.ObjectSet; + +/** + * Renders a Miso scene for all to see. + */ +public class MisoScenePanel extends VirtualMediaPanel + implements MouseListener, MouseMotionListener, AStarPathUtil.TraversalPred, + RadialMenu.Host +{ + /** Instructs the scene view never to draw highlights around object + * tiles. */ + public static final int HIGHLIGHT_NEVER = 0; + + /** Instructs the scene view to highlight only object tiles that have + * a non-empty action string. */ + public static final int HIGHLIGHT_WITH_ACTION = 1; + + /** Instructs the scene view to highlight every object tile, + * regardless of whether it has a valid action string. */ + public static final int HIGHLIGHT_ALWAYS = 2; + + /** Instructs the scene view to highlight whatever tile the mouse is + * over, regardless of whether or not it is an object tile. This is + * generally only useful in an editor rather than a game. */ + public static final int HIGHLIGHT_ALL = 3; + + /** Show flag that indicates we should show all tips. */ + public static final int SHOW_TIPS = (1 << 0); + + /** Show flag that indicates we should show everything. */ + public static final int SHOW_ALL = 0xFFFFFF; + + /** + * Creates a blank miso scene display. Configure it with a scene model + * via {@link #setSceneModel} to cause it to display something. + */ + public MisoScenePanel (MisoContext ctx, MisoSceneMetrics metrics) + { + super(ctx.getFrameManager()); + _ctx = ctx; + _metrics = metrics; + + // set ourselves up + setOpaque(true); + addMouseListener(this); + addMouseMotionListener(this); + + // handy rectangle + _tbounds = new Rectangle(0, 0, _metrics.tilewid, _metrics.tilehei); + } + + /** + * Configures the scene view to highlight object tiles either never + * ({@link #HIGHLIGHT_NEVER}), only when an object tile has an + * associated action string ({@link #HIGHLIGHT_WITH_ACTION}), or + * always ({@link #HIGHLIGHT_ALWAYS}). It is also possible to + * configure the view to highlight whatever tile is under the cursor, + * even if it's not an object tile which is done in the {@link + * #HIGHLIGHT_ALL} mode. + */ + public void setHighlightMode (int hmode) + { + _hmode = hmode; + } + + /** + * Configures this display with a scene model which will immediately + * be resolved and displayed. + */ + public void setSceneModel (MisoSceneModel model) + { + _model = model; + + // clear out old blocks and objects + _blocks.clear(); + _vizobjs.clear(); + _masks.clear(); + + // this will cause us to relayout which will center us in the + // middle of the scene which will cause us to rethink and load up + // all the necessary scene blocks to display ourselves; magic! + revalidate(); + } + + /** + * Returns the scene model being displayed by this panel. Do + * not modify! + */ + public MisoSceneModel getSceneModel () + { + return _model; + } + + /** + * Returns the scene metrics in use by this panel. Do not + * modify! + */ + public MisoSceneMetrics getSceneMetrics () + { + return _metrics; + } + + /** + * Set whether or not to highlight object tooltips (and potentially + * other scene entities). + */ + public void setShowFlags (int flags, boolean on) + { + int oldshow = _showFlags; + + if (on) { + _showFlags |= flags; + } else { + _showFlags &= ~flags; + } + + if (oldshow != _showFlags) { + showFlagsDidChange(oldshow); + } + } + + /** + * Check to see if the specified show flag is on. + */ + public boolean checkShowFlag (int flag) + { + return (0 != (flag & _showFlags)); + } + + /** + * Called when our show flags have changed. + */ + protected void showFlagsDidChange (int oldflags) + { + if ((oldflags & SHOW_TIPS) != (_showFlags & SHOW_TIPS)) { + for (Iterator iter = _tips.values().iterator(); iter.hasNext(); ) { + dirtyTip((SceneObjectTip)iter.next()); + } + } + } + + /** + * Returns the top-most object over which the mouse is hovering; this + * may be a sprite or a {@link SceneObject}. + */ + public Object getHoverObject () + { + return _hobject; + } + + /** + * Returns the tile coordinates of the tile over which the mouse is + * hovering. + */ + public Point getHoverCoords () + { + return _hcoords; + } + + /** + * Computes a path for the specified sprite to the specified tile + * coordinates. + */ + public Path getPath (Sprite sprite, int x, int y) + { + // get the destination tile coordinates + Point src = MisoUtil.screenToTile( + _metrics, sprite.getX(), sprite.getY(), new Point()); + Point dest = MisoUtil.screenToTile(_metrics, x, y, new Point()); + + // TODO: compute this value from the screen size or something + int longestPath = 50; + + // get a reasonable tile path through the scene + List points = AStarPathUtil.getPath( + this, sprite, longestPath, src.x, src.y, dest.x, dest.y); + + // construct a path object to guide the sprite on its merry way + return (points == null) ? null : + new TilePath(_metrics, sprite, points, x, y); + } + + /** + * Converts the supplied full coordinates to screen coordinates. + */ + public Point getScreenCoords (int x, int y) + { + return MisoUtil.fullToScreen(_metrics, x, y, new Point()); + } + + /** + * Coverts the supplied screen coordinates to full coordinates. + */ + public Point getFullCoords (int x, int y) + { + return MisoUtil.screenToFull(_metrics, x, y, new Point()); + } + + /** + * Coverts the supplied screen coordinates to tile coordinates. + */ + public Point getTileCoords (int x, int y) + { + return MisoUtil.screenToTile(_metrics, x, y, new Point()); + } + + /** + * Clears any radial menu being displayed. + */ + public void clearRadialMenu () + { + if (_activeMenu != null) { + _activeMenu.deactivate(); + } + } + +// // documentation inherited from interface +// public void setBaseTile (int fqTileId, int x, int y) +// { +// _model.setBaseTile(x, y, fqTileId); +// populateBaseTile(fqTileId, x, y); + +// // setting a base tile has the side-effect of clearing out the +// // surrounding fringe tiles. +// for (int xx=Math.max(x - 1, 0), +// xn=Math.min(x + 1, _model.width - 1); xx <= xn; xx++) { +// for (int yy=Math.max(y - 1, 0), +// yn=Math.min(y + 1, _model.height - 1); yy <= yn; yy++) { +// _fringe[yy * _model.width + xx] = null; +// } +// } +// } + + // documentation inherited from interface + public void mouseClicked (MouseEvent e) + { + // nothing doing + } + + // documentation inherited from interface + public void mousePressed (MouseEvent e) + { + // if this was not the first button, treat it as a cancellation of + // whatever might be going on + if (e.getButton() != MouseEvent.BUTTON1) { + return; + } + + // ignore mouse presses if we're not responsive + if (!isResponsive()) { + return; + } + + if (_hobject instanceof Sprite) { + handleSpritePressed((Sprite)_hobject, e.getX(), e.getY()); + } else if (_hobject instanceof SceneObject) { + handleObjectPressed((SceneObject)_hobject, e.getX(), e.getY()); + } else { + handleMousePressed(_hobject, e.getX(), e.getY()); + } + } + + /** + * Called when the user presses the mouse button over a sprite. + */ + protected void handleSpritePressed (Sprite sprite, int mx, int my) + { + } + + /** + * Called when the user presses the mouse button over an object. + */ + protected void handleObjectPressed (final SceneObject scobj, int mx, int my) + { + String action = scobj.info.action; + final ObjectActionHandler handler = ObjectActionHandler.lookup(action); + + // if there's no handler, just fire the action immediately + if (handler == null) { + fireObjectAction(null, scobj, new ActionEvent(this, 0, action, 0)); + return; + } + + // if the action's not allowed, pretend like we handled it + if (!handler.actionAllowed(action)) { + return; + } + + // if there's no menu for this object, fire the action immediately + RadialMenu menu = handler.handlePressed(scobj); + if (menu == null) { + fireObjectAction(handler, scobj, + new ActionEvent(this, 0, action, 0)); + return; + } + + // make the menu surround the clicked object, but don't go crazy + // if the object is huge + Rectangle mbounds = new Rectangle(scobj.bounds); + if (mbounds.width > 100) { + mbounds.x += (mbounds.width-100)/2; + mbounds.width = 100; + } + if (mbounds.height > 100) { + mbounds.y += (mbounds.height-100)/2; + mbounds.height = 100; + } + + _activeMenu = menu; + _activeMenu.addActionListener(new ActionListener() { + public void actionPerformed (ActionEvent e) { + fireObjectAction(handler, scobj, e); + } + }); + _activeMenu.activate(this, mbounds, scobj); + } + + /** + * Called when an object or object menu item has been clicked. + */ + protected void fireObjectAction ( + ObjectActionHandler handler, SceneObject scobj, ActionEvent event) + { + if (handler == null) { + Controller.postAction(event); + } else { + handler.handleAction(scobj, event); + } + } + + /** + * Called when the mouse is pressed over an unknown or non-existent + * hover object. + * + * @param hobject the hover object at the time of the mouse press or + * null if no hover object is active. + * + * @return true if the mouse press was handled, false if not. + */ + protected boolean handleMousePressed (Object hobject, int mx, int my) + { + return false; + } + + // documentation inherited from interface + public void mouseReleased (MouseEvent e) + { + // nothing doing; everything is handled on pressed + } + + // documentation inherited from interface + public void mouseEntered (MouseEvent e) + { + // nothing doing + } + + // documentation inherited from interface + public void mouseExited (MouseEvent e) + { + // clear the highlight tracking data + _hcoords.setLocation(-1, -1); + changeHoverObject(null); + repaint(); + } + + // documentation inherited from interface + public void mouseDragged (MouseEvent e) + { + // nothing doing + } + + // documentation inherited from interface + public void mouseMoved (MouseEvent e) + { + int x = e.getX(), y = e.getY(); + boolean repaint = false; + + // update the mouse's tile coordinates + boolean newtile = updateTileCoords(x, y, _hcoords); + // if we're highlighting base tiles, we may need to repaint + if (_hmode == HIGHLIGHT_ALL) { + repaint = (newtile || repaint); + } + + // stop now if we're not responsive + if (!isResponsive()) { + return; + } + + // give derived classes a chance to start with a hover object + Object hobject = computeOverHover(x, y); + + // if they came up with nothing, compute the list of objects over + // which the mouse is hovering + if (hobject == null) { + // start with the sprites that contain the point + _spritemgr.getHitSprites(_hitSprites, x, y); + int hslen = _hitSprites.size(); + for (int i = 0; i < hslen; i++) { + Sprite sprite = (Sprite)_hitSprites.get(i); + appendDirtySprite(_hitList, sprite); + } + + // add the object tiles that contain the point + getHitObjects(_hitList, x, y); + + // sort the list of hit items by rendering order + _hitList.sort(); + + // the last element in the array is what we want (assuming + // there are any items in the array) + int icount = _hitList.size(); + if (icount > 0) { + DirtyItem item = (DirtyItem)_hitList.get(icount-1); + hobject = item.obj; + } + } + + // if the user isn't hovering over a sprite or object with an + // action, allow derived classes to provide some other hover + if (hobject == null) { + hobject = computeUnderHover(x, y); + } + + repaint |= changeHoverObject(hobject); + + // clear out the hitlists + _hitList.clear(); + _hitSprites.clear(); + + if (repaint) { + repaint(); + } + } + + /** + * Gives derived classes a chance to compute a hover object that takes + * precedence over sprites and actionable objects. If this method + * returns non-null, no sprite or object hover calculations will be + * performed and the object returned will become the new hover object. + */ + protected Object computeOverHover (int mx, int my) + { + return null; + } + + /** + * Gives derived classes a chance to compute a hover object that is + * used if the mouse is not hovering over a sprite or actionable + * object. If this method is called, it means that there are no + * sprites or objects under the mouse. Thus if it returns non-null, + * the object returned will become the new hover object. + */ + protected Object computeUnderHover (int mx, int my) + { + return null; + } + + // documentation inherited + public boolean canTraverse (Object traverser, int tx, int ty) + { + SceneBlock block = getBlock(tx, ty); + return (block == null) ? false : block.canTraverse(traverser, tx, ty); + } + + // documentation inherited from interface + public Component getComponent () + { + return this; + } + + // documentation inherited from interface + public void repaintRect (int x, int y, int width, int height) + { + // translate back into view coordinates + x -= _vbounds.x; + y -= _vbounds.y; + repaint(x, y, width, height); + } + + // documentation inherited from interface + public void menuDeactivated (RadialMenu menu) + { + _activeMenu = null; + } + + // documentation inherited + public void doLayout () + { + super.doLayout(); + + // start out centered in the display + setViewLocation((_metrics.bounds.width - _vbounds.width)/2, + (_metrics.bounds.height - _vbounds.height)/2); + + // repaint the whole kit and kaboodle + if (EventQueue.isDispatchThread()) { + repaint(); + } + + Log.info("View: " + StringUtil.toString(_vbounds) + + ", vsize: " + StringUtil.toString(_metrics.bounds) + + ", nx: " + _nx + ", ny: " + _ny + "."); + } + + /** + * Returns the desired size for the panel based on the requested and + * calculated bounds of the scene view. + */ + public Dimension getPreferredSize () + { + return (_metrics == null || isPreferredSizeSet()) ? + super.getPreferredSize() : _metrics.bounds.getSize(); + } + + // documentation inherited + public void setBounds (int x, int y, int width, int height) + { + super.setBounds(x, y, width, height); + + // if we change size, force a rethink + if (width != _rsize.width || height != _rsize.height) { + _rsize.setSize(width, height); + Log.info("Size change rethink"); + rethink(); + } + } + + // documentation inherited + public void setViewLocation (int x, int y) + { + // if we're bounded, make sure no one tries to set our view + // location outside the bounds defined by the view model + if (_metrics.bounded) { + int minx = _metrics.bounds.x, + maxx = _metrics.bounds.width-getWidth(); + int miny = _metrics.bounds.y, + maxy = _metrics.bounds.height-getHeight(); + if (x < minx) { x = minx; } else if (x > maxx) { x = maxx; } + if (y < miny) { y = miny; } else if (y > maxy) { y = maxy; } + } + + super.setViewLocation(x, y); + } + + // documentation inherited + protected void viewLocationDidChange (int nx, int ny) + { + // compute the tile coordinates of our upper left screen + // coordinate and request a rethink if they've changed + MisoUtil.screenToTile(_metrics, nx, ny, _tcoords); + if (!_tcoords.equals(_ulpos)) { + Log.info("Rethinking +" + nx + "+" + ny + " -> " + + StringUtil.toString(_vbounds) + "/" + + StringUtil.toString(_tcoords) + "/" + + StringUtil.toString(_ulpos)); + _ulpos.setLocation(_tcoords); + rethink(); + } + } + + /** + * Derived classes can override this method and provide a colorizer + * that will be used to colorize the supplied scene object when + * rendering. + */ + protected TileSet.Colorizer getColorizer (ObjectInfo oinfo) + { + return null; + } + + /** + * Computes the tile coordinates of the supplied sprite and appends it + * to the supplied dirty item list. + */ + protected void appendDirtySprite (DirtyItemList list, Sprite sprite) + { + MisoUtil.screenToTile(_metrics, sprite.getX(), sprite.getY(), _tcoords); + list.appendDirtySprite(sprite, _tcoords.x, _tcoords.y); + } + + /** + * Returns the tile manager from which we load our tiles. + */ + protected TileManager getTileManager () + { + return _ctx.getTileManager(); + } + + /** + * This is called when our view position has changed by more than one + * tile in any direction. Herein we do a whole crapload of stuff: + * + *
+ * SceneObjectTip.background + * SceneObjectTip.foreground + * SceneObjectTip.font (falls back to Label.font) + *+ */ +public class SceneObjectTip extends LabelSausage +{ + /** The bounding box of this tip, or null prior to layout(). */ + public Rectangle bounds; + + /** + * Construct a SceneObjectTip. + */ + public SceneObjectTip (String text, Icon icon) + { + super(new Label(text, _foreground, _font), icon); + } + + /** + * Called to initialize the tip so that it can be painted. + * + * @param tipFor the bounding rectangle for the object we tip for. + * @param boundary the boundary of all displayable space. + * @param othertips other tip boundaries that we should avoid. + */ + public void layout (Graphics2D gfx, Rectangle tipFor, Rectangle boundary, + Collection othertips) + { + layout(gfx, PAD); + bounds = new Rectangle(_size); + + // center in the on-screen portion of the bounding box of the + // object we're tipping for, but don't go above MAX_HEIGHT from + // the bottom... + Rectangle anchor = boundary.intersection(tipFor); + bounds.setLocation( + anchor.x + (anchor.width - bounds.width) / 2, + anchor.y + Math.max( + (anchor.height - bounds.height) / 2, + anchor.height - MAX_HEIGHT)); + + // and jiggle it to not overlap any other tips + SwingUtil.positionRect(bounds, boundary, othertips); + } + + /** + * Paint this tip at it's location. + */ + public void paint (Graphics2D gfx) + { + paint(gfx, bounds.x, bounds.y, _background, null); + } + + /** + * Generates a string representation of this instance. + */ + public String toString () + { + return _label.getText() + "[" + StringUtil.toString(bounds) + "]"; + } + + // documentation inherited + protected void drawBase (Graphics2D gfx, int x, int y) + { + Composite ocomp = gfx.getComposite(); + gfx.setComposite(ALPHA); + super.drawBase(gfx, x, y); + gfx.setComposite(ocomp); + } + + /** The alpha we use for our base. */ + protected static final Composite ALPHA = AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, .75f); + + /** Colors to use when rendering the tip. */ + protected static Color _background, _foreground; + + /** The font to use when rendering the tip. */ + protected static Font _font; + + // initialize resources shared by all tips + static { + _background = UIManager.getColor("SceneObjectTip.background"); + _foreground = UIManager.getColor("SceneObjectTip.foreground"); + _font = UIManager.getFont("SceneObjectTip.font"); + if (_font == null) { + _font = UIManager.getFont("Label.font"); + } + } + + /** The number of pixels to reserve between elements of the tip. */ + protected static final int PAD = 3; + + /** The maximum height above the bottom of the object bounds that we are + * to center ourselves. */ + protected static final int MAX_HEIGHT = 80; +} diff --git a/src/java/com/threerings/miso/client/SceneView.java b/src/java/com/threerings/miso/client/SceneView.java deleted file mode 100644 index 7fd1d08ef..000000000 --- a/src/java/com/threerings/miso/client/SceneView.java +++ /dev/null @@ -1,87 +0,0 @@ -// -// $Id: SceneView.java,v 1.33 2003/01/31 23:10:45 mdb Exp $ - -package com.threerings.miso.client; - -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.Polygon; -import java.awt.Rectangle; -import java.awt.event.MouseEvent; - -import com.threerings.media.sprite.Sprite; -import com.threerings.media.util.Path; - -/** - * The scene view interface provides an interface to be implemented by - * classes that provide a view of a given scene by drawing the scene - * contents onto a particular GUI component. - */ -public interface SceneView -{ - /** - * Renders an invalid porition of the scene to the given graphics - * context. - * - * @param gfx the graphics context. - * @param invalidRect the invalid region to be repainted. - */ - public void paint (Graphics2D gfx, Rectangle invalidRect); - - /** - * Sets the scene that we're rendering. - * - * @param scene the scene to render in the view. - */ - public void setScene (DisplayMisoScene scene); - - /** - * Returns the scene being rendered. - */ - public DisplayMisoScene getScene (); - - /** - * Returns a {@link Path} object detailing a valid path for the - * given sprite to take in the scene to get from its current - * position to the destination position. - * - * @param sprite the sprite to move. - * @param x the destination x-position in pixel coordinates. - * @param y the destination y-position in pixel coordinates. - * - * @return the sprite's path, or null if no valid path exists. - */ - public Path getPath (Sprite sprite, int x, int y); - - /** - * Returns screen coordinates given the specified full coordinates. - */ - public Point getScreenCoords (int x, int y); - - /** - * Returns full coordinates given the specified screen coordinates. - */ - public Point getFullCoords (int x, int y); - - /** - * Must be called by the containing panel when the mouse moves over - * the view. - * - * @return true if a repaint is required, false if not. - */ - public boolean mouseMoved (MouseEvent e); - - /** - * Must be called by the containing panel when the mouse exits the - * view. - */ - public void mouseExited (MouseEvent e); - - /** - * Returns information about the object over which the mouse is - * currently hovering (either a {@link DisplayObjectInfo} or a {@link - * Sprite}), or null if the mouse is not hovering over anything of - * interest. - */ - public Object getHoverObject (); -} diff --git a/src/java/com/threerings/miso/client/SceneViewPanel.java b/src/java/com/threerings/miso/client/SceneViewPanel.java deleted file mode 100644 index 305990505..000000000 --- a/src/java/com/threerings/miso/client/SceneViewPanel.java +++ /dev/null @@ -1,174 +0,0 @@ -// -// $Id: SceneViewPanel.java,v 1.49 2003/01/31 23:10:45 mdb Exp $ - -package com.threerings.miso.client; - -import java.awt.Dimension; -import java.awt.Graphics2D; -import java.awt.Rectangle; -import java.awt.Shape; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionAdapter; - -import java.util.List; -import com.samskivert.util.StringUtil; - -import com.threerings.media.FrameManager; -import com.threerings.media.VirtualMediaPanel; - -import com.threerings.media.sprite.Sprite; -import com.threerings.media.sprite.SpriteManager; - -import com.threerings.miso.Log; -import com.threerings.miso.client.util.IsoUtil; - -/** - * The scene view panel is responsible for managing a {@link - * SceneView}, rendering it to the screen, and handling view-related - * UI events. - */ -public class SceneViewPanel extends VirtualMediaPanel -{ - /** - * Constructs the scene view panel with the supplied view model. - */ - public SceneViewPanel (FrameManager framemgr, IsoSceneViewModel model) - { - super(framemgr); - - // we're going to want to be opaque - setOpaque(true); - - // create the data model for the scene view - _viewmodel = model; - - // create the scene view - _view = newSceneView(_spritemgr, _viewmodel); - - // listen to mouse... - addMouseListener(new MouseAdapter() { - public void mouseExited (MouseEvent e) { - _view.mouseExited(e); - repaint(); - } - }); - - // ...and mouse motion events - addMouseMotionListener(new MouseMotionAdapter() { - public void mouseMoved (MouseEvent e) { - if (_view.mouseMoved(e)) { - repaint(); - } - } - public void mouseDragged (MouseEvent e) { - if (_view.mouseMoved(e)) { - repaint(); - } - } - }); - } - - /** - * Gets the iso scene view model associated with this panel. - */ - public IsoSceneViewModel getModel () - { - return _viewmodel; - } - - /** - * Constructs the underlying scene view implementation. - */ - protected SceneView newSceneView ( - SpriteManager smgr, IsoSceneViewModel model) - { - return new IsoSceneView(smgr, model, _remgr); - } - - /** - * Sets the scene managed by the panel. - */ - public void setScene (DisplayMisoScene scene) - { - if (scene == null) { - Log.warning("Ignoring request to set null scene."); - } else { - _view.setScene(scene); - } - } - - /** - * Gets the scene managed by the panel. - */ - public SceneView getSceneView () - { - return _view; - } - - // documentation inherited - public void doLayout () - { - super.doLayout(); - - // figure out our viewport offsets - Dimension size = getSize(); - - // start out centered in the display - setViewLocation((_viewmodel.bounds.width - size.width)/2, - (_viewmodel.bounds.height - size.height)/2); - -// Log.info("Size: " + StringUtil.toString(size) + -// ", vsize: " + StringUtil.toString(_viewmodel.bounds) + -// ", nx: " + _nx + ", ny: " + _ny + "."); - } - - // documentation inherited - public void setViewLocation (int x, int y) - { - // if we're bounded, make sure no one tries to set our view - // location outside the bounds defined by the view model - if (_viewmodel.bounded) { - int minx = _viewmodel.bounds.x, - maxx = _viewmodel.bounds.width-getWidth(); - int miny = _viewmodel.bounds.y, - maxy = _viewmodel.bounds.height-getHeight(); - if (x < minx) { x = minx; } else if (x > maxx) { x = maxx; } - if (y < miny) { y = miny; } else if (y > maxy) { y = maxy; } - } - super.setViewLocation(x, y); - } - - // documentation inherited - protected void paintBetween (Graphics2D gfx, Rectangle dirty) - { - _view.paint(gfx, dirty); - } - - /** - * We don't want sprites rendered using the standard mechanism because - * we intersperse them with objects in our scene and need to manage - * their z-order. - */ - protected void paintBits (Graphics2D gfx, int layer, Rectangle dirty) - { - _animmgr.renderMedia(gfx, layer, dirty); - } - - /** - * Returns the desired size for the panel based on the requested - * and calculated bounds of the scene view. - */ - public Dimension getPreferredSize () - { - return (_viewmodel == null || isPreferredSizeSet()) ? - super.getPreferredSize() : _viewmodel.bounds.getSize(); - } - - /** The scene view data model. */ - protected IsoSceneViewModel _viewmodel; - - /** The scene view we're managing. */ - protected SceneView _view; -} diff --git a/src/java/com/threerings/miso/client/SimpleDisplayMisoSceneImpl.java b/src/java/com/threerings/miso/client/SimpleDisplayMisoSceneImpl.java deleted file mode 100644 index 8e3a21c30..000000000 --- a/src/java/com/threerings/miso/client/SimpleDisplayMisoSceneImpl.java +++ /dev/null @@ -1,320 +0,0 @@ -// -// $Id: SimpleDisplayMisoSceneImpl.java,v 1.4 2003/04/07 22:04:39 mdb Exp $ - -package com.threerings.miso.client; - -import java.util.HashMap; - -import com.threerings.media.tile.NoSuchTileException; -import com.threerings.media.tile.NoSuchTileSetException; -import com.threerings.media.tile.ObjectTile; -import com.threerings.media.tile.Tile; -import com.threerings.media.tile.TileSet; - -import com.threerings.miso.Log; -import com.threerings.miso.client.util.ObjectSet; -import com.threerings.miso.data.ObjectInfo; -import com.threerings.miso.data.SimpleMisoSceneImpl; -import com.threerings.miso.data.SimpleMisoSceneModel; -import com.threerings.miso.tile.AutoFringer; -import com.threerings.miso.tile.BaseTile; -import com.threerings.miso.tile.MisoTileManager; - -/** - * An implementation of the {@link DisplayMisoScene} interface that uses a - * simple miso scene model. - */ -public class SimpleDisplayMisoSceneImpl extends SimpleMisoSceneImpl - implements DisplayMisoScene -{ - /** - * Constructs an instance that will be used to display the supplied - * miso scene data. The tiles identified by the scene model will be - * loaded via the supplied tile manager. - * - * @param model the scene data that we'll be displaying. - * @param tmgr the tile manager from which to load our tiles. - */ - public SimpleDisplayMisoSceneImpl (SimpleMisoSceneModel model, - MisoTileManager tmgr) - { - super(model); - - _tmgr = tmgr; - _fringer = tmgr.getAutoFringer(); - - int swid = _model.width; - int shei = _model.height; - - // create the individual tile layer objects - _base = new BaseTile[swid*shei]; - _fringe = new Tile[swid*shei]; - _covered = new boolean[swid*shei]; - } - - // documentation inherited from interface - public void init () - { - int swid = _model.width; - int shei = _model.height; - - // load up the tiles for our base layer - for (int column = 0; column < shei; column++) { - for (int row = 0; row < swid; row++) { - int fqTileId = getBaseTileId(column, row); - if (fqTileId > 0) { - populateBaseTile(fqTileId, column, row); - } - } - } - - // populate our display objects with object tiles - for (int ii = 0; ii < _objects.size(); ii++) { - if (!populateObject((DisplayObjectInfo)_objects.get(ii))) { - // initialization failed, remove the object - _objects.remove(ii--); - } - } - } - - // documentation inherited from interface - public void setBaseTile (int fqTileId, int x, int y) - { - super.setBaseTile(fqTileId, x, y); - populateBaseTile(fqTileId, x, y); - - // setting a base tile has the side-effect of clearing out the - // surrounding fringe tiles. - for (int xx=Math.max(x - 1, 0), - xn=Math.min(x + 1, _model.width - 1); xx <= xn; xx++) { - for (int yy=Math.max(y - 1, 0), - yn=Math.min(y + 1, _model.height - 1); yy <= yn; yy++) { - _fringe[yy * _model.width + xx] = null; - } - } - } - - // documentation inherited from interface - public ObjectInfo addObject (int fqTileId, int x, int y) - { - DisplayObjectInfo info = (DisplayObjectInfo) - super.addObject(fqTileId, x, y); - populateObject(info); - return info; - } - - // documentation inherited from interface - public boolean removeObject (ObjectInfo info) - { - if (super.removeObject(info)) { - // clear out this object's "shadow" - DisplayObjectInfo dinfo = (DisplayObjectInfo)info; - setObjectTileFootprint(dinfo.tile, dinfo.x, dinfo.y, false); - return true; - } else { - return false; - } - } - - // documentation inherited from interface - public BaseTile getBaseTile (int x, int y) - { - if (x < 0 || y < 0 || x >= _model.width || y >= _model.height) { - return null; - } - return _base[y*_model.width+x]; - } - - // documentation inherited from interface - public Tile getFringeTile (int x, int y) - { - if (x < 0 || y < 0 || x >= _model.width || y >= _model.height) { - return null; - } - - // if we have not yet composed this fringe tile, do so - int idx = y * _model.width + x; - if (_fringe[idx] == null) { - _fringe[idx] = _fringer.getFringeTile(this, x, y, _masks, _rando); - // make a note of non-fringed tiles that have been resolved - // but have no fringe tile - if (_fringe[idx] == null) { - _fringe[idx] = _nullFringe; - } - } - - return (_fringe[idx] == _nullFringe) ? null : _fringe[idx]; - } - - // documentation inherited from interface - public boolean canTraverse (Object trav, int x, int y) - { - BaseTile tile = getBaseTile(x, y); - return (((tile != null) && tile.isPassable()) && - !_covered[y*_model.width+x]); - } - - /** - * Called to populate a coordinate with its base tile. - */ - protected void populateBaseTile (int fqTileId, int x, int y) - { - if (x < 0 || y < 0 || x >= _model.width || y >= _model.height) { - // nothing doing - return; - } - - // this is a bit magical, but the tile manager will fetch tiles - // from the tileset repository and the tile set id from which we - // request this tile must map to a base tile as provided by the - // repository, so we just cast it to a base tile and know that all - // is well - String errmsg = null; - try { - _base[y*_model.width+x] = (BaseTile)_tmgr.getTile(fqTileId); - } catch (ClassCastException cce) { - errmsg = "Scene contains non-base tile in base layer"; - } catch (NoSuchTileSetException nste) { - errmsg = "Scene contains non-existent tileset"; - } catch (NoSuchTileException nste) { - errmsg = "Scene contains non-existent tile"; - } - - if (errmsg != null) { - Log.warning(errmsg + " [fqtid=" + fqTileId + - ", x=" + x + ", y=" + y + "]."); - } - } - - /** - * Called to populate an object with its object tile. - */ - protected boolean populateObject (DisplayObjectInfo info) - { - int tsid = (info.tileId >> 16) & 0xFFFF, tid = (info.tileId & 0xFFFF); - try { - initObject(info, (ObjectTile)_tmgr.getTile( - tsid, tid, getColorizer(info))); - return true; - } catch (NoSuchTileException nste) { - Log.warning("Scene contains non-existent object tile " + - "[info=" + info + "]."); - } catch (NoSuchTileSetException te) { - Log.warning("Scene contains non-existent object tileset " + - "[info=" + info + "]."); - } - return false; - } - - /** - * Initializes the supplied object with its object tile and configures - * any necessary peripheral scene business that couldn't be configured - * prior to the object having its tile. - */ - protected void initObject (DisplayObjectInfo info, ObjectTile tile) - { - // configure the object info with its object tile - info.setObjectTile(tile); - - // generate a "shadow" for this object tile by toggling the - // "covered" flag on in all base tiles below it (to prevent - // sprites from walking on those tiles) - setObjectTileFootprint(info.tile, info.x, info.y, true); - } - - /** - * Locates the display object info record for the object tile at the - * specified location. Two of the same kind of object tile cannot - * exist at the same location. - */ - protected DisplayObjectInfo getObjectInfo (ObjectTile tile, int x, int y) - { - int ocount = _objects.size(); - for (int ii = 0; ii < ocount; ii++) { - DisplayObjectInfo oinfo = (DisplayObjectInfo)_objects.get(ii); - if (oinfo.tile == tile && oinfo.x == x && oinfo.y == y) { - return oinfo; - } - } - return null; - } - - /** - * Sets the "covered" flag on all base tiles that are in the footprint - * of the specified object tile. - * - * @param otile the object tile whose footprint should be set. - * @param x the tile x-coordinate. - * @param y the tile y-coordinate. - * @param covered whether or not the footprint is being covered or - * uncovered. - */ - protected void setObjectTileFootprint ( - ObjectTile otile, int x, int y, boolean covered) - { - int endx = Math.max(0, (x - otile.getBaseWidth() + 1)); - int endy = Math.max(0, (y - otile.getBaseHeight() + 1)); - - for (int xx = x; xx >= endx; xx--) { - if ((xx < 0) || (xx >= _model.width)) { - continue; - } - - for (int yy = y; yy >= endy; yy--) { - if ((yy < 0) || (yy >= _model.height)) { - continue; - } - - _covered[yy*_model.width+xx] = true; - } - } - - // Log.info("Set object tile footprint [tile=" + otile + ", sx=" + x + - // ", sy=" + y + ", ex=" + endx + ", ey=" + endy + "]."); - } - - // documentation inherited - protected ObjectInfo createObjectInfo (int tileId, int x, int y) - { - return new DisplayObjectInfo(tileId, x, y); - } - - // documentation inherited - protected ObjectInfo createObjectInfo (ObjectInfo source) - { - return new DisplayObjectInfo(source); - } - - /** - * Returns the colorizer for the specified display object. The - * colorizer must provide colorization assignments that will be used - * to recolor the tile image when it is obtained from the tile - * manager. For an object with no colorizations, it is valid to return - * null here. - */ - protected TileSet.Colorizer getColorizer (DisplayObjectInfo oinfo) - { - return null; - } - - /** The tile manager from which we load tiles. */ - protected MisoTileManager _tmgr; - - /** The base layer of tiles. */ - protected BaseTile[] _base; - - /** The fringe layer of tiles. */ - protected Tile[] _fringe; - - /** Contains cached fringe mask tiles. TODO: LRU this or something. */ - protected HashMap _masks = new HashMap(); - - /** Used to identify non-existent fringe tiles. */ - protected Tile _nullFringe; - - /** Information on which tiles are covered by object tiles. */ - protected boolean[] _covered; - - /** The autofringer. */ - protected AutoFringer _fringer; -} diff --git a/src/java/com/threerings/miso/client/TilePath.java b/src/java/com/threerings/miso/client/TilePath.java index cfdecb14b..bc859c959 100644 --- a/src/java/com/threerings/miso/client/TilePath.java +++ b/src/java/com/threerings/miso/client/TilePath.java @@ -1,5 +1,5 @@ // -// $Id: TilePath.java,v 1.13 2003/01/31 23:10:45 mdb Exp $ +// $Id: TilePath.java,v 1.14 2003/04/17 19:21:16 mdb Exp $ package com.threerings.miso.client; @@ -14,7 +14,8 @@ import com.threerings.media.util.PathNode; import com.threerings.media.util.Pathable; import com.threerings.miso.Log; -import com.threerings.miso.client.util.IsoUtil; +import com.threerings.miso.util.MisoSceneMetrics; +import com.threerings.miso.util.MisoUtil; /** * The tile path represents a path of tiles through a scene. The path is @@ -28,7 +29,8 @@ public class TilePath extends LineSegmentPath /** * Constructs a tile path. * - * @param model the iso scene view model the path is associated with. + * @param metrics the metrics for the scene the with which the path is + * associated. * @param sprite the sprite to follow the path. * @param tiles the tiles to be traversed during the path. * @param destx the destination x-position in screen pixel @@ -36,10 +38,10 @@ public class TilePath extends LineSegmentPath * @param desty the destination y-position in screen pixel * coordinates. */ - public TilePath (IsoSceneViewModel model, Sprite sprite, + public TilePath (MisoSceneMetrics metrics, Sprite sprite, List tiles, int destx, int desty) { - _model = model; + _metrics = metrics; // set up the path nodes createPath(sprite, tiles, destx, desty); @@ -58,7 +60,7 @@ public class TilePath extends LineSegmentPath // check whether we've arrived at the destination tile if (!_arrived) { // get the sprite's latest tile coordinates - IsoUtil.screenToTile(_model, sx, sy, pos); + MisoUtil.screenToTile(_metrics, sx, sy, pos); // if the sprite has reached the destination tile, // update the sprite's tile location and remember @@ -98,12 +100,12 @@ public class TilePath extends LineSegmentPath { // constrain destination pixels to fine coordinates Point fpos = new Point(); - IsoUtil.screenToFull(_model, destx, desty, fpos); + MisoUtil.screenToFull(_metrics, destx, desty, fpos); // add the starting path node Point ipos = new Point(); int sx = sprite.getX(), sy = sprite.getY(); - IsoUtil.screenToTile(_model, sx, sy, ipos); + MisoUtil.screenToTile(_metrics, sx, sy, ipos); addNode(ipos.x, ipos.y, sx, sy, NORTH); // TODO: make more visually appealing path segments from start @@ -117,15 +119,15 @@ public class TilePath extends LineSegmentPath Point next = (Point)tiles.get(ii); // determine the direction from previous to next node - int dir = IsoUtil.getIsoDirection(prev.x, prev.y, next.x, next.y); + int dir = MisoUtil.getIsoDirection(prev.x, prev.y, next.x, next.y); // determine the node's position in screen pixel coordinates - IsoUtil.tileToScreen(_model, next.x, next.y, spos); + MisoUtil.tileToScreen(_metrics, next.x, next.y, spos); // add the node to the path, wandering through the middle // of each tile in the path for now - int dsx = spos.x + _model.tilehwid; - int dsy = spos.y + _model.tilehhei; + int dsx = spos.x + _metrics.tilehwid; + int dsy = spos.y + _metrics.tilehhei; addNode(next.x, next.y, dsx, dsy, dir); prev = next; @@ -133,22 +135,22 @@ public class TilePath extends LineSegmentPath // get the final destination point's screen coordinates // constrained to the closest full coordinate - IsoUtil.fullToScreen(_model, fpos.x, fpos.y, spos); + MisoUtil.fullToScreen(_metrics, fpos.x, fpos.y, spos); // get the tile coordinates for the final destination tile - int tdestx = IsoUtil.fullToTile(fpos.x); - int tdesty = IsoUtil.fullToTile(fpos.y); + int tdestx = MisoUtil.fullToTile(fpos.x); + int tdesty = MisoUtil.fullToTile(fpos.y); // get the facing direction for the final node int dir; if (prev.x == ipos.x && prev.y == ipos.y) { // if destination is within starting tile, direction is // determined by studying the fine coordinates - dir = IsoUtil.getDirection(_model, sx, sy, spos.x, spos.y); + dir = MisoUtil.getDirection(_metrics, sx, sy, spos.x, spos.y); } else { // else it's based on the last tile we traversed - dir = IsoUtil.getIsoDirection(prev.x, prev.y, tdestx, tdesty); + dir = MisoUtil.getIsoDirection(prev.x, prev.y, tdestx, tdesty); } // add the final destination path node @@ -176,6 +178,6 @@ public class TilePath extends LineSegmentPath /** The destination tile path node. */ protected TilePathNode _dest; - /** The iso scene view model. */ - protected IsoSceneViewModel _model; + /** The scene metrics. */ + protected MisoSceneMetrics _metrics; } diff --git a/src/java/com/threerings/miso/client/VirtualDisplayMisoSceneImpl.java b/src/java/com/threerings/miso/client/VirtualDisplayMisoSceneImpl.java deleted file mode 100644 index 529597b60..000000000 --- a/src/java/com/threerings/miso/client/VirtualDisplayMisoSceneImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -// -// $Id: VirtualDisplayMisoSceneImpl.java,v 1.2 2003/04/01 02:17:58 mdb Exp $ - -package com.threerings.miso.client; - -import java.awt.Rectangle; - -import com.threerings.media.tile.Tile; - -import com.threerings.miso.client.util.ObjectSet; -import com.threerings.miso.data.MisoSceneModel; -import com.threerings.miso.data.ObjectInfo; -import com.threerings.miso.tile.BaseTile; - -/** - * Provides a useful base class for "virtual" {@link DisplayMisoScene} - * implementations. These return tiles based on some algorithm rather than - * a repository of predefined tile data. - */ -public class VirtualDisplayMisoSceneImpl - implements DisplayMisoScene -{ - // documentation inherited from interface - public void init () - { - } - - // documentation inherited from interface - public int getBaseTileId (int x, int y) - { - return -1; - } - - // documentation inherited from interface - public void getObjects (Rectangle region, ObjectSet set) - { - // nothing doing - } - - // documentation inherited from interface - public void setBaseTile (int fqTileId, int x, int y) - { - // nothing doing - } - - // documentation inherited from interface - public void setBaseTiles (Rectangle r, int setId, int setSize) - { - // nothing doing - } - - // documentation inherited from interface - public ObjectInfo addObject (int fqTileId, int x, int y) - { - return null; - } - - // documentation inherited from interface - public boolean removeObject (ObjectInfo info) - { - return false; - } - - // documentation inherited from interface - public MisoSceneModel getSceneModel () - { - return null; - } - - // documentation inherited from interface - public BaseTile getBaseTile (int x, int y) - { - return null; - } - - // documentation inherited from interface - public Tile getFringeTile (int x, int y) - { - return null; - } - - // documentation inherited from interface - public boolean canTraverse (Object traverser, int x, int y) - { - return true; - } -} diff --git a/src/java/com/threerings/miso/data/MisoScene.java b/src/java/com/threerings/miso/data/MisoScene.java deleted file mode 100644 index 8e1205449..000000000 --- a/src/java/com/threerings/miso/data/MisoScene.java +++ /dev/null @@ -1,77 +0,0 @@ -// -// $Id: MisoScene.java,v 1.3 2003/02/24 18:40:41 mdb Exp $ - -package com.threerings.miso.data; - -import java.awt.Rectangle; - -import com.threerings.miso.client.util.ObjectSet; - -/** - * Provides information on the composition of tiles in a Miso scene. - */ -public interface MisoScene -{ - /** - * Returns the fully qualified tile id of the base tile at the - * specified coordinates.
-1 will be returned if there is
- * no tile at the specified coordinate.
- */
- public int getBaseTileId (int x, int y);
-
- /**
- * Populates the supplied object set with info on all objects whose
- * origin falls in the requested region.
- */
- public void getObjects (Rectangle region, ObjectSet set);
-
- /**
- * Updates the tile at the specified location in the base layer.
- *
- * @param fqTileId the fully-qualified tile id (@see
- * TileUtil#getFQTileId}) of the tile to set.
- * @param x the x-coordinate of the tile to set.
- * @param y the y-coordinate of the tile to set.
- *
- * Note that if there are fringe tiles associated with this scene,
- * calling this method may result in the surrounding fringe tiles being
- * cleared and subsequently recalculated. This should not be called
- * on a displaying scene unless you know what you are doing.
- */
- public void setBaseTile (int fqTileId, int x, int y);
-
- /**
- * Fill a rectangular area with random tiles from the specified base
- * tileset.
- *
- * @param r the region to be filled.
- * @param setId the id of the tileset to use when filling.
- * @param setSize the number of tiles in the tileset.
- */
- public void setBaseTiles (Rectangle r, int setId, int setSize);
-
- /**
- * Adds an object to this scene.
- *
- * @param fqTileId the fully-qualified tile id (@see
- * TileUtil#getFQTileId}) of the object tile.
- * @param x the object's origin x-coordinate.
- * @param y the object's origin y-coordinate.
- *
- * @return the new object info record.
- */
- public ObjectInfo addObject (int fqTileId, int x, int y);
-
- /**
- * Removes the specified object from the scene.
- */
- public boolean removeObject (ObjectInfo info);
-
- /**
- * Returns the scene model used by this scene. This is an expensive
- * operation as it must recreate the scene model from the (possibly
- * changed) runtime data. Thus it should not be called in a normal
- * client display and is provided mainly for scene editors and such.
- */
- public MisoSceneModel getSceneModel ();
-}
diff --git a/src/java/com/threerings/miso/data/MisoSceneModel.java b/src/java/com/threerings/miso/data/MisoSceneModel.java
index 32e8f185b..80be14d29 100644
--- a/src/java/com/threerings/miso/data/MisoSceneModel.java
+++ b/src/java/com/threerings/miso/data/MisoSceneModel.java
@@ -1,48 +1,31 @@
//
-// $Id: MisoSceneModel.java,v 1.13 2003/04/12 02:14:10 mdb Exp $
+// $Id: MisoSceneModel.java,v 1.14 2003/04/17 19:21:16 mdb Exp $
package com.threerings.miso.data;
-import java.util.ArrayList;
-
-import com.samskivert.util.ArrayUtil;
-import com.samskivert.util.IntListUtil;
-import com.samskivert.util.ListUtil;
+import java.awt.Rectangle;
+import java.util.Random;
import com.threerings.io.SimpleStreamableObject;
+
+import com.threerings.media.tile.TileUtil;
import com.threerings.media.util.MathUtil;
+import com.threerings.miso.util.ObjectSet;
+
/**
* Contains basic information for a miso scene model that is shared among
- * every specialized model implementation.
+ * the specialized model implementations.
*/
-public class MisoSceneModel extends SimpleStreamableObject
+public abstract class MisoSceneModel extends SimpleStreamableObject
implements Cloneable
{
- /** The width of this scene or section of the scene (depending on the
- * model implementation), in tile units. */
+ /** The width of this scene in tiles. */
public short width;
- /** The height of this scene or section of the scene (depending on the
- * model implementation), in tile units. */
+ /** The height of this scene in tiles. */
public short height;
- /** The combined tile ids (tile set id and tile id) of the
- * "uninteresting" tiles in the object layer. */
- public int[] objectTileIds;
-
- /** The x coordinate of the "uninteresting" tiles in the object
- * layer. */
- public short[] objectXs;
-
- /** The y coordinate of the "uninteresting" tiles in the object
- * layer. */
- public short[] objectYs;
-
- /** Information records for the "interesting" objects in the object
- * layer. */
- public ObjectInfo[] objectInfo;
-
/**
* Creates a completely uninitialized model suitable for little more
* than unserialization.
@@ -60,47 +43,74 @@ public class MisoSceneModel extends SimpleStreamableObject
Short.MIN_VALUE, width, Short.MAX_VALUE);
this.height = (short)MathUtil.bound(
Short.MIN_VALUE, height, Short.MAX_VALUE);
-
- // start with zero-length object arrays
- objectTileIds = new int[0];
- objectXs = new short[0];
- objectYs = new short[0];
- objectInfo = new ObjectInfo[0];
}
/**
- * Adds an object to this model.
+ * Returns the fully qualified tile id of the base tile at the
+ * specified coordinates. -1 will be returned if there is
+ * no tile at the specified coordinate.
*/
- public void addObject (ObjectInfo info)
+ public abstract int getBaseTileId (int x, int y);
+
+ /**
+ * Updates the tile at the specified location in the base layer.
+ *
+ * Note that if there are fringe tiles associated with this scene,
+ * calling this method may result in the surrounding fringe tiles
+ * being cleared and subsequently recalculated. This should not be
+ * called on a displaying scene unless you know what you are doing.
+ *
+ * @param fqTileId the fully-qualified tile id (@see
+ * TileUtil#getFQTileId}) of the tile to set.
+ * @param x the x-coordinate of the tile to set.
+ * @param y the y-coordinate of the tile to set.
+ *
+ * @return false if the specified tile coordinates are outside of the
+ * scene and the tile was not saved, true otherwise.
+ */
+ public abstract boolean setBaseTile (int fqTileId, int x, int y);
+
+ /**
+ * Fill a rectangular area with random tiles from the specified base
+ * tileset.
+ *
+ * @param r the region to be filled.
+ * @param setId the id of the tileset to use when filling.
+ * @param setSize the number of tiles in the tileset.
+ */
+ public void setBaseTiles (Rectangle r, int setId, int setSize)
{
- if (info.isInteresting()) {
- objectInfo = (ObjectInfo[])ArrayUtil.append(objectInfo, info);
- } else {
- objectTileIds = ArrayUtil.append(objectTileIds, info.tileId);
- objectXs = ArrayUtil.append(objectXs, (short)info.x);
- objectYs = ArrayUtil.append(objectYs, (short)info.y);
+ for (int x = r.x; x < r.x + r.width; x++) {
+ for (int y = r.y; y < r.y + r.height; y++) {
+ int index = _rando.nextInt(setSize);
+ setBaseTile(TileUtil.getFQTileId(setId, index), x, y);
+ }
}
}
/**
- * Removes an object from this model.
+ * Populates the supplied object set with info on all objects whose
+ * origin falls in the requested region.
*/
- public void removeObject (ObjectInfo info)
- {
- // look for it in the interesting info array
- int oidx = ListUtil.indexOfEqual(objectInfo, info);
- if (oidx != -1) {
- objectInfo = (ObjectInfo[])ArrayUtil.splice(objectInfo, oidx, 1);
- }
+ public abstract void getObjects (Rectangle region, ObjectSet set);
- // look for it in the uninteresting arrays
- oidx = IntListUtil.indexOf(objectTileIds, info.tileId);
- if (oidx != -1) {
- objectTileIds = ArrayUtil.splice(objectTileIds, oidx, 1);
- objectXs = ArrayUtil.splice(objectXs, oidx, 1);
- objectYs = ArrayUtil.splice(objectYs, oidx, 1);
- }
- }
+ /**
+ * Adds an object to this scene.
+ */
+ public abstract void addObject (ObjectInfo info);
+
+ /**
+ * Updates an object in this scene.
+ */
+ public abstract void updateObject (ObjectInfo info);
+
+ /**
+ * Removes the specified object from the scene.
+ *
+ * @return true if it was removed, false if the object was not in the
+ * scene.
+ */
+ public abstract boolean removeObject (ObjectInfo info);
/**
* Creates a copy of this scene model.
@@ -108,39 +118,12 @@ public class MisoSceneModel extends SimpleStreamableObject
public Object clone ()
{
try {
- MisoSceneModel model = (MisoSceneModel)super.clone();
- model.objectTileIds = (int[])objectTileIds.clone();
- model.objectXs = (short[])objectXs.clone();
- model.objectYs = (short[])objectYs.clone();
- model.objectInfo = (ObjectInfo[])objectInfo.clone();
- return model;
+ return (MisoSceneModel)super.clone();
} catch (CloneNotSupportedException cnse) {
throw new RuntimeException("MisoSceneModel.clone: " + cnse);
}
}
- /**
- * Populates the interesting and uninteresting parts of a miso scene
- * model given lists of {@link ObjectInfo} records for each.
- */
- public static void populateObjects (MisoSceneModel model,
- ArrayList ilist, ArrayList ulist)
- {
- // set up the uninteresting arrays
- int ucount = ulist.size();
- model.objectTileIds = new int[ucount];
- model.objectXs = new short[ucount];
- model.objectYs = new short[ucount];
- for (int ii = 0; ii < ucount; ii++) {
- ObjectInfo info = (ObjectInfo)ulist.get(ii);
- model.objectTileIds[ii] = info.tileId;
- model.objectXs[ii] = (short)info.x;
- model.objectYs[ii] = (short)info.y;
- }
-
- // set up the interesting array
- int icount = ilist.size();
- model.objectInfo = new ObjectInfo[icount];
- ilist.toArray(model.objectInfo);
- }
+ /** A random number generator for filling random base tiles. */
+ protected transient Random _rando = new Random();
}
diff --git a/src/java/com/threerings/miso/data/SimpleMisoSceneImpl.java b/src/java/com/threerings/miso/data/SimpleMisoSceneImpl.java
deleted file mode 100644
index 6fe74b83a..000000000
--- a/src/java/com/threerings/miso/data/SimpleMisoSceneImpl.java
+++ /dev/null
@@ -1,175 +0,0 @@
-//
-// $Id: SimpleMisoSceneImpl.java,v 1.2 2003/02/24 18:40:41 mdb Exp $
-
-package com.threerings.miso.data;
-
-import java.awt.Rectangle;
-import java.util.ArrayList;
-import java.util.Random;
-
-import com.threerings.media.tile.TileUtil;
-
-import com.threerings.miso.Log;
-import com.threerings.miso.client.util.ObjectSet;
-
-/**
- * A simple implementation of the {@link MisoScene} interface that assumes
- * a scene will be relatively small and all tile and object data can be
- * held in memory all at once.
- */
-public class SimpleMisoSceneImpl
- implements MisoScene
-{
- /**
- * Creates an initializes an instance using the supplied source model.
- */
- public SimpleMisoSceneImpl (SimpleMisoSceneModel model)
- {
- _model = model;
-
- // create display object infos for our uninteresting objects
- int ocount = (_model.objectTileIds == null) ? 0 :
- _model.objectTileIds.length;
- for (int ii = 0; ii < ocount; ii++) {
- _objects.add(createObjectInfo(_model.objectTileIds[ii],
- _model.objectXs[ii],
- _model.objectYs[ii]));
- }
-
- // create display object infos for our interesting objects
- for (int ii = 0, ll = _model.objectInfo.length; ii < ll; ii++) {
- // replace the object info in our model with the possibly
- // expanded derived class
- _model.objectInfo[ii] = createObjectInfo(_model.objectInfo[ii]);
- _objects.add(_model.objectInfo[ii]);
- }
- }
-
- // documentation inherited from interface
- public int getBaseTileId (int x, int y)
- {
- return _model.getBaseTile(x, y);
- }
-
- // documentation inherited from interface
- public void getObjects (Rectangle region, ObjectSet set)
- {
- for (int ii = 0, ll = _objects.size(); ii < ll; ii++) {
- ObjectInfo info = (ObjectInfo)_objects.get(ii);
- if (region.contains(info.x, info.y)) {
- set.insert(info);
- }
- }
- }
-
- // documentation inherited from interface
- public void setBaseTile (int fqTileId, int x, int y)
- {
- _model.setBaseTile(x, y, fqTileId);
- }
-
- // documentation inherited from interface
- public void setBaseTiles (Rectangle r, int setId, int setSize)
- {
- for (int x = r.x; x < r.x + r.width; x++) {
- for (int y = r.y; y < r.y + r.height; y++) {
- int index = _rando.nextInt(setSize);
- setBaseTile(TileUtil.getFQTileId(setId, index), x, y);
- }
- }
- }
-
- // documentation inherited from interface
- public ObjectInfo addObject (int fqTileId, int x, int y)
- {
- ObjectInfo info = createObjectInfo(fqTileId, x, y);
- _objects.add(info);
- return info;
- }
-
- // documentation inherited from interface
- public boolean removeObject (ObjectInfo info)
- {
- return _objects.remove(info);
- }
-
- // documentation inherited from interface
- public MisoSceneModel getSceneModel ()
- {
- // flush our objects list back to the arrays so that we pick up
- // any changes made since we created the list from the model
- int plain = 0, ocount = _objects.size();
- for (int ii = 0; ii < ocount; ii++) {
- ObjectInfo info = (ObjectInfo)_objects.get(ii);
- if (!info.isInteresting()) {
- plain++;
- }
- }
-
- // create new arrays of the appropriate size
- _model.objectInfo = new ObjectInfo[ocount-plain];
- _model.objectTileIds = new int[plain];
- _model.objectXs = new short[plain];
- _model.objectYs = new short[plain];
-
- // populate those arrays appropriately
- for (int cc = 0, pp = 0, ii = 0; cc < ocount; cc++) {
- ObjectInfo info = (ObjectInfo)_objects.get(cc);
- if (info.isInteresting()) {
- _model.objectInfo[ii++] = info;
- } else {
- _model.objectTileIds[pp] = info.tileId;
- _model.objectXs[pp] = (short)info.x;
- _model.objectYs[pp++] = (short)info.y;
- }
- }
-
- return _model;
- }
-
- /**
- * Return a string representation of this Miso scene object.
- */
- public String toString ()
- {
- StringBuffer buf = new StringBuffer("[");
- toString(buf);
- return buf.append("]").toString();
- }
-
- /**
- * An extensible {@link #toString()} helper.
- */
- protected void toString (StringBuffer buf)
- {
- buf.append("width=").append(_model.width);
- buf.append(", height=").append(_model.height);
- }
-
- /**
- * Creates an {@link ObjectInfo} record from the supplied tile
- * information.
- */
- protected ObjectInfo createObjectInfo (int tileId, int x, int y)
- {
- return new ObjectInfo(tileId, x, y);
- }
-
- /**
- * Creates an {@link ObjectInfo} record from the supplied source
- * record.
- */
- protected ObjectInfo createObjectInfo (ObjectInfo source)
- {
- return source;
- }
-
- /** The miso scene model from which we obtain our data. */
- protected SimpleMisoSceneModel _model;
-
- /** The scene object records. */
- protected ArrayList _objects = new ArrayList();
-
- /** A random number generator for filling random base tiles. */
- protected Random _rando = new Random();
-}
diff --git a/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java b/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
index 818a3ca11..cfbc7fc7a 100644
--- a/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
+++ b/src/java/com/threerings/miso/data/SimpleMisoSceneModel.java
@@ -1,14 +1,17 @@
//
-// $Id: SimpleMisoSceneModel.java,v 1.2 2003/04/12 02:14:10 mdb Exp $
+// $Id: SimpleMisoSceneModel.java,v 1.3 2003/04/17 19:21:16 mdb Exp $
package com.threerings.miso.data;
+import java.awt.Rectangle;
import java.util.ArrayList;
import com.samskivert.util.ArrayUtil;
import com.samskivert.util.IntListUtil;
import com.samskivert.util.ListUtil;
+import com.threerings.miso.util.ObjectSet;
+
/**
* Contains miso scene data for a scene that is assumed to be reasonably
* simple and small, such that all base tile data for the entire scene can
@@ -33,6 +36,22 @@ public class SimpleMisoSceneModel extends MisoSceneModel
* methods. */
public int[] baseTileIds;
+ /** The combined tile ids (tile set id and tile id) of the
+ * "uninteresting" tiles in the object layer. */
+ public int[] objectTileIds;
+
+ /** The x coordinate of the "uninteresting" tiles in the object
+ * layer. */
+ public short[] objectXs;
+
+ /** The y coordinate of the "uninteresting" tiles in the object
+ * layer. */
+ public short[] objectYs;
+
+ /** Information records for the "interesting" objects in the object
+ * layer. */
+ public ObjectInfo[] objectInfo;
+
/**
* Creates a completely uninitialized model suitable for little more
* than unserialization.
@@ -50,24 +69,22 @@ public class SimpleMisoSceneModel extends MisoSceneModel
this.vwidth = vwidth;
this.vheight = vheight;
allocateBaseTileArray();
+
+ // start with zero-length object arrays
+ objectTileIds = new int[0];
+ objectXs = new short[0];
+ objectYs = new short[0];
+ objectInfo = new ObjectInfo[0];
}
- /**
- * Get the fully-qualified tile id of the base tile at the specified
- * row and column.
- */
- public int getBaseTile (int col, int row)
+ // documentation inherited
+ public int getBaseTileId (int col, int row)
{
int index = getIndex(col, row);
return (index == -1) ? 0 : baseTileIds[index];
}
- /**
- * Set the fully-qualified tile id of a base tile.
- *
- * @return false if the specified tile coordinates are outside
- * of the viewport and the tile was not saved.
- */
+ // documentation inherited
public boolean setBaseTile (int col, int row, int fqBaseTileId)
{
int index = getIndex(col, row);
@@ -78,6 +95,80 @@ public class SimpleMisoSceneModel extends MisoSceneModel
return true;
}
+ // documentation inherited
+ public void getObjects (Rectangle region, ObjectSet set)
+ {
+ // first look for intersecting interesting objects
+ for (int ii = 0; ii < objectInfo.length; ii++) {
+ ObjectInfo info = objectInfo[ii];
+ if (region.contains(info.x, info.y)) {
+ set.insert(info);
+ }
+ }
+
+ // now look for intersecting non-interesting objects
+ for (int ii = 0; ii < objectTileIds.length; ii++) {
+ int x = objectXs[ii], y = objectYs[ii];
+ if (region.contains(x, y)) {
+ set.insert(new ObjectInfo(objectTileIds[ii], x, y));
+ }
+ }
+ }
+
+ // documentation inherited
+ public void addObject (ObjectInfo info)
+ {
+ if (info.isInteresting()) {
+ objectInfo = (ObjectInfo[])ArrayUtil.append(objectInfo, info);
+ } else {
+ objectTileIds = ArrayUtil.append(objectTileIds, info.tileId);
+ objectXs = ArrayUtil.append(objectXs, (short)info.x);
+ objectYs = ArrayUtil.append(objectYs, (short)info.y);
+ }
+ }
+
+ // documentation inherited
+ public void updateObject (ObjectInfo info)
+ {
+ // not efficient, but this is only done in editing situations
+ removeObject(info);
+ addObject(info);
+ }
+
+ // documentation inherited
+ public boolean removeObject (ObjectInfo info)
+ {
+ // look for it in the interesting info array
+ int oidx = ListUtil.indexOfEqual(objectInfo, info);
+ if (oidx != -1) {
+ objectInfo = (ObjectInfo[])ArrayUtil.splice(objectInfo, oidx, 1);
+ return true;
+ }
+
+ // look for it in the uninteresting arrays
+ oidx = IntListUtil.indexOf(objectTileIds, info.tileId);
+ if (oidx != -1) {
+ objectTileIds = ArrayUtil.splice(objectTileIds, oidx, 1);
+ objectXs = ArrayUtil.splice(objectXs, oidx, 1);
+ objectYs = ArrayUtil.splice(objectYs, oidx, 1);
+ return true;
+ }
+
+ return false;
+ }
+
+ // documentation inherited
+ public Object clone ()
+ {
+ SimpleMisoSceneModel model = (SimpleMisoSceneModel)super.clone();
+ model.baseTileIds = (int[])baseTileIds.clone();
+ model.objectTileIds = (int[])objectTileIds.clone();
+ model.objectXs = (short[])objectXs.clone();
+ model.objectYs = (short[])objectYs.clone();
+ model.objectInfo = (ObjectInfo[])objectInfo.clone();
+ return model;
+ }
+
/**
* Get the index into the baseTileIds[] for the specified
* x and y coordinates, or return -1 if the specified coordinates
@@ -135,11 +226,28 @@ public class SimpleMisoSceneModel extends MisoSceneModel
baseTileIds = new int[vwidth + vheight + ((vwidth * vheight) << 1)];
}
- // documentation inherited
- public Object clone ()
+ /**
+ * Populates the interesting and uninteresting parts of a miso scene
+ * model given lists of {@link ObjectInfo} records for each.
+ */
+ public static void populateObjects (SimpleMisoSceneModel model,
+ ArrayList ilist, ArrayList ulist)
{
- SimpleMisoSceneModel model = (SimpleMisoSceneModel)super.clone();
- model.baseTileIds = (int[])baseTileIds.clone();
- return model;
+ // set up the uninteresting arrays
+ int ucount = ulist.size();
+ model.objectTileIds = new int[ucount];
+ model.objectXs = new short[ucount];
+ model.objectYs = new short[ucount];
+ for (int ii = 0; ii < ucount; ii++) {
+ ObjectInfo info = (ObjectInfo)ulist.get(ii);
+ model.objectTileIds[ii] = info.tileId;
+ model.objectXs[ii] = (short)info.x;
+ model.objectYs[ii] = (short)info.y;
+ }
+
+ // set up the interesting array
+ int icount = ilist.size();
+ model.objectInfo = new ObjectInfo[icount];
+ ilist.toArray(model.objectInfo);
}
}
diff --git a/src/java/com/threerings/miso/data/VirtualMisoSceneModel.java b/src/java/com/threerings/miso/data/VirtualMisoSceneModel.java
new file mode 100644
index 000000000..ee64c93b7
--- /dev/null
+++ b/src/java/com/threerings/miso/data/VirtualMisoSceneModel.java
@@ -0,0 +1,53 @@
+//
+// $Id: VirtualMisoSceneModel.java,v 1.1 2003/04/17 19:21:16 mdb Exp $
+
+package com.threerings.miso.data;
+
+import java.awt.Rectangle;
+
+/**
+ * A convenient base class for "virtual" scenes which do not allow editing
+ * and compute the base and object tiles rather than obtain them from some
+ * data structure.
+ */
+public abstract class VirtualMisoSceneModel extends MisoSceneModel
+{
+ public VirtualMisoSceneModel ()
+ {
+ }
+
+ public VirtualMisoSceneModel (int width, int height)
+ {
+ super(width, height);
+ }
+
+ // documentation inherited from interface
+ public boolean setBaseTile (int fqTileId, int x, int y)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // documentation inherited from interface
+ public void setBaseTiles (Rectangle r, int setId, int setSize)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // documentation inherited from interface
+ public void addObject (ObjectInfo info)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // documentation inherited from interface
+ public void updateObject (ObjectInfo info)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ // documentation inherited from interface
+ public boolean removeObject (ObjectInfo info)
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/java/com/threerings/miso/tile/AutoFringer.java b/src/java/com/threerings/miso/tile/AutoFringer.java
index 327e96801..18b74f660 100644
--- a/src/java/com/threerings/miso/tile/AutoFringer.java
+++ b/src/java/com/threerings/miso/tile/AutoFringer.java
@@ -1,5 +1,5 @@
//
-// $Id: AutoFringer.java,v 1.19 2003/02/12 05:38:12 mdb Exp $
+// $Id: AutoFringer.java,v 1.20 2003/04/17 19:21:16 mdb Exp $
package com.threerings.miso.tile;
@@ -32,7 +32,7 @@ import com.threerings.media.image.BackedVolatileMirage;
import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage;
-import com.threerings.miso.data.MisoScene;
+import com.threerings.miso.data.MisoSceneModel;
/**
* Automatically fringes a scene according to the rules in the supplied
@@ -56,7 +56,7 @@ public class AutoFringer
* Compute and return the fringe tile to be inserted at the specified
* location.
*/
- public Tile getFringeTile (MisoScene scene, int col, int row,
+ public Tile getFringeTile (MisoSceneModel scene, int col, int row,
HashMap masks, Random rando)
{
// get the tileset id of the base tile we are considering
diff --git a/src/java/com/threerings/miso/tools/xml/SimpleMisoSceneParser.java b/src/java/com/threerings/miso/tools/xml/SimpleMisoSceneParser.java
new file mode 100644
index 000000000..e43a923c5
--- /dev/null
+++ b/src/java/com/threerings/miso/tools/xml/SimpleMisoSceneParser.java
@@ -0,0 +1,73 @@
+//
+// $Id: SimpleMisoSceneParser.java,v 1.1 2003/04/17 19:21:16 mdb Exp $
+
+package com.threerings.miso.tools.xml;
+
+import java.io.IOException;
+import java.io.FileInputStream;
+
+import org.xml.sax.SAXException;
+import org.apache.commons.digester.Digester;
+
+import com.samskivert.util.StringUtil;
+import com.threerings.tools.xml.NestableRuleSet;
+
+import com.threerings.miso.data.SimpleMisoSceneModel;
+
+/**
+ * A simple class for parsing simple miso scene models.
+ */
+public class SimpleMisoSceneParser
+{
+ /**
+ * Constructs a scene parser that parses scenes with the specified XML
+ * path prefix.
+ */
+ public SimpleMisoSceneParser (String prefix)
+ {
+ // create and configure our digester
+ _digester = new Digester();
+
+ // create our scene rule set
+ SimpleMisoSceneRuleSet set = new SimpleMisoSceneRuleSet();
+
+ // configure our top-level path prefix
+ if (StringUtil.blank(prefix)) {
+ _prefix = set.getOuterElement();
+ } else {
+ _prefix = prefix + "/" + set.getOuterElement();
+ }
+
+ // add the scene rules
+ set.addRuleInstances(_prefix, _digester);
+
+ // add a rule to grab the finished scene model
+ _digester.addSetNext(
+ _prefix, "setScene", SimpleMisoSceneModel.class.getName());
+ }
+
+ /**
+ * Parses the XML file at the specified path into a scene model
+ * instance.
+ */
+ public SimpleMisoSceneModel parseScene (String path)
+ throws IOException, SAXException
+ {
+ _model = null;
+ _digester.push(this);
+ _digester.parse(new FileInputStream(path));
+ return _model;
+ }
+
+ /**
+ * Called by the parser once the scene is parsed.
+ */
+ public void setScene (SimpleMisoSceneModel model)
+ {
+ _model = model;
+ }
+
+ protected String _prefix;
+ protected Digester _digester;
+ protected SimpleMisoSceneModel _model;
+}
diff --git a/src/java/com/threerings/miso/client/util/AStarPathUtil.java b/src/java/com/threerings/miso/util/AStarPathUtil.java
similarity index 99%
rename from src/java/com/threerings/miso/client/util/AStarPathUtil.java
rename to src/java/com/threerings/miso/util/AStarPathUtil.java
index 839c64124..a289660d2 100644
--- a/src/java/com/threerings/miso/client/util/AStarPathUtil.java
+++ b/src/java/com/threerings/miso/util/AStarPathUtil.java
@@ -1,7 +1,7 @@
//
-// $Id: AStarPathUtil.java,v 1.27 2003/04/12 02:14:52 mdb Exp $
+// $Id: AStarPathUtil.java,v 1.1 2003/04/17 19:21:16 mdb Exp $
-package com.threerings.miso.client.util;
+package com.threerings.miso.util;
import java.awt.Point;
import java.util.*;
diff --git a/src/java/com/threerings/miso/util/MisoContext.java b/src/java/com/threerings/miso/util/MisoContext.java
index 923c68d61..5df8c3466 100644
--- a/src/java/com/threerings/miso/util/MisoContext.java
+++ b/src/java/com/threerings/miso/util/MisoContext.java
@@ -1,8 +1,9 @@
//
-// $Id: MisoContext.java,v 1.9 2002/04/06 02:04:23 mdb Exp $
+// $Id: MisoContext.java,v 1.10 2003/04/17 19:21:16 mdb Exp $
package com.threerings.miso.util;
+import com.threerings.media.FrameManager;
import com.threerings.miso.tile.MisoTileManager;
/**
@@ -11,6 +12,11 @@ import com.threerings.miso.tile.MisoTileManager;
*/
public interface MisoContext
{
+ /**
+ * Returns the frame manager that our scene panel will interact with.
+ */
+ public FrameManager getFrameManager ();
+
/**
* Returns a reference to the tile manager. This reference is valid
* for the lifetime of the application.
diff --git a/src/java/com/threerings/miso/util/MisoSceneMetrics.java b/src/java/com/threerings/miso/util/MisoSceneMetrics.java
new file mode 100644
index 000000000..03d19cddf
--- /dev/null
+++ b/src/java/com/threerings/miso/util/MisoSceneMetrics.java
@@ -0,0 +1,134 @@
+//
+// $Id: MisoSceneMetrics.java,v 1.1 2003/04/17 19:21:16 mdb Exp $
+
+package com.threerings.miso.util;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+
+/**
+ * Contains information on the configuration of a particular isometric
+ * view. The member data are public to facilitate convenient referencing
+ * by the {@link MisoScenePanel} class, the values should not be modified
+ * once the metrics are constructed.
+ */
+public class MisoSceneMetrics
+{
+ /** Tile dimensions and half-dimensions in the view. */
+ public int tilewid, tilehei, tilehwid, tilehhei;
+
+ /** Fine coordinate dimensions. */
+ public int finehwid, finehhei;
+
+ /** Number of fine coordinates on each axis within a tile. */
+ public int finegran;
+
+ /** Size of the view in tile count. */
+ public int scenevwid, scenevhei;
+
+ /** Dimensions of our scene blocks in tile count. */
+ public int blockwid = 10, blockhei = 10;
+
+ /** Whether or not this view can extend beyond the bounds defined by
+ * the view width and height. True if it cannot, false if it can. */
+ public boolean bounded = true;
+
+ /** The bounds of the view in screen pixel coordinates. */
+ public Rectangle bounds;
+
+ /** The position in pixels at which tile (0, 0) is drawn. */
+ public Point origin;
+
+ /** The length of a tile edge in pixels. */
+ public float tilelen;
+
+ /** The slope of the x- and y-axis lines. */
+ public float slopeX, slopeY;
+
+ /** The length between fine coordinates in pixels. */
+ public float finelen;
+
+ /** The y-intercept of the x-axis line within a tile. */
+ public float fineBX;
+
+ /** The slope of the x- and y-axis lines within a tile. */
+ public float fineSlopeX, fineSlopeY;
+
+ /**
+ * Constructs scene metrics by directly specifying the desired config
+ * parameters.
+ *
+ * @param tilewid the width in pixels of the tiles.
+ * @param tilehei the height in pixels of the tiles.
+ * @param finegran the number of sub-tile divisions to use for fine
+ * coordinates.
+ * @param svwid the width in tiles of the viewport.
+ * @param svhei the height in tiles of the viewport.
+ * @param offy the offset of the origin (in tiles) from the top of the
+ * viewport.
+ */
+ public MisoSceneMetrics (int tilewid, int tilehei, int finegran,
+ int svwid, int svhei, int offy)
+ {
+ // keep track of this stuff
+ this.tilewid = tilewid;
+ this.tilehei = tilehei;
+ this.finegran = finegran;
+ this.scenevwid = svwid;
+ this.scenevhei = svhei;
+
+ // set the desired scene view bounds
+ bounds = new Rectangle(0, 0, scenevwid * tilewid, scenevhei * tilehei);
+
+ // set the scene display origin
+ origin = new Point((bounds.width / 2), (offy * tilehei));
+
+ // halve the dimensions
+ tilehwid = (tilewid / 2);
+ tilehhei = (tilehei / 2);
+
+ // calculate the length of a tile edge in pixels
+ tilelen = (float) Math.sqrt(
+ (tilehwid * tilehwid) + (tilehhei * tilehhei));
+
+ // calculate the slope of the x- and y-axis lines
+ slopeX = (float)tilehei / (float)tilewid;
+ slopeY = -slopeX;
+
+ // calculate the edge length separating each fine coordinate
+ finelen = tilelen / (float)finegran;
+
+ // calculate the fine-coordinate x-axis line
+ fineSlopeX = (float)tilehei / (float)tilewid;
+ fineBX = -(fineSlopeX * (float)tilehwid);
+ fineSlopeY = -fineSlopeX;
+
+ // calculate the fine coordinate dimensions
+ finehwid = (int)((float)tilehwid / (float)finegran);
+ finehhei = (int)((float)tilehhei / (float)finegran);
+ }
+
+ /**
+ * Returns whether the given tile coordinate is a valid coordinate in
+ * our coordinate system (which allows tile coordinates from 0 to
+ * 2^15-1).
+ */
+ public boolean isCoordinateValid (int x, int y)
+ {
+ return (x >= 0 && x < Short.MAX_VALUE &&
+ y >= 0 && y < Short.MAX_VALUE);
+ }
+
+ /**
+ * Returns whether the given full coordinate is a valid coordinate
+ * within the scene.
+ */
+ public boolean isFullCoordinateValid (int x, int y)
+ {
+ int tx = MisoUtil.fullToTile(x), ty = MisoUtil.fullToTile(y);
+ int fx = MisoUtil.fullToFine(x), fy = MisoUtil.fullToFine(y);
+ return (isCoordinateValid(tx, ty) &&
+ fx >= 0 && fx < finegran &&
+ fy >= 0 && fy < finegran);
+ }
+}
diff --git a/src/java/com/threerings/miso/client/util/IsoUtil.java b/src/java/com/threerings/miso/util/MisoUtil.java
similarity index 62%
rename from src/java/com/threerings/miso/client/util/IsoUtil.java
rename to src/java/com/threerings/miso/util/MisoUtil.java
index daf04ac9a..4a4856b6a 100644
--- a/src/java/com/threerings/miso/client/util/IsoUtil.java
+++ b/src/java/com/threerings/miso/util/MisoUtil.java
@@ -1,7 +1,7 @@
//
-// $Id: IsoUtil.java,v 1.45 2003/02/12 05:36:18 mdb Exp $
+// $Id: MisoUtil.java,v 1.18 2003/04/17 19:21:16 mdb Exp $
-package com.threerings.miso.client.util;
+package com.threerings.miso.util;
import java.awt.Point;
import java.awt.Polygon;
@@ -16,108 +16,13 @@ import com.threerings.util.DirectionCodes;
import com.threerings.util.DirectionUtil;
import com.threerings.miso.Log;
-import com.threerings.miso.client.IsoSceneViewModel;
-import com.threerings.miso.client.DisplayObjectInfo;
/**
- * The IsoUtil class is a holding place for miscellaneous
- * isometric-display-related utility routines.
+ * Miscellaneous isometric-display-related utility routines.
*/
-public class IsoUtil
+public class MisoUtil
implements DirectionCodes
{
- /**
- * Returns a polygon bounding all footprint tiles of the given
- * object tile.
- *
- * @param model the scene view model.
- * @param tx the x tile-coordinate of the object tile.
- * @param ty the y tile-coordinate of the object tile.
- * @param tile the object tile.
- *
- * @return the bounding polygon.
- */
- public static Polygon getObjectFootprint (
- IsoSceneViewModel model, DisplayObjectInfo scobj)
- {
- Polygon boundsPoly = new SmartPolygon();
- Point tpos = tileToScreen(model, scobj.x, scobj.y, new Point());
-
- int bwid = scobj.tile.getBaseWidth(), bhei = scobj.tile.getBaseHeight();
- int oox = tpos.x + model.tilehwid, ooy = tpos.y + model.tilehei;
- int rx = oox, ry = ooy;
-
- // bottom-center point
- boundsPoly.addPoint(rx, ry);
-
- // left point
- rx -= bwid * model.tilehwid;
- ry -= bwid * model.tilehhei;
- boundsPoly.addPoint(rx, ry);
-
- // top-center point
- rx += bhei * model.tilehwid;
- ry -= bhei * model.tilehhei;
- boundsPoly.addPoint(rx, ry);
-
- // right point
- rx += bwid * model.tilehwid;
- ry += bwid * model.tilehhei;
- boundsPoly.addPoint(rx, ry);
-
- // bottom-center point
- boundsPoly.addPoint(rx, ry);
-
- return boundsPoly;
- }
-
- /**
- * Returns a rectangle that encloses the entire object image, with the
- * upper left set to the appropriate values for rendering the object
- * image.
- *
- * @param model the scene view model.
- * @param tx the x tile-coordinate of the object tile.
- * @param ty the y tile-coordinate of the object tile.
- * @param tile the object tile.
- *
- * @return the bounding rectangle.
- */
- public static Rectangle getObjectBounds (
- IsoSceneViewModel model, DisplayObjectInfo scobj)
- {
- Point tpos = tileToScreen(model, scobj.x, scobj.y, new Point());
-
- // if the tile has an origin, use that, otherwise compute the
- // origin based on the tile footprint
- int tox = scobj.tile.getOriginX(), toy = scobj.tile.getOriginY();
- if (tox == Integer.MIN_VALUE) {
- tox = scobj.tile.getBaseWidth() * model.tilehwid;
- }
- if (toy == Integer.MIN_VALUE) {
- toy = scobj.tile.getHeight();
- }
-
- int oox = tpos.x + model.tilehwid, ooy = tpos.y + model.tilehei;
- int sx = oox - tox, sy = ooy - toy;
-
- return new Rectangle(
- sx, sy, scobj.tile.getWidth(), scobj.tile.getHeight());
- }
-
- /**
- * Returns true if the footprints of the two object tiles overlap when
- * the objects occupy the specified coordinates, false if not.
- */
- public static boolean objectFootprintsOverlap (
- DisplayObjectInfo so1, DisplayObjectInfo so2)
- {
- return (so2.x > so1.x - so1.tile.getBaseWidth() &&
- so1.x > so2.x - so2.tile.getBaseWidth() &&
- so2.y > so1.y - so1.tile.getBaseHeight() &&
- so1.y > so2.y - so2.tile.getBaseHeight());
- }
-
/**
* Given two points in screen pixel coordinates, return the
* compass direction that point B lies in from point A from an
@@ -132,14 +37,14 @@ public class IsoUtil
* class's direction constants.
*/
public static int getDirection (
- IsoSceneViewModel model, int ax, int ay, int bx, int by)
+ MisoSceneMetrics metrics, int ax, int ay, int bx, int by)
{
Point afpos = new Point(), bfpos = new Point();
// convert screen coordinates to full coordinates to get both
// tile coordinates and fine coordinates
- screenToFull(model, ax, ay, afpos);
- screenToFull(model, bx, by, bfpos);
+ screenToFull(metrics, ax, ay, afpos);
+ screenToFull(metrics, bx, by, bfpos);
// pull out the tile coordinates for each point
int tax = afpos.x / FULL_TILE_FACTOR;
@@ -278,16 +183,18 @@ public class IsoUtil
* parameter.
*/
public static Point screenToTile (
- IsoSceneViewModel model, int sx, int sy, Point tpos)
+ MisoSceneMetrics metrics, int sx, int sy, Point tpos)
{
// determine the upper-left of the quadrant that contains our
// point
- int zx = (int)Math.floor((float)(sx - model.origin.x) / model.tilewid);
- int zy = (int)Math.floor((float)(sy - model.origin.y) / model.tilehei);
+ int zx = (int)Math.floor((float)(sx - metrics.origin.x) /
+ metrics.tilewid);
+ int zy = (int)Math.floor((float)(sy - metrics.origin.y) /
+ metrics.tilehei);
// these are the screen coordinates of the tile's top
- int ox = (zx * model.tilewid + model.origin.x),
- oy = (zy * model.tilehei + model.origin.y);
+ int ox = (zx * metrics.tilewid + metrics.origin.x),
+ oy = (zy * metrics.tilehei + metrics.origin.y);
// these are the tile coordinates
tpos.x = zy + zx; tpos.y = zy - zx;
@@ -295,11 +202,11 @@ public class IsoUtil
// now determine which of the four tiles our point occupies
int dx = sx - ox, dy = sy - oy;
- if (Math.round(model.slopeY * dx + model.tilehei) <= dy) {
+ if (Math.round(metrics.slopeY * dx + metrics.tilehei) <= dy) {
tpos.x += 1;
}
- if (Math.round(model.slopeX * dx) > dy) {
+ if (Math.round(metrics.slopeX * dx) > dy) {
tpos.y -= 1;
}
@@ -313,8 +220,10 @@ public class IsoUtil
/**
* Convert the given tile-based coordinates to their corresponding
- * screen-based pixel coordinates. Converted coordinates are
- * placed in the given point object.
+ * screen-based pixel coordinates. The screen coordinate for a tile is
+ * the upper-left coordinate of the rectangle that bounds the tile
+ * polygon. Converted coordinates are placed in the given point
+ * object.
*
* @param x the tile x-position coordinate.
* @param y the tile y-position coordinate.
@@ -324,10 +233,10 @@ public class IsoUtil
* parameter.
*/
public static Point tileToScreen (
- IsoSceneViewModel model, int x, int y, Point spos)
+ MisoSceneMetrics metrics, int x, int y, Point spos)
{
- spos.x = model.origin.x + ((x - y - 1) * model.tilehwid);
- spos.y = model.origin.y + ((x + y) * model.tilehhei);
+ spos.x = metrics.origin.x + ((x - y - 1) * metrics.tilehwid);
+ spos.y = metrics.origin.y + ((x + y) * metrics.tilehhei);
return spos;
}
@@ -341,10 +250,10 @@ public class IsoUtil
* @param ppos the point object to place coordinates in.
*/
public static void fineToPixel (
- IsoSceneViewModel model, int x, int y, Point ppos)
+ MisoSceneMetrics metrics, int x, int y, Point ppos)
{
- ppos.x = model.tilehwid + ((x - y) * model.finehwid);
- ppos.y = (x + y) * model.finehhei;
+ ppos.x = metrics.tilehwid + ((x - y) * metrics.finehwid);
+ ppos.y = (x + y) * metrics.finehhei;
}
/**
@@ -358,28 +267,28 @@ public class IsoUtil
* @param fpos the point object to place coordinates in.
*/
public static void pixelToFine (
- IsoSceneViewModel model, int x, int y, Point fpos)
+ MisoSceneMetrics metrics, int x, int y, Point fpos)
{
// calculate line parallel to the y-axis (from the given
// x/y-pos to the x-axis)
- float bY = y - (model.fineSlopeY * x);
+ float bY = y - (metrics.fineSlopeY * x);
// determine intersection of x- and y-axis lines
- int crossx = (int)((bY - model.fineBX) /
- (model.fineSlopeX - model.fineSlopeY));
- int crossy = (int)((model.fineSlopeY * crossx) + bY);
+ int crossx = (int)((bY - metrics.fineBX) /
+ (metrics.fineSlopeX - metrics.fineSlopeY));
+ int crossy = (int)((metrics.fineSlopeY * crossx) + bY);
// TODO: final position should check distance between our
// position and the surrounding fine coords and return the
// actual closest fine coord, rather than just dividing.
// determine distance along the x-axis
- float xdist = MathUtil.distance(model.tilehwid, 0, crossx, crossy);
- fpos.x = (int)(xdist / model.finelen);
+ float xdist = MathUtil.distance(metrics.tilehwid, 0, crossx, crossy);
+ fpos.x = (int)(xdist / metrics.finelen);
// determine distance along the y-axis
float ydist = MathUtil.distance(x, y, crossx, crossy);
- fpos.y = (int)(ydist / model.finelen);
+ fpos.y = (int)(ydist / metrics.finelen);
}
/**
@@ -395,17 +304,17 @@ public class IsoUtil
* @return the point passed in to receive the coordinates.
*/
public static Point screenToFull (
- IsoSceneViewModel model, int sx, int sy, Point fpos)
+ MisoSceneMetrics metrics, int sx, int sy, Point fpos)
{
// get the tile coordinates
Point tpos = new Point();
- screenToTile(model, sx, sy, tpos);
+ screenToTile(metrics, sx, sy, tpos);
// get the screen coordinates for the containing tile
- Point spos = tileToScreen(model, tpos.x, tpos.y, new Point());
+ Point spos = tileToScreen(metrics, tpos.x, tpos.y, new Point());
// get the fine coordinates within the containing tile
- pixelToFine(model, sx - spos.x, sy - spos.y, fpos);
+ pixelToFine(metrics, sx - spos.x, sy - spos.y, fpos);
// toss in the tile coordinates for good measure
fpos.x += (tpos.x * FULL_TILE_FACTOR);
@@ -426,16 +335,16 @@ public class IsoUtil
* @return the point passed in to receive the coordinates.
*/
public static Point fullToScreen (
- IsoSceneViewModel model, int x, int y, Point spos)
+ MisoSceneMetrics metrics, int x, int y, Point spos)
{
// get the tile screen position
int tx = x / FULL_TILE_FACTOR, ty = y / FULL_TILE_FACTOR;
- Point tspos = tileToScreen(model, tx, ty, new Point());
+ Point tspos = tileToScreen(metrics, tx, ty, new Point());
// get the pixel position of the fine coords within the tile
Point ppos = new Point();
int fx = x - (tx * FULL_TILE_FACTOR), fy = y - (ty * FULL_TILE_FACTOR);
- fineToPixel(model, fx, fy, ppos);
+ fineToPixel(metrics, fx, fy, ppos);
// final position is tile position offset by fine position
spos.x = tspos.x + ppos.x;
@@ -449,9 +358,9 @@ public class IsoUtil
* coordinate plus a fine coordinate remainder). The fine coordinate
* is assumed to be relative to tile (0, 0).
*/
- public static int fineToFull (IsoSceneViewModel model, int fine)
+ public static int fineToFull (MisoSceneMetrics metrics, int fine)
{
- return toFull(fine / model.finegran, fine % model.finegran);
+ return toFull(fine / metrics.finegran, fine % metrics.finegran);
}
/**
@@ -470,61 +379,58 @@ public class IsoUtil
* @param y the tile y-position coordinate.
*/
public static Polygon getTilePolygon (
- IsoSceneViewModel model, int x, int y)
+ MisoSceneMetrics metrics, int x, int y)
{
- // get the top-left screen coordinate for the tile
- Point spos = IsoUtil.tileToScreen(model, x, y, new Point());
-
- // create a polygon framing the tile
- Polygon poly = new SmartPolygon();
- poly.addPoint(spos.x, spos.y + model.tilehhei);
- poly.addPoint(spos.x + model.tilehwid, spos.y);
- poly.addPoint(spos.x + model.tilewid, spos.y + model.tilehhei);
- poly.addPoint(spos.x + model.tilehwid, spos.y + model.tilehei);
-
- return poly;
+ return getFootprintPolygon(metrics, x, y, 1, 1);
}
/**
* Return a screen-coordinates polygon framing the two specified
* tile-coordinate points.
*/
- public static Polygon getMultiTilePolygon (IsoSceneViewModel model,
+ public static Polygon getMultiTilePolygon (MisoSceneMetrics metrics,
Point sp1, Point sp2)
{
- int minx, maxx, miny, maxy;
- Point[] p = new Point[4];
+ int x = Math.min(sp1.x, sp2.x), y = Math.min(sp1.y, sp2.y);
+ int width = Math.abs(sp1.x-sp2.x), height = Math.abs(sp1.y-sp2.y);
+ return getFootprintPolygon(metrics, x, y, width, height);
+ }
- // load in all possible screen coords
- p[0] = IsoUtil.tileToScreen(model, sp1.x, sp1.y, new Point());
- p[1] = IsoUtil.tileToScreen(model, sp2.x, sp2.y, new Point());
- p[2] = IsoUtil.tileToScreen(model, sp1.x, sp2.y, new Point());
- p[3] = IsoUtil.tileToScreen(model, sp2.x, sp1.y, new Point());
+ /**
+ * Returns a polygon framing the specified scene footprint.
+ *
+ * @param x the x tile coordinate of the "upper-left" of the footprint.
+ * @param y the y tile coordinate of the "upper-left" of the footprint.
+ * @param width the width in tiles of the footprint.
+ * @param height the height in tiles of the footprint.
+ */
+ public static Polygon getFootprintPolygon (
+ MisoSceneMetrics metrics, int x, int y, int width, int height)
+ {
+ SmartPolygon footprint = new SmartPolygon();
+ Point tpos = MisoUtil.tileToScreen(metrics, x, y, new Point());
- // locate the indexes of min/max for x and y
- minx = maxx = miny = maxy = 0;
- for (int ii=1; ii < 4; ii++) {
- if (p[ii].x < p[minx].x) {
- minx = ii;
- } else if (p[ii].x > p[maxx].x) {
- maxx = ii;
- }
+ // start with top-center point
+ int rx = tpos.x + metrics.tilehwid, ry = tpos.y;
+ footprint.addPoint(rx, ry);
+ // right point
+ rx += width * metrics.tilehwid;
+ ry += width * metrics.tilehhei;
+ footprint.addPoint(rx, ry);
+ // bottom-center point
+ rx -= height * metrics.tilehwid;
+ ry += height * metrics.tilehhei;
+ footprint.addPoint(rx, ry);
+ // left point
+ rx -= width * metrics.tilehwid;
+ ry -= width * metrics.tilehhei;
+ footprint.addPoint(rx, ry);
+ // end with top-center point
+ rx -= height * metrics.tilehwid;
+ ry += height * metrics.tilehhei;
+ footprint.addPoint(rx, ry);
- if (p[ii].y < p[miny].y) {
- miny = ii;
- } else if (p[ii].y > p[maxy].y) {
- maxy = ii;
- }
- }
-
- // now make the polygon! Whoo!
- Polygon poly = new SmartPolygon();
- poly.addPoint(p[minx].x, p[minx].y + model.tilehhei);
- poly.addPoint(p[miny].x + model.tilehwid, p[miny].y);
- poly.addPoint(p[maxx].x + model.tilewid, p[maxx].y + model.tilehhei);
- poly.addPoint(p[maxy].x + model.tilehwid, p[maxy].y + model.tilehei);
-
- return poly;
+ return footprint;
}
/**
@@ -533,22 +439,22 @@ public class IsoUtil
*
* @retun the point object supplied as full.
*/
- public static Point tilePlusFineToFull (IsoSceneViewModel model,
+ public static Point tilePlusFineToFull (MisoSceneMetrics metrics,
int tileX, int tileY,
int fineX, int fineY,
Point full)
{
- int dtx = fineX / model.finegran;
- int dty = fineY / model.finegran;
- int fx = fineX - dtx * model.finegran;
+ int dtx = fineX / metrics.finegran;
+ int dty = fineY / metrics.finegran;
+ int fx = fineX - dtx * metrics.finegran;
if (fx < 0) {
dtx--;
- fx += model.finegran;
+ fx += metrics.finegran;
}
- int fy = fineY - dty * model.finegran;
+ int fy = fineY - dty * metrics.finegran;
if (fy < 0) {
dty--;
- fy += model.finegran;
+ fy += metrics.finegran;
}
full.x = toFull(tileX + dtx, fx);
diff --git a/src/java/com/threerings/miso/client/util/ObjectSet.java b/src/java/com/threerings/miso/util/ObjectSet.java
similarity index 97%
rename from src/java/com/threerings/miso/client/util/ObjectSet.java
rename to src/java/com/threerings/miso/util/ObjectSet.java
index ddf7b8ec6..a8032afc6 100644
--- a/src/java/com/threerings/miso/client/util/ObjectSet.java
+++ b/src/java/com/threerings/miso/util/ObjectSet.java
@@ -1,7 +1,7 @@
//
-// $Id: ObjectSet.java,v 1.4 2003/02/12 05:36:44 mdb Exp $
+// $Id: ObjectSet.java,v 1.1 2003/04/17 19:21:17 mdb Exp $
-package com.threerings.miso.client.util;
+package com.threerings.miso.util;
import java.util.Arrays;
import java.util.Comparator;
diff --git a/tests/rsrc/scenes/idyll.xml b/tests/rsrc/scenes/idyll.xml
index 88d405a13..2c5abae18 100644
--- a/tests/rsrc/scenes/idyll.xml
+++ b/tests/rsrc/scenes/idyll.xml
@@ -6,7 +6,14 @@