Create tile bounding polygons on demand; changed object tile handling such
that a list of object metric records is used rather than a hashtable mapping tile coords to object tile bounding polygons because we were never doing a hash lookup, only iterating over the whole table. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1004 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: IsoSceneView.java,v 1.92 2002/02/12 08:54:49 mdb Exp $
|
// $Id: IsoSceneView.java,v 1.93 2002/02/17 07:16:21 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
@@ -20,7 +20,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.samskivert.util.HashIntMap;
|
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.threerings.media.animation.AnimationManager;
|
import com.threerings.media.animation.AnimationManager;
|
||||||
@@ -76,18 +75,9 @@ public class IsoSceneView implements SceneView
|
|||||||
_spritemgr = spritemgr;
|
_spritemgr = spritemgr;
|
||||||
_model = model;
|
_model = model;
|
||||||
|
|
||||||
// give the model a chance to pre-calculate various things
|
// create our polygon arrays, these will be populated with the
|
||||||
_model.precalculate();
|
// tile polygons as they are requested
|
||||||
|
|
||||||
// create our polygon arrays and create polygons for each of the
|
|
||||||
// tiles. we use these repeatedly, so we go ahead and make 'em all
|
|
||||||
// up front
|
|
||||||
_polys = new Polygon[model.scenewid][model.scenehei];
|
_polys = new Polygon[model.scenewid][model.scenehei];
|
||||||
for (int xx = 0; xx < model.scenewid; xx++) {
|
|
||||||
for (int yy = 0; yy < model.scenehei; yy++) {
|
|
||||||
_polys[xx][yy] = IsoUtil.getTilePolygon(_model, xx, yy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the array used to mark dirty tiles
|
// create the array used to mark dirty tiles
|
||||||
_dirty = new boolean[model.scenewid][model.tilehei];
|
_dirty = new boolean[model.scenewid][model.tilehei];
|
||||||
@@ -123,8 +113,9 @@ public class IsoSceneView implements SceneView
|
|||||||
// clear all dirty lists and tile array
|
// clear all dirty lists and tile array
|
||||||
clearDirtyRegions();
|
clearDirtyRegions();
|
||||||
|
|
||||||
// generate all object tile polygons
|
// obtain a list of the objects in the scene and generate records
|
||||||
initAllObjectBounds();
|
// for each of them that contain precomputed metrics
|
||||||
|
prepareObjectList();
|
||||||
|
|
||||||
// invalidate the entire screen as there's a new scene in town
|
// invalidate the entire screen as there's a new scene in town
|
||||||
invalidate();
|
invalidate();
|
||||||
@@ -197,7 +188,7 @@ public class IsoSceneView implements SceneView
|
|||||||
!StringUtil.blank(_scene.getObjectAction(
|
!StringUtil.blank(_scene.getObjectAction(
|
||||||
_hcoords.x, _hcoords.y))) {
|
_hcoords.x, _hcoords.y))) {
|
||||||
hpoly = IsoUtil.getObjectFootprint(
|
hpoly = IsoUtil.getObjectFootprint(
|
||||||
_model, _polys[_hcoords.x][_hcoords.y],
|
_model, getTilePoly(_hcoords.x, _hcoords.y),
|
||||||
(ObjectTile)_hobject);
|
(ObjectTile)_hobject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +197,7 @@ public class IsoSceneView implements SceneView
|
|||||||
// then paint the bounds of the highlighted base tile
|
// then paint the bounds of the highlighted base tile
|
||||||
if (hpoly == null && _hmode == HIGHLIGHT_ALL &&
|
if (hpoly == null && _hmode == HIGHLIGHT_ALL &&
|
||||||
_hcoords.x != -1 && _hcoords.y != -1) {
|
_hcoords.x != -1 && _hcoords.y != -1) {
|
||||||
hpoly = _polys[_hcoords.x][_hcoords.y];
|
hpoly = getTilePoly(_hcoords.x, _hcoords.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we've determined that there's something to highlight
|
// if we've determined that there's something to highlight
|
||||||
@@ -267,7 +258,7 @@ public class IsoSceneView implements SceneView
|
|||||||
for (int xx = 0; xx < _model.scenewid; xx++) {
|
for (int xx = 0; xx < _model.scenewid; xx++) {
|
||||||
for (int yy = 0; yy < _model.scenehei; yy++) {
|
for (int yy = 0; yy < _model.scenehei; yy++) {
|
||||||
if (_dirty[xx][yy]) {
|
if (_dirty[xx][yy]) {
|
||||||
gfx.draw(_polys[xx][yy]);
|
gfx.draw(getTilePoly(xx, yy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,15 +315,15 @@ public class IsoSceneView implements SceneView
|
|||||||
// draw the base and fringe tile images
|
// draw the base and fringe tile images
|
||||||
Tile tile;
|
Tile tile;
|
||||||
if ((tile = base.getTile(xx, yy)) != null) {
|
if ((tile = base.getTile(xx, yy)) != null) {
|
||||||
tile.paint(gfx, _polys[xx][yy]);
|
tile.paint(gfx, getTilePoly(xx, yy));
|
||||||
}
|
}
|
||||||
if ((tile = fringe.getTile(xx, yy)) != null) {
|
if ((tile = fringe.getTile(xx, yy)) != null) {
|
||||||
tile.paint(gfx, _polys[xx][yy]);
|
tile.paint(gfx, getTilePoly(xx, yy));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're showing coordinates, outline the tiles as well
|
// if we're showing coordinates, outline the tiles as well
|
||||||
if (_model.showCoords) {
|
if (_model.showCoords) {
|
||||||
gfx.draw(_polys[xx][yy]);
|
gfx.draw(getTilePoly(xx, yy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,55 +362,45 @@ public class IsoSceneView implements SceneView
|
|||||||
* Generates and stores bounding polygons for all object tiles in the
|
* Generates and stores bounding polygons for all object tiles in the
|
||||||
* scene for later use while rendering.
|
* scene for later use while rendering.
|
||||||
*/
|
*/
|
||||||
protected void initAllObjectBounds ()
|
protected void prepareObjectList ()
|
||||||
{
|
{
|
||||||
// clear out any previously existing object polygons
|
// clear out any previously existing object data
|
||||||
_objpolys.clear();
|
_objects.clear();
|
||||||
|
|
||||||
// generate bounding polygons for all objects
|
// generate metric records for all objects
|
||||||
ObjectTileLayer tiles = _scene.getObjectLayer();
|
ObjectTileLayer tiles = _scene.getObjectLayer();
|
||||||
for (int yy = 0; yy < tiles.getHeight(); yy++) {
|
for (int yy = 0; yy < tiles.getHeight(); yy++) {
|
||||||
for (int xx = 0; xx < tiles.getWidth(); xx++) {
|
for (int xx = 0; xx < tiles.getWidth(); xx++) {
|
||||||
ObjectTile tile = tiles.getTile(xx, yy);
|
ObjectTile tile = tiles.getTile(xx, yy);
|
||||||
if (tile != null) {
|
if (tile == null) {
|
||||||
generateObjectBounds(tile, xx, yy);
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a metrics record for this object
|
||||||
|
ObjectMetrics metrics = new ObjectMetrics();
|
||||||
|
metrics.tile = tile;
|
||||||
|
metrics.x = xx;
|
||||||
|
metrics.y = yy;
|
||||||
|
metrics.action = _scene.getObjectAction(xx, yy);
|
||||||
|
metrics.bounds = IsoUtil.getObjectBounds(
|
||||||
|
_model, getTilePoly(xx, yy), tile);
|
||||||
|
|
||||||
|
// and add it to the list
|
||||||
|
_objects.add(metrics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and stores the bounding polygon for the object which
|
* Returns the polygon bounding the tile at the specified coordinates.
|
||||||
* is used when invalidating dirty rectangles or tiles, and when
|
|
||||||
* rendering the object to a graphics context. This method should
|
|
||||||
* be called when an object tile is added to a scene.
|
|
||||||
*/
|
*/
|
||||||
protected void generateObjectBounds (ObjectTile tile, int x, int y)
|
protected Polygon getTilePoly (int x, int y)
|
||||||
{
|
{
|
||||||
// create the bounding polygon for this object
|
Polygon poly = _polys[x][y];
|
||||||
int key = getCoordinateKey(x, y);
|
if (poly == null) {
|
||||||
|
poly = _polys[x][y] = IsoUtil.getTilePolygon(_model, x, y);
|
||||||
// save it off in the object bounds hashtable
|
}
|
||||||
_objpolys.put(key, newObjectBounds(tile, x, y));
|
return poly;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and returns a new polygon bounding the given object
|
|
||||||
* tile positioned at the given scene coordinates.
|
|
||||||
*/
|
|
||||||
protected Polygon newObjectBounds (ObjectTile tile, int x, int y)
|
|
||||||
{
|
|
||||||
return IsoUtil.getObjectBounds(_model, _polys[x][y], tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a unique integer key corresponding to the given
|
|
||||||
* coordinates, suitable for storing and retrieving objects from a
|
|
||||||
* hashtable.
|
|
||||||
*/
|
|
||||||
protected int getCoordinateKey (int x, int y)
|
|
||||||
{
|
|
||||||
return (x << 16 | y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -440,7 +421,7 @@ public class IsoSceneView implements SceneView
|
|||||||
for (int yy = 0; yy < _model.scenehei; yy++) {
|
for (int yy = 0; yy < _model.scenehei; yy++) {
|
||||||
for (int xx = 0; xx < _model.scenewid; xx++) {
|
for (int xx = 0; xx < _model.scenewid; xx++) {
|
||||||
// get the top-left screen coordinates of the tile
|
// get the top-left screen coordinates of the tile
|
||||||
Rectangle bounds = _polys[xx][yy].getBounds();
|
Rectangle bounds = getTilePoly(xx, yy).getBounds();
|
||||||
|
|
||||||
// only draw coordinates if the tile is on-screen
|
// only draw coordinates if the tile is on-screen
|
||||||
if (bounds.intersects(_model.bounds)) {
|
if (bounds.intersects(_model.bounds)) {
|
||||||
@@ -592,7 +573,7 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
|
|
||||||
// expand the tile bounds rectangle to include this tile
|
// expand the tile bounds rectangle to include this tile
|
||||||
Rectangle bounds = _polys[x][y].getBounds();
|
Rectangle bounds = getTilePoly(x, y).getBounds();
|
||||||
if (tileBounds.x == -1) {
|
if (tileBounds.x == -1) {
|
||||||
tileBounds.setBounds(bounds);
|
tileBounds.setBounds(bounds);
|
||||||
} else {
|
} else {
|
||||||
@@ -635,29 +616,29 @@ public class IsoSceneView implements SceneView
|
|||||||
|
|
||||||
// add any objects impacted by the dirty rectangle
|
// add any objects impacted by the dirty rectangle
|
||||||
if (_scene != null) {
|
if (_scene != null) {
|
||||||
ObjectTileLayer tiles = _scene.getObjectLayer();
|
Iterator iter = _objects.iterator();
|
||||||
Iterator iter = _objpolys.keys();
|
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
// get the object's coordinates and bounding polygon
|
ObjectMetrics metrics = (ObjectMetrics)iter.next();
|
||||||
int coord = ((Integer)iter.next()).intValue();
|
Polygon poly = metrics.bounds;
|
||||||
Polygon poly = (Polygon)_objpolys.get(coord);
|
|
||||||
if (!poly.intersects(r)) {
|
if (!poly.intersects(r)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the dirty portion of the object
|
// get the dirty portion of the object
|
||||||
Rectangle drect = poly.getBounds().intersection(r);
|
Rectangle drect = poly.getBounds().intersection(r);
|
||||||
int tx = coord >> 16, ty = coord & 0x0000FFFF;
|
int tx = metrics.x, ty = metrics.y;
|
||||||
ObjectTile tile = tiles.getTile(tx, ty);
|
|
||||||
|
|
||||||
// compute the footprint if we're rendering those
|
// compute the footprint if we're rendering those
|
||||||
Polygon foot = null;
|
Polygon foot = null;
|
||||||
if (_renderObjectFootprints) {
|
if (_renderObjectFootprints) {
|
||||||
foot = IsoUtil.getObjectFootprint(
|
foot = IsoUtil.getObjectFootprint(
|
||||||
_model, _polys[tx][ty], tile);
|
_model, getTilePoly(tx, ty), metrics.tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
_dirtyItems.appendDirtyObject(tile, poly, foot, tx, ty, drect);
|
// add the intersected section of the object to the dirty
|
||||||
|
// items list
|
||||||
|
_dirtyItems.appendDirtyObject(
|
||||||
|
metrics.tile, poly, foot, tx, ty, drect);
|
||||||
// Log.info("Dirtied item: Object(" + tx + ", " + ty + ")");
|
// Log.info("Dirtied item: Object(" + tx + ", " + ty + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -769,30 +750,25 @@ public class IsoSceneView implements SceneView
|
|||||||
*/
|
*/
|
||||||
protected void getHitObjects (DirtyItemList list, int x, int y)
|
protected void getHitObjects (DirtyItemList list, int x, int y)
|
||||||
{
|
{
|
||||||
ObjectTileLayer tiles = _scene.getObjectLayer();
|
Iterator iter = _objects.iterator();
|
||||||
Iterator iter = _objpolys.keys();
|
|
||||||
|
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
// get the object's coordinates and bounding polygon
|
ObjectMetrics metrics = (ObjectMetrics)iter.next();
|
||||||
int coord = ((Integer)iter.next()).intValue();
|
|
||||||
Polygon poly = (Polygon)_objpolys.get(coord);
|
|
||||||
|
|
||||||
// skip polys that don't contain the point
|
// skip polys that don't contain the point
|
||||||
if (!poly.contains(x, y)) {
|
if (!metrics.bounds.contains(x, y)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check that the pixel in the tile image is
|
// now check that the pixel in the tile image is
|
||||||
// non-transparent at that point
|
// non-transparent at that point
|
||||||
int tx = coord >> 16, ty = coord & 0x0000FFFF;
|
int tx = metrics.x, ty = metrics.y;
|
||||||
ObjectTile tile = tiles.getTile(tx, ty);
|
Rectangle pbounds = metrics.bounds.getBounds();
|
||||||
Rectangle pbounds = poly.getBounds();
|
if (!metrics.tile.hitTest(x - pbounds.x, y - pbounds.y)) {
|
||||||
if (!tile.hitTest(x - pbounds.x, y - pbounds.y)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we've passed the test, add the object to the list
|
// we've passed the test, add the object to the list
|
||||||
list.appendDirtyObject(tile, poly, null, tx, ty, pbounds);
|
list.appendDirtyObject(metrics.tile, metrics.bounds, null,
|
||||||
|
tx, ty, pbounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,6 +821,26 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class used to cache necessary information on all object tiles in
|
||||||
|
* the scene.
|
||||||
|
*/
|
||||||
|
protected static class ObjectMetrics
|
||||||
|
{
|
||||||
|
/** The x and y tile coordinates of the object. */
|
||||||
|
public int x, y;
|
||||||
|
|
||||||
|
/** A reference to the object tile itself. */
|
||||||
|
public ObjectTile tile;
|
||||||
|
|
||||||
|
/** The object's bounding polygon. */
|
||||||
|
public Polygon bounds;
|
||||||
|
|
||||||
|
/** The action associated with the object or null if no action is
|
||||||
|
* associated. */
|
||||||
|
public String action;
|
||||||
|
}
|
||||||
|
|
||||||
/** The sprite manager. */
|
/** The sprite manager. */
|
||||||
protected SpriteManager _spritemgr;
|
protected SpriteManager _spritemgr;
|
||||||
|
|
||||||
@@ -866,8 +862,8 @@ public class IsoSceneView implements SceneView
|
|||||||
/** Polygon instances for all of our tiles. */
|
/** Polygon instances for all of our tiles. */
|
||||||
protected Polygon _polys[][];
|
protected Polygon _polys[][];
|
||||||
|
|
||||||
/** Bounding polygons for all of the object tiles. */
|
/** Metric information for all of the object tiles. */
|
||||||
protected HashIntMap _objpolys = new HashIntMap();
|
protected ArrayList _objects = new ArrayList();
|
||||||
|
|
||||||
/** The dirty tiles that need to be re-painted. */
|
/** The dirty tiles that need to be re-painted. */
|
||||||
protected boolean _dirty[][];
|
protected boolean _dirty[][];
|
||||||
|
|||||||
Reference in New Issue
Block a user