Brought miso stuff into line with new media architecture; implemented
various and sundry optimizations in the process. We love the spiral development. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@1476 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: DirtyItemList.java,v 1.10 2002/02/06 23:14:56 mdb Exp $
|
// $Id: DirtyItemList.java,v 1.11 2002/06/18 22:38:12 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
@@ -8,18 +8,16 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
import com.samskivert.util.HashIntMap;
|
import com.samskivert.util.SortableArrayList;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
|
import com.threerings.media.Log;
|
||||||
import com.threerings.media.sprite.Sprite;
|
import com.threerings.media.sprite.Sprite;
|
||||||
import com.threerings.media.tile.ObjectTile;
|
import com.threerings.media.tile.ObjectTile;
|
||||||
|
|
||||||
import com.threerings.media.Log;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The dirty item list keeps track of dirty sprites and object tiles
|
* The dirty item list keeps track of dirty sprites and object tiles
|
||||||
* in a scene.
|
* in a scene.
|
||||||
@@ -27,24 +25,37 @@ import com.threerings.media.Log;
|
|||||||
public class DirtyItemList
|
public class DirtyItemList
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Appends the dirty sprite at the given coordinates to the dirty
|
* Appends the dirty sprite at the given coordinates to the dirty item
|
||||||
* item list.
|
* list.
|
||||||
|
*
|
||||||
|
* @param sprite the dirty sprite itself.
|
||||||
|
* @param tx the sprite's x tile position.
|
||||||
|
* @param ty the sprite's y tile position.
|
||||||
*/
|
*/
|
||||||
public void appendDirtySprite (
|
public void appendDirtySprite (MisoCharacterSprite sprite, int tx, int ty)
|
||||||
MisoCharacterSprite sprite, int x, int y, Rectangle dirtyRect)
|
|
||||||
{
|
{
|
||||||
_items.add(new DirtyItem(sprite, null, null, x, y, dirtyRect));
|
DirtyItem item = getDirtyItem();
|
||||||
|
item.init(sprite, null, null, tx, ty);
|
||||||
|
_items.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Appends the dirty object tile at the given coordinates to the
|
* Appends the dirty object tile at the given coordinates to the dirty
|
||||||
* dirty item list.
|
* item list.
|
||||||
|
*
|
||||||
|
* @param tile the object tile that is dirty.
|
||||||
|
* @param bounds the bounds of this object tile.
|
||||||
|
* @param footprint the footprint of the object tile if it should be
|
||||||
|
* rendered, null otherwise.
|
||||||
|
* @param tx the object tile's x tile position.
|
||||||
|
* @param ty the object tile's y tile position.
|
||||||
*/
|
*/
|
||||||
public void appendDirtyObject (
|
public void appendDirtyObject (
|
||||||
ObjectTile tile, Shape bounds, Shape footprint,
|
ObjectTile tile, Rectangle bounds, Shape footprint, int tx, int ty)
|
||||||
int x, int y, Rectangle dirtyRect)
|
|
||||||
{
|
{
|
||||||
_items.add(new DirtyItem(tile, bounds, footprint, x, y, dirtyRect));
|
DirtyItem item = getDirtyItem();
|
||||||
|
item.init(tile, bounds, footprint, tx, ty);
|
||||||
|
_items.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,7 +70,7 @@ public class DirtyItemList
|
|||||||
* Returns an array of the {@link DirtyItem} objects in the list
|
* Returns an array of the {@link DirtyItem} objects in the list
|
||||||
* sorted in proper rendering order.
|
* sorted in proper rendering order.
|
||||||
*/
|
*/
|
||||||
public DirtyItem[] sort ()
|
public void sort ()
|
||||||
{
|
{
|
||||||
int size = size();
|
int size = size();
|
||||||
|
|
||||||
@@ -67,41 +78,64 @@ public class DirtyItemList
|
|||||||
Log.info("Sorting dirty item list [size=" + size + "].");
|
Log.info("Sorting dirty item list [size=" + size + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
// get items sorted by increasing origin x-coordinate
|
// if we've only got one item, we need to do no sorting
|
||||||
DirtyItem[] xitems = new DirtyItem[size];
|
if (size > 1) {
|
||||||
_items.toArray(xitems);
|
// get items sorted by increasing origin x-coordinate
|
||||||
// if we've only got one item, bail out now
|
_xitems.addAll(_items);
|
||||||
if (xitems.length < 2) {
|
_xitems.sort(ORIGIN_X_COMP);
|
||||||
return xitems;
|
if (DEBUG_SORT) {
|
||||||
|
Log.info("Sorted by x-origin " +
|
||||||
|
"[items=" + toString(_xitems) + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get items sorted by increasing origin y-coordinate
|
||||||
|
_yitems.addAll(_items);
|
||||||
|
_yitems.sort(ORIGIN_Y_COMP);
|
||||||
|
if (DEBUG_SORT) {
|
||||||
|
Log.info("Sorted by y-origin " +
|
||||||
|
"[items=" + toString(_yitems) + "].");
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort items into proper render order
|
||||||
|
_items.sort(_rcomp);
|
||||||
|
|
||||||
|
// clear out our temporary arrays
|
||||||
|
_xitems.clear();
|
||||||
|
_yitems.clear();
|
||||||
}
|
}
|
||||||
Arrays.sort(xitems, ORIGIN_X_COMP);
|
|
||||||
|
|
||||||
if (DEBUG_SORT) {
|
if (DEBUG_SORT) {
|
||||||
Log.info("Sorted by x-origin " +
|
Log.info("Sorted for render [items=" + toString(_items) + "].");
|
||||||
"[items=" + DirtyItemList.toString(xitems) + "].");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// get items sorted by increasing origin y-coordinate
|
/**
|
||||||
DirtyItem[] yitems = new DirtyItem[size];
|
* Paints all the dirty items in this list using the supplied graphics
|
||||||
_items.toArray(yitems);
|
* context. The items are removed from the dirty list after being
|
||||||
Arrays.sort(yitems, ORIGIN_Y_COMP);
|
* painted and the dirty list ends up empty.
|
||||||
|
*/
|
||||||
if (DEBUG_SORT) {
|
public void paintAndClear (Graphics2D gfx)
|
||||||
Log.info("Sorted by y-origin " +
|
{
|
||||||
"[items=" + DirtyItemList.toString(yitems) + "].");
|
int icount = _items.size();
|
||||||
|
for (int ii = 0; ii < icount; ii++) {
|
||||||
|
DirtyItem item = (DirtyItem)_items.get(ii);
|
||||||
|
item.paint(gfx);
|
||||||
|
item.clear();
|
||||||
|
_freelist.add(item);
|
||||||
}
|
}
|
||||||
|
_items.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// sort items into proper render order
|
/**
|
||||||
DirtyItem[] ritems = new DirtyItem[size];
|
* Clears out any items that were in this list.
|
||||||
_items.toArray(ritems);
|
*/
|
||||||
Arrays.sort(ritems, new RenderComparator(xitems, yitems));
|
public void clear ()
|
||||||
|
{
|
||||||
if (DEBUG_SORT) {
|
for (int icount = _items.size(); icount > 0; icount--) {
|
||||||
Log.info("Sorted for render " +
|
DirtyItem item = (DirtyItem)_items.remove(0);
|
||||||
"[items=" + toString(ritems) + "].");
|
item.clear();
|
||||||
|
_freelist.add(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ritems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,11 +147,16 @@ public class DirtyItemList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all items in the list.
|
* Obtains a new dirty item instance, reusing an old one if possible
|
||||||
|
* or creating a new one otherwise.
|
||||||
*/
|
*/
|
||||||
public void clear ()
|
protected DirtyItem getDirtyItem ()
|
||||||
{
|
{
|
||||||
_items.clear();
|
if (_freelist.size() > 0) {
|
||||||
|
return (DirtyItem)_freelist.remove(0);
|
||||||
|
} else {
|
||||||
|
return new DirtyItem();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -127,7 +166,12 @@ public class DirtyItemList
|
|||||||
*/
|
*/
|
||||||
protected static String toString (DirtyItem a, DirtyItem b)
|
protected static String toString (DirtyItem a, DirtyItem b)
|
||||||
{
|
{
|
||||||
return toString(new DirtyItem[] { a, b });
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append("[(ox=").append(a.ox);
|
||||||
|
buf.append(", oy=").append(a.oy).append("), ");
|
||||||
|
buf.append("(ox=").append(b.ox);
|
||||||
|
buf.append(", oy=").append(b.oy).append(")");
|
||||||
|
return buf.append("]").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,14 +179,15 @@ public class DirtyItemList
|
|||||||
* items describing each by only its origin coordinates. Intended for
|
* items describing each by only its origin coordinates. Intended for
|
||||||
* debugging purposes.
|
* debugging purposes.
|
||||||
*/
|
*/
|
||||||
protected static String toString (DirtyItem[] items)
|
protected static String toString (SortableArrayList items)
|
||||||
{
|
{
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
buf.append("[");
|
buf.append("[");
|
||||||
for (int ii = 0; ii < items.length; ii++) {
|
for (int ii = 0; ii < items.size(); ii++) {
|
||||||
buf.append("(ox=").append(items[ii].ox);
|
DirtyItem item = (DirtyItem)items.get(ii);
|
||||||
buf.append(", oy=").append(items[ii].oy).append(")");
|
buf.append("(ox=").append(item.ox);
|
||||||
if (ii < (items.length - 1)) {
|
buf.append(", oy=").append(item.oy).append(")");
|
||||||
|
if (ii < (items.size() - 1)) {
|
||||||
buf.append(", ");
|
buf.append(", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -160,7 +205,7 @@ public class DirtyItemList
|
|||||||
public Object obj;
|
public Object obj;
|
||||||
|
|
||||||
/** The bounds of the dirty item if it's an object tile. */
|
/** The bounds of the dirty item if it's an object tile. */
|
||||||
public Shape bounds;
|
public Rectangle bounds;
|
||||||
|
|
||||||
/** The footprint of the dirty item if it's an object tile and
|
/** The footprint of the dirty item if it's an object tile and
|
||||||
* we're drawing footprints. */
|
* we're drawing footprints. */
|
||||||
@@ -175,25 +220,21 @@ public class DirtyItemList
|
|||||||
/** The rightmost tile coordinates. */
|
/** The rightmost tile coordinates. */
|
||||||
public int rx, ry;
|
public int rx, ry;
|
||||||
|
|
||||||
/** The dirty rectangle. */
|
|
||||||
public Rectangle dirtyRect;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a dirty item.
|
* Initializes a dirty item.
|
||||||
*/
|
*/
|
||||||
public DirtyItem (Object obj, Shape bounds, Shape footprint,
|
public void init (Object obj, Rectangle bounds, Shape footprint,
|
||||||
int x, int y, Rectangle dirtyRect)
|
int x, int y)
|
||||||
{
|
{
|
||||||
this.obj = obj;
|
this.obj = obj;
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.footprint = footprint;
|
this.footprint = footprint;
|
||||||
this.ox = x;
|
this.ox = x;
|
||||||
this.oy = y;
|
this.oy = y;
|
||||||
this.dirtyRect = dirtyRect;
|
|
||||||
|
|
||||||
// calculate the item's leftmost and rightmost tiles.
|
// calculate the item's leftmost and rightmost tiles; note
|
||||||
// note that sprites occupy only a single tile, so
|
// that sprites occupy only a single tile, so leftmost and
|
||||||
// leftmost and rightmost tiles are equivalent
|
// rightmost tiles are equivalent
|
||||||
lx = rx = ox;
|
lx = rx = ox;
|
||||||
ly = ry = oy;
|
ly = ry = oy;
|
||||||
if (obj instanceof ObjectTile) {
|
if (obj instanceof ObjectTile) {
|
||||||
@@ -208,13 +249,8 @@ public class DirtyItemList
|
|||||||
* the portion of the item that falls within the given dirty
|
* the portion of the item that falls within the given dirty
|
||||||
* rectangle is actually drawn.
|
* rectangle is actually drawn.
|
||||||
*/
|
*/
|
||||||
public void paint (Graphics2D gfx, Rectangle clip)
|
public void paint (Graphics2D gfx)
|
||||||
{
|
{
|
||||||
Shape oclip = gfx.getClip();
|
|
||||||
|
|
||||||
// clip the draw region to the dirty portion of the item
|
|
||||||
gfx.clip(clip);
|
|
||||||
|
|
||||||
// if there's a footprint, paint that
|
// if there's a footprint, paint that
|
||||||
if (footprint != null) {
|
if (footprint != null) {
|
||||||
gfx.setColor(Color.black);
|
gfx.setColor(Color.black);
|
||||||
@@ -225,11 +261,19 @@ public class DirtyItemList
|
|||||||
if (obj instanceof Sprite) {
|
if (obj instanceof Sprite) {
|
||||||
((Sprite)obj).paint(gfx);
|
((Sprite)obj).paint(gfx);
|
||||||
} else {
|
} else {
|
||||||
((ObjectTile)obj).paint(gfx, bounds);
|
((ObjectTile)obj).paint(gfx, bounds.x, bounds.y);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// restore original clipping region
|
/**
|
||||||
gfx.setClip(oclip);
|
* Releases all references held by this dirty item so that it
|
||||||
|
* doesn't inadvertently hold on to any objects while waiting to
|
||||||
|
* be reused.
|
||||||
|
*/
|
||||||
|
public void clear ()
|
||||||
|
{
|
||||||
|
obj = null;
|
||||||
|
bounds = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -309,18 +353,8 @@ public class DirtyItemList
|
|||||||
* suitable for rendering in the isometric view with proper visual
|
* suitable for rendering in the isometric view with proper visual
|
||||||
* results.
|
* results.
|
||||||
*/
|
*/
|
||||||
protected static class RenderComparator implements Comparator
|
protected class RenderComparator implements Comparator
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Constructs a render comparator with the given list of
|
|
||||||
* pre-sorted dirty item lists for each axis.
|
|
||||||
*/
|
|
||||||
public RenderComparator (DirtyItem[] xitems, DirtyItem[] yitems)
|
|
||||||
{
|
|
||||||
_xitems = xitems;
|
|
||||||
_yitems = yitems;
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
public int compare (Object a, Object b)
|
public int compare (Object a, Object b)
|
||||||
{
|
{
|
||||||
@@ -374,7 +408,7 @@ public class DirtyItemList
|
|||||||
int axis, DirtyItem da, DirtyItem db)
|
int axis, DirtyItem da, DirtyItem db)
|
||||||
{
|
{
|
||||||
// prepare for the partitioning check
|
// prepare for the partitioning check
|
||||||
DirtyItem[] sitems;
|
SortableArrayList sitems;
|
||||||
Comparator comp;
|
Comparator comp;
|
||||||
boolean swapped = false;
|
boolean swapped = false;
|
||||||
switch (axis) {
|
switch (axis) {
|
||||||
@@ -420,14 +454,14 @@ public class DirtyItemList
|
|||||||
|
|
||||||
// get the bounding item indices and the number of
|
// get the bounding item indices and the number of
|
||||||
// potentially-partitioning dirty items
|
// potentially-partitioning dirty items
|
||||||
int aidx = Arrays.binarySearch(sitems, da, comp);
|
int aidx = sitems.binarySearch(da, comp);
|
||||||
int bidx = Arrays.binarySearch(sitems, db, comp);
|
int bidx = sitems.binarySearch(db, comp);
|
||||||
int size = bidx - aidx - 1;
|
int size = bidx - aidx - 1;
|
||||||
|
|
||||||
// check each potentially partitioning item
|
// check each potentially partitioning item
|
||||||
int startidx = aidx + 1, endidx = startidx + size;
|
int startidx = aidx + 1, endidx = startidx + size;
|
||||||
for (int pidx = startidx; pidx < endidx; pidx++) {
|
for (int pidx = startidx; pidx < endidx; pidx++) {
|
||||||
DirtyItem dp = sitems[pidx];
|
DirtyItem dp = (DirtyItem)sitems.get(pidx);
|
||||||
if (dp.obj instanceof MisoCharacterSprite) {
|
if (dp.obj instanceof MisoCharacterSprite) {
|
||||||
// character sprites can't partition things
|
// character sprites can't partition things
|
||||||
continue;
|
continue;
|
||||||
@@ -503,12 +537,6 @@ public class DirtyItemList
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The items in the dirty item list sorted by ascending x origin. */
|
|
||||||
protected DirtyItem[] _xitems;
|
|
||||||
|
|
||||||
/** The items in the dirty item list sorted by ascending y origin. */
|
|
||||||
protected DirtyItem[] _yitems;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether to log debug info when comparing pairs of dirty items. */
|
/** Whether to log debug info when comparing pairs of dirty items. */
|
||||||
@@ -532,5 +560,17 @@ public class DirtyItemList
|
|||||||
new OriginComparator(Y_AXIS);
|
new OriginComparator(Y_AXIS);
|
||||||
|
|
||||||
/** The list of dirty items. */
|
/** The list of dirty items. */
|
||||||
protected ArrayList _items = new ArrayList();
|
protected SortableArrayList _items = new SortableArrayList();
|
||||||
|
|
||||||
|
/** The list of dirty items sorted by x-position. */
|
||||||
|
protected SortableArrayList _xitems = new SortableArrayList();
|
||||||
|
|
||||||
|
/** The list of dirty items sorted by y-position. */
|
||||||
|
protected SortableArrayList _yitems = new SortableArrayList();
|
||||||
|
|
||||||
|
/** The render comparator we'll use for our final, magical sort. */
|
||||||
|
protected Comparator _rcomp = new RenderComparator();
|
||||||
|
|
||||||
|
/** Unused dirty items. */
|
||||||
|
protected ArrayList _freelist = new ArrayList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: IsoSceneView.java,v 1.111 2002/06/18 21:22:34 ray Exp $
|
// $Id: IsoSceneView.java,v 1.112 2002/06/18 22:38:12 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
@@ -78,14 +78,8 @@ public class IsoSceneView implements SceneView
|
|||||||
_model = model;
|
_model = model;
|
||||||
_remgr = remgr;
|
_remgr = remgr;
|
||||||
|
|
||||||
// create a cache which will be populated with the tile polygons
|
// handy rectangle
|
||||||
// as they are requested. We manually adjust the size/load factor
|
_tbounds = new Rectangle(0, 0, _model.tilewid, _model.tilehei);
|
||||||
// to optimize memory usage (because we happen to know things
|
|
||||||
// hash weirdly because of the way we make the keys.
|
|
||||||
_polys = new HashIntMap(model.scenewid, (float) model.scenehei);
|
|
||||||
|
|
||||||
// create the array used to mark dirty tiles
|
|
||||||
_dirty = new boolean[model.scenewid][model.tilehei];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,80 +126,21 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
// documentation inherited from interface
|
||||||
public void viewWillScroll (int dx, int dy)
|
public void paint (Graphics2D gfx, Rectangle dirtyRect)
|
||||||
{
|
|
||||||
// adjust our offsets
|
|
||||||
_xoff += dx;
|
|
||||||
_yoff += dy;
|
|
||||||
|
|
||||||
// determine whether or not this scrolling causes us to cross
|
|
||||||
// boundaries in the x or y directions
|
|
||||||
if (_xoff >= _model.tilehwid) {
|
|
||||||
_tiledx += 1;
|
|
||||||
_tiledy -= 1;
|
|
||||||
_xoff -= _model.tilewid;
|
|
||||||
|
|
||||||
} else if (_xoff < -_model.tilehwid) {
|
|
||||||
_tiledx -= 1;
|
|
||||||
_tiledy += 1;
|
|
||||||
_xoff += _model.tilewid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_yoff >= _model.tilehhei) {
|
|
||||||
_tiledx += 1;
|
|
||||||
_tiledy += 1;
|
|
||||||
_yoff -= _model.tilehei;
|
|
||||||
|
|
||||||
} else if (_yoff < -_model.tilehhei) {
|
|
||||||
_tiledx -= 1;
|
|
||||||
_tiledy -= 1;
|
|
||||||
_yoff += _model.tilehei;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// documentation inherited from interface
|
|
||||||
public void paint (Graphics2D gfx, Rectangle[] dirtyRects)
|
|
||||||
{
|
{
|
||||||
if (_scene == null) {
|
if (_scene == null) {
|
||||||
Log.warning("Scene view painted with null scene.");
|
Log.warning("Scene view painted with null scene.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log.info("Rendering: " + StringUtil.toString(dirtyRects) +
|
// render any intersecting tiles
|
||||||
// ", clip: " + StringUtil.toString(gfx.getClip()));
|
renderTiles(gfx, dirtyRect);
|
||||||
|
|
||||||
// // invalidate the invalid rectangles
|
// render anything that goes on top of the tiles
|
||||||
// int rsize = dirtyRects.length;
|
renderBaseDecorations(gfx, dirtyRect);
|
||||||
// for (int ii = 0; ii < rsize; ii++) {
|
|
||||||
// invalidateRect(dirtyRects[ii]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// translate according to our scroll parameters
|
// render our dirty sprites and objects
|
||||||
gfx.translate(-_xoff, -_yoff);
|
renderDirtyItems(gfx, dirtyRect);
|
||||||
|
|
||||||
// render the scrolling part of the scene
|
|
||||||
int rcount = dirtyRects.length;
|
|
||||||
for (int ii = 0; ii < rcount; ii++) {
|
|
||||||
Rectangle rect = dirtyRects[ii];
|
|
||||||
rect.translate(_xoff, _yoff);
|
|
||||||
Shape oclip = gfx.getClip();
|
|
||||||
gfx.clipRect(rect.x, rect.y, rect.width, rect.height);
|
|
||||||
renderScrollingScene(gfx, rect);
|
|
||||||
gfx.setClip(oclip);
|
|
||||||
rect.translate(-_xoff, -_yoff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// untranslate according to our scroll parameters
|
|
||||||
gfx.translate(_xoff, _yoff);
|
|
||||||
|
|
||||||
// render the fixed part of the scene
|
|
||||||
for (int ii = 0; ii < rcount; ii++) {
|
|
||||||
Rectangle rect = dirtyRects[ii];
|
|
||||||
Shape oclip = gfx.getClip();
|
|
||||||
gfx.clipRect(rect.x, rect.y, rect.width, rect.height);
|
|
||||||
renderFixedScene(gfx, rect);
|
|
||||||
gfx.setClip(oclip);
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw sprite paths
|
// draw sprite paths
|
||||||
if (_model.showPaths) {
|
if (_model.showPaths) {
|
||||||
@@ -213,10 +148,10 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
|
|
||||||
// paint our highlighted tile (if any)
|
// paint our highlighted tile (if any)
|
||||||
paintHighlights(gfx);
|
paintHighlights(gfx, dirtyRect);
|
||||||
|
|
||||||
// paint any extra goodies
|
// paint any extra goodies
|
||||||
paintExtras(gfx);
|
paintExtras(gfx, dirtyRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,7 +159,7 @@ public class IsoSceneView implements SceneView
|
|||||||
*
|
*
|
||||||
* @param gfx the graphics context.
|
* @param gfx the graphics context.
|
||||||
*/
|
*/
|
||||||
protected void paintHighlights (Graphics2D gfx)
|
protected void paintHighlights (Graphics2D gfx, Rectangle clip)
|
||||||
{
|
{
|
||||||
// if we're not highlighting object tiles, bail now
|
// if we're not highlighting object tiles, bail now
|
||||||
if (_hmode == HIGHLIGHT_NEVER) {
|
if (_hmode == HIGHLIGHT_NEVER) {
|
||||||
@@ -241,8 +176,8 @@ public class IsoSceneView implements SceneView
|
|||||||
// this one has an action
|
// this one has an action
|
||||||
String action = _scene.getObjectAction(otile);
|
String action = _scene.getObjectAction(otile);
|
||||||
if (_hmode != HIGHLIGHT_WITH_ACTION || !StringUtil.blank(action)) {
|
if (_hmode != HIGHLIGHT_WITH_ACTION || !StringUtil.blank(action)) {
|
||||||
Polygon tpoly = getTilePoly(_hcoords.x, _hcoords.y);
|
hpoly = IsoUtil.getObjectFootprint(
|
||||||
hpoly = IsoUtil.getObjectFootprint(_model, tpoly, otile);
|
_model, _hcoords.x, _hcoords.y, otile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +185,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 = getTilePoly(_hcoords.x, _hcoords.y);
|
hpoly = IsoUtil.getTilePolygon(_model, _hcoords.x, _hcoords.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we've determined that there's something to highlight
|
// if we've determined that there's something to highlight
|
||||||
@@ -272,94 +207,133 @@ public class IsoSceneView implements SceneView
|
|||||||
* A function where derived classes can paint extra stuff while we've
|
* A function where derived classes can paint extra stuff while we've
|
||||||
* got the clipping region set up.
|
* got the clipping region set up.
|
||||||
*/
|
*/
|
||||||
protected void paintExtras (Graphics2D gfx)
|
protected void paintExtras (Graphics2D gfx, Rectangle clip)
|
||||||
{
|
{
|
||||||
// nothing for now
|
// nothing for now
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the scrolling part of the scene to the given graphics
|
|
||||||
* context.
|
|
||||||
*
|
|
||||||
* @param gfx the graphics context.
|
|
||||||
*/
|
|
||||||
protected void renderScrollingScene (Graphics2D gfx, Rectangle clip)
|
|
||||||
{
|
|
||||||
// render any intersecting tiles
|
|
||||||
renderTiles(gfx, clip);
|
|
||||||
|
|
||||||
// render anything that goes on top of the tiles
|
|
||||||
renderBaseDecorations(gfx, clip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the non-scrolling part of the scene to the given graphics
|
|
||||||
* context.
|
|
||||||
*
|
|
||||||
* @param gfx the graphics context.
|
|
||||||
*/
|
|
||||||
protected void renderFixedScene (Graphics2D gfx, Rectangle clip)
|
|
||||||
{
|
|
||||||
renderDirtyItems(gfx, clip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the base and fringe layer tiles that intersect the
|
* Renders the base and fringe layer tiles that intersect the
|
||||||
* specified clipping rectangle.
|
* specified clipping rectangle.
|
||||||
*/
|
*/
|
||||||
protected void renderTiles (Graphics2D gfx, Rectangle clip)
|
protected void renderTiles (Graphics2D gfx, Rectangle clip)
|
||||||
{
|
{
|
||||||
FontMetrics fm = gfx.getFontMetrics(_font);
|
// if we're showing coordinates, we need to do some setting up
|
||||||
int fhei = fm.getAscent();
|
int thw = 0, thh = 0, fhei = 0;
|
||||||
int cx = _model.tilehwid, cy = _model.tilehhei;
|
FontMetrics fm = null;
|
||||||
|
|
||||||
if (_model.showCoords) {
|
if (_model.showCoords) {
|
||||||
|
fm = gfx.getFontMetrics(_font);
|
||||||
|
fhei = fm.getAscent();
|
||||||
|
thw = _model.tilehwid;
|
||||||
|
thh = _model.tilehhei;
|
||||||
gfx.setFont(_font);
|
gfx.setFont(_font);
|
||||||
gfx.setColor(Color.white);
|
gfx.setColor(Color.white);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int yy = 0; yy < _model.scenehei; yy++) {
|
|
||||||
for (int xx = 0; xx < _model.scenewid; xx++) {
|
|
||||||
Polygon tpoly = getTilePoly(xx, yy);
|
|
||||||
|
|
||||||
// skip non-intersecting tiles
|
// determine which tiles intersect this clipping region: this is
|
||||||
// if (!tpoly.intersects(clip)) {
|
// going to be nearly incomprehensible without some sort of
|
||||||
if (!tpoly.getBounds().intersects(clip)) {
|
// diagram; i'll do what i can to comment it, but you'll want to
|
||||||
continue;
|
// print out a scene diagram (docs/miso/scene.ps) and start making
|
||||||
}
|
// notes if you want to follow along
|
||||||
|
|
||||||
// offset the tile coordinates by our scrolled deltas
|
// obtain our upper left tile
|
||||||
int tx = xx + _tiledx, ty = yy + _tiledy;
|
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
|
// draw the base and fringe tile images
|
||||||
Tile tile;
|
try {
|
||||||
if ((tile = _scene.getBaseTile(tx, ty)) != null) {
|
Tile tile;
|
||||||
tile.paint(gfx, tpoly);
|
if ((tile = _scene.getBaseTile(tx, ty)) != null) {
|
||||||
}
|
tile.paint(gfx, _tbounds.x, _tbounds.y);
|
||||||
if ((tile = _scene.getFringeTile(tx, ty)) != null) {
|
}
|
||||||
tile.paint(gfx, tpoly);
|
if ((tile = _scene.getFringeTile(tx, ty)) != null) {
|
||||||
|
tile.paint(gfx, _tbounds.x, _tbounds.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
} 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 we're showing coordinates, do that
|
||||||
if (_model.showCoords) {
|
if (_model.showCoords) {
|
||||||
// outline the tile
|
// outline the tile
|
||||||
gfx.draw(tpoly);
|
// gfx.draw(tpoly);
|
||||||
|
|
||||||
// get the top-left screen coordinates of the tile
|
// get the top-left screen coordinates of the tile
|
||||||
Rectangle bounds = tpoly.getBounds();
|
int sx = _tbounds.x, sy = _tbounds.y;
|
||||||
int sx = bounds.x, sy = bounds.y;
|
|
||||||
|
|
||||||
// draw x-coordinate
|
// draw x-coordinate
|
||||||
String str = String.valueOf(xx + _tiledx);
|
String str = String.valueOf(tx);
|
||||||
int xpos = sx + cx - (fm.stringWidth(str) / 2);
|
int xpos = sx + thw - (fm.stringWidth(str) / 2);
|
||||||
gfx.drawString(str, xpos, sy + cy);
|
gfx.drawString(str, xpos, sy + thh);
|
||||||
|
|
||||||
// draw y-coordinate
|
// draw y-coordinate
|
||||||
str = String.valueOf(yy + _tiledy);
|
str = String.valueOf(ty);
|
||||||
xpos = sx + cx - (fm.stringWidth(str) / 2);
|
xpos = sx + thw - (fm.stringWidth(str) / 2);
|
||||||
gfx.drawString(str, xpos, sy + cy + fhei);
|
gfx.drawString(str, xpos, sy + thh + fhei);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -379,20 +353,57 @@ public class IsoSceneView implements SceneView
|
|||||||
*/
|
*/
|
||||||
protected void renderDirtyItems (Graphics2D gfx, Rectangle clip)
|
protected void renderDirtyItems (Graphics2D gfx, Rectangle clip)
|
||||||
{
|
{
|
||||||
invalidateItems(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++) {
|
||||||
|
MisoCharacterSprite sprite = (MisoCharacterSprite)
|
||||||
|
_dirtySprites.get(ii);
|
||||||
|
Rectangle bounds = sprite.getBounds();
|
||||||
|
if (!bounds.intersects(clip)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dirtyItems.appendDirtySprite(
|
||||||
|
sprite, sprite.getTileX(), sprite.getTileY());
|
||||||
|
// Log.info("Dirtied item: " + sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add any objects impacted by the dirty rectangle
|
||||||
|
Iterator iter = _objects.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
ObjectMetrics metrics = (ObjectMetrics)iter.next();
|
||||||
|
Rectangle obounds = metrics.bounds;
|
||||||
|
if (!obounds.intersects(clip)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute the footprint if we're rendering those
|
||||||
|
Polygon foot = null;
|
||||||
|
if (_model.showFootprints) {
|
||||||
|
foot = IsoUtil.getObjectFootprint(
|
||||||
|
_model, metrics.x, metrics.y, metrics.tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the object to the dirty items list
|
||||||
|
_dirtyItems.appendDirtyObject(
|
||||||
|
metrics.tile, obounds, foot, metrics.x, metrics.y);
|
||||||
|
// Log.info("Dirtied item: Object(" +
|
||||||
|
// metrics.x + ", " + metrics.y + ")");
|
||||||
|
}
|
||||||
|
|
||||||
// Log.info("renderDirtyItems [items=" + _dirtyItems.size() + "].");
|
// Log.info("renderDirtyItems [items=" + _dirtyItems.size() + "].");
|
||||||
|
|
||||||
// sort the dirty sprites and objects visually back-to-front
|
// sort the dirty sprites and objects visually back-to-front;
|
||||||
DirtyItem items[] = _dirtyItems.sort();
|
// paint them and be done
|
||||||
|
_dirtyItems.sort();
|
||||||
// render each item clipping to its dirty rectangle
|
_dirtyItems.paintAndClear(gfx);
|
||||||
for (int ii = 0; ii < items.length; ii++) {
|
|
||||||
items[ii].paint(gfx, items[ii].dirtyRect);
|
|
||||||
// Log.info("Painting item [item=" + items[ii] + "].");
|
|
||||||
}
|
|
||||||
|
|
||||||
_dirtyItems.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -424,8 +435,7 @@ public class IsoSceneView implements SceneView
|
|||||||
metrics.tile = tile;
|
metrics.tile = tile;
|
||||||
metrics.x = x;
|
metrics.x = x;
|
||||||
metrics.y = y;
|
metrics.y = y;
|
||||||
metrics.bounds = IsoUtil.getObjectBounds(
|
metrics.bounds = IsoUtil.getObjectBounds(_model, x, y, tile);
|
||||||
_model, getTilePoly(x, y), tile);
|
|
||||||
|
|
||||||
// and add it to the list
|
// and add it to the list
|
||||||
_objects.add(metrics);
|
_objects.add(metrics);
|
||||||
@@ -446,211 +456,6 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the polygon bounding the tile at the specified coordinates.
|
|
||||||
*/
|
|
||||||
protected Polygon getTilePoly (int x, int y)
|
|
||||||
{
|
|
||||||
int key = IsoUtil.coordsToKey(x, y);
|
|
||||||
|
|
||||||
Polygon poly = (Polygon) _polys.get(key);
|
|
||||||
if (poly == null) {
|
|
||||||
poly = IsoUtil.getTilePolygon(_model, x, y);
|
|
||||||
_polys.put(key, poly);
|
|
||||||
}
|
|
||||||
return poly;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invalidates the given rectangle in screen pixel coordinates in the
|
|
||||||
* view. Returns a rectangle that bounds all tiles that were dirtied.
|
|
||||||
*
|
|
||||||
* @param rect the dirty rectangle.
|
|
||||||
*/
|
|
||||||
protected Rectangle invalidateScreenRect (Rectangle r)
|
|
||||||
{
|
|
||||||
// Log.info("Invalidating [rect=" + r +
|
|
||||||
// ", xoff=" + _xoff + ", yoff=" + _yoff + "].");
|
|
||||||
|
|
||||||
// account for our current scrolling offset
|
|
||||||
int rx = r.x + _xoff, ry = r.y + _yoff;
|
|
||||||
|
|
||||||
// initialize the rectangle bounding all tiles dirtied by the
|
|
||||||
// invalidated rectangle
|
|
||||||
Rectangle tileBounds = new Rectangle(-1, -1, 0, 0);
|
|
||||||
|
|
||||||
// note that corner tiles may be included unnecessarily, but
|
|
||||||
// checking to determine whether they're actually needed
|
|
||||||
// complicates the code with likely-insufficient benefit
|
|
||||||
|
|
||||||
// determine the top-left tile impacted by this rect
|
|
||||||
Point tpos = new Point();
|
|
||||||
IsoUtil.screenToTile(_model, rx, ry, tpos);
|
|
||||||
|
|
||||||
// determine screen coordinates for top-left tile
|
|
||||||
Point topleft = new Point();
|
|
||||||
IsoUtil.tileToScreen(_model, tpos.x, tpos.y, topleft);
|
|
||||||
|
|
||||||
// determine number of horizontal tiles for rect
|
|
||||||
int numh = (int)Math.ceil((float)r.width / (float)_model.tilewid);
|
|
||||||
|
|
||||||
// set up iterating variables
|
|
||||||
int tx = tpos.x, ty = tpos.y, mx = tpos.x, my = tpos.y;
|
|
||||||
|
|
||||||
// set the starting screen y-position
|
|
||||||
int screenY = topleft.y;
|
|
||||||
|
|
||||||
// add top row if rect may overlap
|
|
||||||
if (ry < (screenY + _model.tilehhei)) {
|
|
||||||
ty--;
|
|
||||||
for (int ii = 0; ii < numh; ii++) {
|
|
||||||
addDirtyTile(tileBounds, tx++, ty--);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine the bottom-left tile impacted by this rect
|
|
||||||
Point bpos = new Point();
|
|
||||||
IsoUtil.screenToTile(_model, rx, ry + r.height, bpos);
|
|
||||||
|
|
||||||
// determine screen coordinates for bottom-left tile
|
|
||||||
Point botleft = new Point();
|
|
||||||
IsoUtil.tileToScreen(_model, bpos.x, bpos.y, botleft);
|
|
||||||
|
|
||||||
// determine the number of vertical rows for our rect (we do this
|
|
||||||
// by subtracting the "height" of the top tile from that of the
|
|
||||||
// bottom tile, the height being the sum of the x and y
|
|
||||||
// coordinate)
|
|
||||||
int numv = (bpos.x + bpos.y) - (tpos.x + tpos.y);
|
|
||||||
|
|
||||||
// now we need to extend the rect to contain the row containing
|
|
||||||
// the bottom tile, and potentially the row below that
|
|
||||||
numv += ((ry + r.height) > (botleft.y + _model.tilehhei)) ? 2 : 1;
|
|
||||||
|
|
||||||
// add dirty tiles from each affected row
|
|
||||||
for (int ii = 0; ii < numv; ii++) {
|
|
||||||
|
|
||||||
// set up iterating variables for this row
|
|
||||||
tx = mx;
|
|
||||||
ty = my;
|
|
||||||
int length = numh;
|
|
||||||
|
|
||||||
// set the starting screen x-position
|
|
||||||
int screenX = topleft.x;
|
|
||||||
if (ii%2 == 1) {
|
|
||||||
screenX -= _model.tilehwid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip leftmost tile if rect doesn't overlap
|
|
||||||
if (rx > screenX + _model.tilewid) {
|
|
||||||
tx++;
|
|
||||||
ty--;
|
|
||||||
screenX += _model.tilewid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add to the right edge if rect may overlap
|
|
||||||
if (rx + r.width > (screenX + (length * _model.tilewid))) {
|
|
||||||
length++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add all tiles in the row to the dirty set
|
|
||||||
for (int jj = 0; jj < length; jj++) {
|
|
||||||
addDirtyTile(tileBounds, tx++, ty--);
|
|
||||||
}
|
|
||||||
|
|
||||||
// step along the x- or y-axis appropriately
|
|
||||||
if (ii%2 == 1) {
|
|
||||||
mx++;
|
|
||||||
} else {
|
|
||||||
my++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tileBounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks the tile at the given coordinates dirty and expands the tile
|
|
||||||
* bounds rectangle to include the rectangle for the dirtied tile.
|
|
||||||
*/
|
|
||||||
protected boolean addDirtyTile (Rectangle tileBounds, int x, int y)
|
|
||||||
{
|
|
||||||
if (!_model.isCoordinateValid(x, y)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// expand the tile bounds rectangle to include this tile
|
|
||||||
Rectangle bounds = getTilePoly(x, y).getBounds();
|
|
||||||
if (tileBounds.x == -1) {
|
|
||||||
tileBounds.setBounds(bounds);
|
|
||||||
} else {
|
|
||||||
tileBounds.add(bounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do nothing if the tile's already dirty
|
|
||||||
if (_dirty[x][y]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mark the tile dirty
|
|
||||||
_numDirty++;
|
|
||||||
_dirty[x][y] = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds any sprites or objects in the scene whose bounds overlap
|
|
||||||
* with the given dirty rectangle to the dirty item list for later
|
|
||||||
* re-rendering.
|
|
||||||
*/
|
|
||||||
protected void invalidateItems (Rectangle r)
|
|
||||||
{
|
|
||||||
// add any sprites impacted by the dirty rectangle
|
|
||||||
_dirtySprites.clear();
|
|
||||||
_spritemgr.getIntersectingSprites(_dirtySprites, r);
|
|
||||||
|
|
||||||
int size = _dirtySprites.size();
|
|
||||||
for (int ii = 0; ii < size; ii++) {
|
|
||||||
MisoCharacterSprite sprite =
|
|
||||||
(MisoCharacterSprite)_dirtySprites.get(ii);
|
|
||||||
|
|
||||||
// get the dirty portion of the sprite
|
|
||||||
Rectangle drect = sprite.getBounds().intersection(r);
|
|
||||||
|
|
||||||
_dirtyItems.appendDirtySprite(
|
|
||||||
sprite, sprite.getTileX(), sprite.getTileY(), drect);
|
|
||||||
// Log.info("Dirtied item: " + sprite);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add any objects impacted by the dirty rectangle
|
|
||||||
if (_scene != null) {
|
|
||||||
Iterator iter = _objects.iterator();
|
|
||||||
while (iter.hasNext()) {
|
|
||||||
ObjectMetrics metrics = (ObjectMetrics)iter.next();
|
|
||||||
Rectangle obounds = metrics.bounds;
|
|
||||||
if (!obounds.intersects(r)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the dirty portion of the object
|
|
||||||
Rectangle drect = obounds.intersection(r);
|
|
||||||
int tx = metrics.x, ty = metrics.y;
|
|
||||||
|
|
||||||
// compute the footprint if we're rendering those
|
|
||||||
Polygon foot = null;
|
|
||||||
if (_model.showFootprints) {
|
|
||||||
foot = IsoUtil.getObjectFootprint(
|
|
||||||
_model, getTilePoly(tx, ty), metrics.tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the intersected section of the object to the dirty
|
|
||||||
// items list
|
|
||||||
_dirtyItems.appendDirtyObject(
|
|
||||||
metrics.tile, obounds, foot, tx, ty, drect);
|
|
||||||
// Log.info("Dirtied item: Object(" + tx + ", " + ty + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a path between the two points (in screen coordinates)
|
* Get a path between the two points (in screen coordinates)
|
||||||
* that will update a MisoCharacterSprite as it walks the path.
|
* that will update a MisoCharacterSprite as it walks the path.
|
||||||
@@ -677,8 +482,7 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get the destination tile coordinates
|
// get the destination tile coordinates
|
||||||
Point dest = new Point();
|
Point dest = IsoUtil.screenToTile(_model, x, y, new Point());
|
||||||
IsoUtil.screenToTile(_model, x + _xoff, y + _yoff, dest);
|
|
||||||
|
|
||||||
// get a reasonable tile path through the scene
|
// get a reasonable tile path through the scene
|
||||||
List points = AStarPathUtil.getPath(
|
List points = AStarPathUtil.getPath(
|
||||||
@@ -693,20 +497,13 @@ public class IsoSceneView implements SceneView
|
|||||||
// documentation inherited
|
// documentation inherited
|
||||||
public Point getScreenCoords (int x, int y)
|
public Point getScreenCoords (int x, int y)
|
||||||
{
|
{
|
||||||
Point coords = new Point();
|
return IsoUtil.fullToScreen(_model, x, y, new Point());
|
||||||
IsoUtil.fullToScreen(_model, x, y, coords);
|
|
||||||
// adjust for our scrolling offset
|
|
||||||
coords.x -= _xoff;
|
|
||||||
coords.y -= _yoff;
|
|
||||||
return coords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
public Point getFullCoords (int x, int y)
|
public Point getFullCoords (int x, int y)
|
||||||
{
|
{
|
||||||
Point coords = new Point();
|
return IsoUtil.screenToFull(_model, x, y, new Point());
|
||||||
IsoUtil.screenToFull(_model, x + _xoff, y + _yoff, coords);
|
|
||||||
return coords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
@@ -722,36 +519,36 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compute the list of objects over which the mouse is hovering
|
// compute the list of objects over which the mouse is hovering
|
||||||
_hitList.clear();
|
Object hobject = null;
|
||||||
_hitSprites.clear();
|
|
||||||
// add the sprites that contain the point
|
// start with the sprites that contain the point
|
||||||
_spritemgr.getHitSprites(_hitSprites, x, y);
|
_spritemgr.getHitSprites(_hitSprites, x, y);
|
||||||
int hslen = _hitSprites.size();
|
int hslen = _hitSprites.size();
|
||||||
for (int i = 0; i < hslen; i++) {
|
for (int i = 0; i < hslen; i++) {
|
||||||
MisoCharacterSprite sprite =
|
MisoCharacterSprite sprite =
|
||||||
(MisoCharacterSprite)_hitSprites.get(i);
|
(MisoCharacterSprite)_hitSprites.get(i);
|
||||||
_hitList.appendDirtySprite(
|
_hitList.appendDirtySprite(
|
||||||
sprite, sprite.getTileX(), sprite.getTileY(),
|
sprite, sprite.getTileX(), sprite.getTileY());
|
||||||
sprite.getBounds());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the object tiles that contain the point
|
// add the object tiles that contain the point
|
||||||
getHitObjects(_hitList, x, y);
|
getHitObjects(_hitList, x, y);
|
||||||
|
|
||||||
// sort the list of hit items by rendering order
|
// sort the list of hit items by rendering order
|
||||||
Object hobject = null;
|
_hitList.sort();
|
||||||
DirtyItem[] items = _hitList.sort();
|
|
||||||
// the last element in the array is what we want (assuming there
|
// the last element in the array is what we want (assuming there
|
||||||
// are any items in the array)
|
// are any items in the array)
|
||||||
if (items.length > 0) {
|
int icount = _hitList.size();
|
||||||
hobject = items[items.length-1].obj;
|
if (icount > 0) {
|
||||||
}
|
DirtyItem item = (DirtyItem)_hitList.get(icount-1);
|
||||||
|
hobject = item.obj;
|
||||||
|
|
||||||
// if this is an object tile, we need to update the hcoords
|
// if this is an object tile, we need to update the hcoords
|
||||||
if (hobject != null && hobject instanceof ObjectTile) {
|
if (hobject instanceof ObjectTile) {
|
||||||
DirtyItem item = items[items.length-1];
|
_hcoords.x = item.ox;
|
||||||
_hcoords.x = item.ox;
|
_hcoords.y = item.oy;
|
||||||
_hcoords.y = item.oy;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this hover object is different than before, we'll need to be
|
// if this hover object is different than before, we'll need to be
|
||||||
@@ -769,6 +566,10 @@ public class IsoSceneView implements SceneView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear out the hitlists
|
||||||
|
_hitList.clear();
|
||||||
|
_hitSprites.clear();
|
||||||
|
|
||||||
return repaint;
|
return repaint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -783,22 +584,21 @@ public class IsoSceneView implements SceneView
|
|||||||
Iterator iter = _objects.iterator();
|
Iterator iter = _objects.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
ObjectMetrics metrics = (ObjectMetrics)iter.next();
|
ObjectMetrics metrics = (ObjectMetrics)iter.next();
|
||||||
|
Rectangle pbounds = metrics.bounds;
|
||||||
// skip polys that don't contain the point
|
// skip polys that don't contain the point
|
||||||
if (!metrics.bounds.contains(x, y)) {
|
if (!pbounds.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 = metrics.x, ty = metrics.y;
|
|
||||||
Rectangle pbounds = metrics.bounds.getBounds();
|
|
||||||
if (!metrics.tile.hitTest(x - pbounds.x, y - pbounds.y)) {
|
if (!metrics.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(metrics.tile, metrics.bounds, null,
|
list.appendDirtyObject(metrics.tile, metrics.bounds, null,
|
||||||
tx, ty, pbounds);
|
metrics.x, metrics.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -838,8 +638,7 @@ public class IsoSceneView implements SceneView
|
|||||||
*/
|
*/
|
||||||
protected boolean updateTileCoords (int sx, int sy, Point tpos)
|
protected boolean updateTileCoords (int sx, int sy, Point tpos)
|
||||||
{
|
{
|
||||||
Point npos = new Point();
|
Point npos = IsoUtil.screenToTile(_model, sx, sy, new Point());
|
||||||
IsoUtil.screenToTile(_model, sx + _xoff, sy + _yoff, npos);
|
|
||||||
|
|
||||||
// make sure the new coordinate is both valid and different
|
// make sure the new coordinate is both valid and different
|
||||||
if (_model.isCoordinateValid(npos.x, npos.y) && !tpos.equals(npos)) {
|
if (_model.isCoordinateValid(npos.x, npos.y) && !tpos.equals(npos)) {
|
||||||
@@ -879,31 +678,18 @@ public class IsoSceneView implements SceneView
|
|||||||
/** The scene to be displayed. */
|
/** The scene to be displayed. */
|
||||||
protected DisplayMisoScene _scene;
|
protected DisplayMisoScene _scene;
|
||||||
|
|
||||||
/** Polygon outlines for all of our base tiles. */
|
|
||||||
protected HashIntMap _polys;
|
|
||||||
|
|
||||||
/** Metric information for all of the object tiles. */
|
/** Metric information for all of the object tiles. */
|
||||||
protected ArrayList _objects = new ArrayList();
|
protected ArrayList _objects = new ArrayList();
|
||||||
|
|
||||||
/** The rendering offsets used to support scrolling. */
|
|
||||||
protected int _xoff = 0, _yoff = 0;
|
|
||||||
|
|
||||||
/** The offsets from (0, 0) in tile coordinates to which we have
|
|
||||||
* scrolled. */
|
|
||||||
protected int _tiledx, _tiledy;
|
|
||||||
|
|
||||||
/** The dirty tiles that need to be re-painted. */
|
|
||||||
protected boolean _dirty[][];
|
|
||||||
|
|
||||||
/** The number of dirty tiles. */
|
|
||||||
protected int _numDirty;
|
|
||||||
|
|
||||||
/** The dirty sprites and objects that need to be re-painted. */
|
/** The dirty sprites and objects that need to be re-painted. */
|
||||||
protected DirtyItemList _dirtyItems = new DirtyItemList();
|
protected DirtyItemList _dirtyItems = new DirtyItemList();
|
||||||
|
|
||||||
/** The working sprites list used when calculating dirty regions. */
|
/** The working sprites list used when calculating dirty regions. */
|
||||||
protected ArrayList _dirtySprites = new ArrayList();
|
protected ArrayList _dirtySprites = new ArrayList();
|
||||||
|
|
||||||
|
/** Used when rendering tiles. */
|
||||||
|
protected Rectangle _tbounds;
|
||||||
|
|
||||||
/** Used to collect the list of sprites "hit" by a particular mouse
|
/** Used to collect the list of sprites "hit" by a particular mouse
|
||||||
* location. */
|
* location. */
|
||||||
protected List _hitSprites = new ArrayList();
|
protected List _hitSprites = new ArrayList();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: SceneView.java,v 1.28 2002/05/31 03:38:03 mdb Exp $
|
// $Id: SceneView.java,v 1.29 2002/06/18 22:38:12 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
@@ -18,21 +18,13 @@ import com.threerings.media.util.Path;
|
|||||||
public interface SceneView
|
public interface SceneView
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Lets the view know that it will be scrolled by the specified number
|
* Renders an invalid porition of the scene to the given graphics
|
||||||
* of pixels in each direction the next time that {@link #paint} is
|
* context.
|
||||||
* called. This is called automatically by the {@link SceneViewPanel}
|
|
||||||
* which takes care of dirtying the regions exposed by the scrolling
|
|
||||||
* and copying the scrollable pixels.
|
|
||||||
*/
|
|
||||||
public void viewWillScroll (int dx, int dy);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the scene to the given graphics context.
|
|
||||||
*
|
*
|
||||||
* @param gfx the graphics context.
|
* @param gfx the graphics context.
|
||||||
* @param invalidRects the list of invalid regions to be repainted.
|
* @param invalidRect the invalid region to be repainted.
|
||||||
*/
|
*/
|
||||||
public void paint (Graphics2D gfx, Rectangle[] invalidRects);
|
public void paint (Graphics2D gfx, Rectangle invalidRect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the scene that we're rendering.
|
* Sets the scene that we're rendering.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: SceneViewPanel.java,v 1.40 2002/04/23 03:11:17 mdb Exp $
|
// $Id: SceneViewPanel.java,v 1.41 2002/06/18 22:38:12 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene;
|
package com.threerings.miso.scene;
|
||||||
|
|
||||||
@@ -13,9 +13,10 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.event.MouseMotionAdapter;
|
import java.awt.event.MouseMotionAdapter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.threerings.media.FrameManager;
|
import com.threerings.media.FrameManager;
|
||||||
import com.threerings.media.MediaPanel;
|
import com.threerings.media.VirtualMediaPanel;
|
||||||
|
|
||||||
import com.threerings.media.sprite.Sprite;
|
import com.threerings.media.sprite.Sprite;
|
||||||
import com.threerings.media.sprite.SpriteManager;
|
import com.threerings.media.sprite.SpriteManager;
|
||||||
@@ -28,7 +29,7 @@ import com.threerings.miso.scene.util.IsoUtil;
|
|||||||
* SceneView}, rendering it to the screen, and handling view-related
|
* SceneView}, rendering it to the screen, and handling view-related
|
||||||
* UI events.
|
* UI events.
|
||||||
*/
|
*/
|
||||||
public class SceneViewPanel extends MediaPanel
|
public class SceneViewPanel extends VirtualMediaPanel
|
||||||
implements IsoSceneViewModelListener
|
implements IsoSceneViewModelListener
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -38,7 +39,7 @@ public class SceneViewPanel extends MediaPanel
|
|||||||
{
|
{
|
||||||
super(framemgr);
|
super(framemgr);
|
||||||
|
|
||||||
// we're going to want to be opaque
|
// we're going to want to be opaque
|
||||||
setOpaque(true);
|
setOpaque(true);
|
||||||
|
|
||||||
// create the data model for the scene view
|
// create the data model for the scene view
|
||||||
@@ -122,50 +123,27 @@ public class SceneViewPanel extends MediaPanel
|
|||||||
super.addSprite(sprite);
|
super.addSprite(sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// documentation inherited
|
||||||
* If we're scrolling, we need to pass the word on to our scene view.
|
public void doLayout ()
|
||||||
*/
|
|
||||||
protected void viewWillScroll (int dx, int dy, long now)
|
|
||||||
{
|
{
|
||||||
_view.viewWillScroll(dx, dy);
|
super.doLayout();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// figure out our viewport offsets
|
||||||
* We want to pretend like we're in a view that fits our whole model
|
Dimension size = getSize();
|
||||||
* so we return the model bounds as our view size.
|
|
||||||
*/
|
|
||||||
protected Dimension getViewSize ()
|
|
||||||
{
|
|
||||||
return _viewmodel.bounds.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// start out centered in the display
|
||||||
* We overload this to translate mouse events into the proper
|
setViewLocation((_viewmodel.bounds.width - size.width)/2,
|
||||||
* coordinates before they are dispatched to any of the mouse
|
(_viewmodel.bounds.height - size.height)/2);
|
||||||
* listeners.
|
|
||||||
*/
|
|
||||||
protected void processMouseEvent (MouseEvent event)
|
|
||||||
{
|
|
||||||
event.translatePoint(_tx, _ty);
|
|
||||||
super.processMouseEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// Log.info("Size: " + StringUtil.toString(size) +
|
||||||
* We overload this to translate mouse events into the proper
|
// ", vsize: " + StringUtil.toString(_viewmodel.bounds) +
|
||||||
* coordinates before they are dispatched to any of the mouse
|
// ", nx: " + _nx + ", ny: " + _ny + ".");
|
||||||
* listeners.
|
|
||||||
*/
|
|
||||||
protected void processMouseMotionEvent (MouseEvent event)
|
|
||||||
{
|
|
||||||
event.translatePoint(_tx, _ty);
|
|
||||||
super.processMouseMotionEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected void paintBetween (Graphics2D gfx, Rectangle[] dirtyRects)
|
protected void paintBetween (Graphics2D gfx, Rectangle dirty)
|
||||||
{
|
{
|
||||||
// render the isometric view
|
_view.paint(gfx, dirty);
|
||||||
_view.paint(gfx, dirtyRects);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -173,12 +151,9 @@ public class SceneViewPanel extends MediaPanel
|
|||||||
* we intersperse them with objects in our scene and need to manage
|
* we intersperse them with objects in our scene and need to manage
|
||||||
* their z-order.
|
* their z-order.
|
||||||
*/
|
*/
|
||||||
protected void paintBits (Graphics2D gfx, int layer, Rectangle clip)
|
protected void paintBits (Graphics2D gfx, int layer, Rectangle dirty)
|
||||||
{
|
{
|
||||||
Shape oclip = gfx.getClip();
|
_animmgr.renderAnimations(gfx, layer, dirty);
|
||||||
gfx.clipRect(clip.x, clip.y, clip.width, clip.height);
|
|
||||||
_animmgr.renderAnimations(gfx, layer, clip);
|
|
||||||
gfx.setClip(oclip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: IsoUtil.java,v 1.32 2002/05/24 20:32:11 ray Exp $
|
// $Id: IsoUtil.java,v 1.33 2002/06/18 22:38:12 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.miso.scene.util;
|
package com.threerings.miso.scene.util;
|
||||||
|
|
||||||
@@ -52,20 +52,20 @@ public class IsoUtil
|
|||||||
* object tile.
|
* object tile.
|
||||||
*
|
*
|
||||||
* @param model the scene view model.
|
* @param model the scene view model.
|
||||||
* @param root the polygon for the root tile at which the object
|
* @param tx the x tile-coordinate of the object tile.
|
||||||
* is located.
|
* @param ty the y tile-coordinate of the object tile.
|
||||||
* @param tile the object tile.
|
* @param tile the object tile.
|
||||||
*
|
*
|
||||||
* @return the bounding polygon.
|
* @return the bounding polygon.
|
||||||
*/
|
*/
|
||||||
public static Polygon getObjectFootprint (
|
public static Polygon getObjectFootprint (
|
||||||
IsoSceneViewModel model, Polygon root, ObjectTile tile)
|
IsoSceneViewModel model, int tx, int ty, ObjectTile tile)
|
||||||
{
|
{
|
||||||
Polygon boundsPoly = new SmartPolygon();
|
Polygon boundsPoly = new SmartPolygon();
|
||||||
Rectangle bounds = root.getBounds();
|
Point tpos = tileToScreen(model, tx, ty, new Point());
|
||||||
|
|
||||||
int bwid = tile.getBaseWidth(), bhei = tile.getBaseHeight();
|
int bwid = tile.getBaseWidth(), bhei = tile.getBaseHeight();
|
||||||
int oox = bounds.x + model.tilehwid, ooy = bounds.y + model.tilehei;
|
int oox = tpos.x + model.tilehwid, ooy = tpos.y + model.tilehei;
|
||||||
int rx = oox, ry = ooy;
|
int rx = oox, ry = ooy;
|
||||||
|
|
||||||
// bottom-center point
|
// bottom-center point
|
||||||
@@ -98,16 +98,16 @@ public class IsoUtil
|
|||||||
* object dimensions. This is currently not used.
|
* object dimensions. This is currently not used.
|
||||||
*
|
*
|
||||||
* @param model the scene view model.
|
* @param model the scene view model.
|
||||||
* @param root the polygon for the root tile at which the object is
|
* @param tx the x tile-coordinate of the object tile.
|
||||||
* located.
|
* @param ty the y tile-coordinate of the object tile.
|
||||||
* @param tile the object tile.
|
* @param tile the object tile.
|
||||||
*
|
*
|
||||||
* @return the bounding polygon.
|
* @return the bounding polygon.
|
||||||
*/
|
*/
|
||||||
public static Polygon getTightObjectBounds (
|
public static Polygon getTightObjectBounds (
|
||||||
IsoSceneViewModel model, Polygon root, ObjectTile tile)
|
IsoSceneViewModel model, int tx, int ty, ObjectTile tile)
|
||||||
{
|
{
|
||||||
Rectangle bounds = root.getBounds();
|
Point tpos = tileToScreen(model, tx, ty, new Point());
|
||||||
|
|
||||||
// if the tile has an origin, use that, otherwise compute the
|
// if the tile has an origin, use that, otherwise compute the
|
||||||
// origin based on the tile footprint
|
// origin based on the tile footprint
|
||||||
@@ -118,7 +118,7 @@ public class IsoUtil
|
|||||||
}
|
}
|
||||||
|
|
||||||
float slope = (float)model.tilehei / (float)model.tilewid;
|
float slope = (float)model.tilehei / (float)model.tilewid;
|
||||||
int oox = bounds.x + model.tilehwid, ooy = bounds.y + model.tilehei;
|
int oox = tpos.x + model.tilehwid, ooy = tpos.y + model.tilehei;
|
||||||
int sx = oox - tox, sy = ooy - toy;
|
int sx = oox - tox, sy = ooy - toy;
|
||||||
|
|
||||||
Polygon boundsPoly = new SmartPolygon();
|
Polygon boundsPoly = new SmartPolygon();
|
||||||
@@ -136,8 +136,7 @@ public class IsoUtil
|
|||||||
boundsPoly.addPoint(rx, ry);
|
boundsPoly.addPoint(rx, ry);
|
||||||
|
|
||||||
// bottom-middle point
|
// bottom-middle point
|
||||||
boundsPoly.addPoint(bounds.x + model.tilehwid,
|
boundsPoly.addPoint(tpos.x + model.tilehwid, tpos.y + model.tilehei);
|
||||||
bounds.y + model.tilehei);
|
|
||||||
|
|
||||||
// bottom-left point
|
// bottom-left point
|
||||||
rx = sx;
|
rx = sx;
|
||||||
@@ -156,16 +155,16 @@ public class IsoUtil
|
|||||||
* image.
|
* image.
|
||||||
*
|
*
|
||||||
* @param model the scene view model.
|
* @param model the scene view model.
|
||||||
* @param root the polygon for the root tile at which the object is
|
* @param tx the x tile-coordinate of the object tile.
|
||||||
* located.
|
* @param ty the y tile-coordinate of the object tile.
|
||||||
* @param tile the object tile.
|
* @param tile the object tile.
|
||||||
*
|
*
|
||||||
* @return the bounding rectangle.
|
* @return the bounding rectangle.
|
||||||
*/
|
*/
|
||||||
public static Rectangle getObjectBounds (
|
public static Rectangle getObjectBounds (
|
||||||
IsoSceneViewModel model, Polygon root, ObjectTile tile)
|
IsoSceneViewModel model, int tx, int ty, ObjectTile tile)
|
||||||
{
|
{
|
||||||
Rectangle bounds = root.getBounds();
|
Point tpos = tileToScreen(model, tx, ty, new Point());
|
||||||
|
|
||||||
// if the tile has an origin, use that, otherwise compute the
|
// if the tile has an origin, use that, otherwise compute the
|
||||||
// origin based on the tile footprint
|
// origin based on the tile footprint
|
||||||
@@ -175,7 +174,7 @@ public class IsoUtil
|
|||||||
toy = tile.getHeight();
|
toy = tile.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
int oox = bounds.x + model.tilehwid, ooy = bounds.y + model.tilehei;
|
int oox = tpos.x + model.tilehwid, ooy = tpos.y + model.tilehei;
|
||||||
int sx = oox - tox, sy = ooy - toy;
|
int sx = oox - tox, sy = ooy - toy;
|
||||||
|
|
||||||
return new Rectangle(sx, sy, tile.getWidth(), tile.getHeight());
|
return new Rectangle(sx, sy, tile.getWidth(), tile.getHeight());
|
||||||
@@ -337,26 +336,42 @@ public class IsoUtil
|
|||||||
* @param sx the screen x-position pixel coordinate.
|
* @param sx the screen x-position pixel coordinate.
|
||||||
* @param sy the screen y-position pixel coordinate.
|
* @param sy the screen y-position pixel coordinate.
|
||||||
* @param tpos the point object to place coordinates in.
|
* @param tpos the point object to place coordinates in.
|
||||||
|
*
|
||||||
|
* @return the point instance supplied via the <code>tpos</code>
|
||||||
|
* parameter.
|
||||||
*/
|
*/
|
||||||
public static void screenToTile (
|
public static Point screenToTile (
|
||||||
IsoSceneViewModel model, int sx, int sy, Point tpos)
|
IsoSceneViewModel model, int sx, int sy, Point tpos)
|
||||||
{
|
{
|
||||||
// calculate line parallel to the y-axis (from mouse pos to x-axis)
|
// determine the upper-left of the quadrant that contains our
|
||||||
int bY = (int)(sy - (model.slopeY * sx));
|
// 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);
|
||||||
|
|
||||||
// determine intersection of x- and y-axis lines
|
// these are the screen coordinates of the tile's top
|
||||||
int crossx = (int)((bY - (model.bX + model.origin.y)) /
|
int ox = (zx * model.tilewid + model.origin.x),
|
||||||
(model.slopeX - model.slopeY));
|
oy = (zy * model.tilehei + model.origin.y);
|
||||||
int crossy = (int)((model.slopeY * crossx) + bY);
|
|
||||||
|
|
||||||
// determine distance of mouse pos along the x axis
|
// these are the tile coordinates
|
||||||
int xdist = (int)MathUtil.distance(
|
tpos.x = zy + zx; tpos.y = zy - zx;
|
||||||
model.origin.x, model.origin.y, crossx, crossy);
|
|
||||||
tpos.x = (int)(xdist / model.tilelen);
|
|
||||||
|
|
||||||
// determine distance of mouse pos along the y-axis
|
// now determine which of the four tiles our point occupies
|
||||||
int ydist = (int)MathUtil.distance(sx, sy, crossx, crossy);
|
int dx = sx - ox, dy = sy - oy;
|
||||||
tpos.y = (int)(ydist / model.tilelen);
|
|
||||||
|
if (Math.round(model.slopeY * dx + model.tilehei) < dy) {
|
||||||
|
tpos.x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.round(model.slopeX * dx) > dy) {
|
||||||
|
tpos.y -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log.info("Converted [sx=" + sx + ", sy=" + sy +
|
||||||
|
// ", zx=" + zx + ", zy=" + zy +
|
||||||
|
// ", ox=" + ox + ", oy=" + oy +
|
||||||
|
// ", dx=" + dx + ", dy=" + dy +
|
||||||
|
// ", tpos.x=" + tpos.x + ", tpos.y=" + tpos.y + "].");
|
||||||
|
return tpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -367,12 +382,16 @@ public class IsoUtil
|
|||||||
* @param x the tile x-position coordinate.
|
* @param x the tile x-position coordinate.
|
||||||
* @param y the tile y-position coordinate.
|
* @param y the tile y-position coordinate.
|
||||||
* @param spos the point object to place coordinates in.
|
* @param spos the point object to place coordinates in.
|
||||||
|
*
|
||||||
|
* @return the point instance supplied via the <code>spos</code>
|
||||||
|
* parameter.
|
||||||
*/
|
*/
|
||||||
public static void tileToScreen (
|
public static Point tileToScreen (
|
||||||
IsoSceneViewModel model, int x, int y, Point spos)
|
IsoSceneViewModel model, int x, int y, Point spos)
|
||||||
{
|
{
|
||||||
spos.x = model.origin.x + ((x - y - 1) * model.tilehwid);
|
spos.x = model.origin.x + ((x - y - 1) * model.tilehwid);
|
||||||
spos.y = model.origin.y + ((x + y) * model.tilehhei);
|
spos.y = model.origin.y + ((x + y) * model.tilehhei);
|
||||||
|
return spos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -435,8 +454,10 @@ public class IsoUtil
|
|||||||
* @param sx the screen x-position pixel coordinate.
|
* @param sx the screen x-position pixel coordinate.
|
||||||
* @param sy the screen y-position pixel coordinate.
|
* @param sy the screen y-position pixel coordinate.
|
||||||
* @param fpos the point object to place coordinates in.
|
* @param fpos the point object to place coordinates in.
|
||||||
|
*
|
||||||
|
* @return the point passed in to receive the coordinates.
|
||||||
*/
|
*/
|
||||||
public static void screenToFull (
|
public static Point screenToFull (
|
||||||
IsoSceneViewModel model, int sx, int sy, Point fpos)
|
IsoSceneViewModel model, int sx, int sy, Point fpos)
|
||||||
{
|
{
|
||||||
// get the tile coordinates
|
// get the tile coordinates
|
||||||
@@ -444,8 +465,7 @@ public class IsoUtil
|
|||||||
screenToTile(model, sx, sy, tpos);
|
screenToTile(model, sx, sy, tpos);
|
||||||
|
|
||||||
// get the screen coordinates for the containing tile
|
// get the screen coordinates for the containing tile
|
||||||
Point spos = new Point();
|
Point spos = tileToScreen(model, tpos.x, tpos.y, new Point());
|
||||||
tileToScreen(model, tpos.x, tpos.y, spos);
|
|
||||||
|
|
||||||
// get the fine coordinates within the containing tile
|
// get the fine coordinates within the containing tile
|
||||||
pixelToFine(model, sx - spos.x, sy - spos.y, fpos);
|
pixelToFine(model, sx - spos.x, sy - spos.y, fpos);
|
||||||
@@ -453,6 +473,8 @@ public class IsoUtil
|
|||||||
// toss in the tile coordinates for good measure
|
// toss in the tile coordinates for good measure
|
||||||
fpos.x += (tpos.x * FULL_TILE_FACTOR);
|
fpos.x += (tpos.x * FULL_TILE_FACTOR);
|
||||||
fpos.y += (tpos.y * FULL_TILE_FACTOR);
|
fpos.y += (tpos.y * FULL_TILE_FACTOR);
|
||||||
|
|
||||||
|
return fpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,14 +485,15 @@ public class IsoUtil
|
|||||||
* @param x the x-position full coordinate.
|
* @param x the x-position full coordinate.
|
||||||
* @param y the y-position full coordinate.
|
* @param y the y-position full coordinate.
|
||||||
* @param spos the point object to place coordinates in.
|
* @param spos the point object to place coordinates in.
|
||||||
|
*
|
||||||
|
* @return the point passed in to receive the coordinates.
|
||||||
*/
|
*/
|
||||||
public static void fullToScreen (
|
public static Point fullToScreen (
|
||||||
IsoSceneViewModel model, int x, int y, Point spos)
|
IsoSceneViewModel model, int x, int y, Point spos)
|
||||||
{
|
{
|
||||||
// get the tile screen position
|
// get the tile screen position
|
||||||
Point tspos = new Point();
|
|
||||||
int tx = x / FULL_TILE_FACTOR, ty = y / FULL_TILE_FACTOR;
|
int tx = x / FULL_TILE_FACTOR, ty = y / FULL_TILE_FACTOR;
|
||||||
tileToScreen(model, tx, ty, tspos);
|
Point tspos = tileToScreen(model, tx, ty, new Point());
|
||||||
|
|
||||||
// get the pixel position of the fine coords within the tile
|
// get the pixel position of the fine coords within the tile
|
||||||
Point ppos = new Point();
|
Point ppos = new Point();
|
||||||
@@ -480,6 +503,8 @@ public class IsoUtil
|
|||||||
// final position is tile position offset by fine position
|
// final position is tile position offset by fine position
|
||||||
spos.x = tspos.x + ppos.x;
|
spos.x = tspos.x + ppos.x;
|
||||||
spos.y = tspos.y + ppos.y;
|
spos.y = tspos.y + ppos.y;
|
||||||
|
|
||||||
|
return spos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -492,8 +517,7 @@ public class IsoUtil
|
|||||||
IsoSceneViewModel model, int x, int y)
|
IsoSceneViewModel model, int x, int y)
|
||||||
{
|
{
|
||||||
// get the top-left screen coordinate for the tile
|
// get the top-left screen coordinate for the tile
|
||||||
Point spos = new Point();
|
Point spos = IsoUtil.tileToScreen(model, x, y, new Point());
|
||||||
IsoUtil.tileToScreen(model, x, y, spos);
|
|
||||||
|
|
||||||
// create a polygon framing the tile
|
// create a polygon framing the tile
|
||||||
Polygon poly = new SmartPolygon();
|
Polygon poly = new SmartPolygon();
|
||||||
@@ -516,10 +540,10 @@ public class IsoUtil
|
|||||||
Point[] p = new Point[4];
|
Point[] p = new Point[4];
|
||||||
|
|
||||||
// load in all possible screen coords
|
// load in all possible screen coords
|
||||||
IsoUtil.tileToScreen(model, sp1.x, sp1.y, p[0] = new Point());
|
p[0] = IsoUtil.tileToScreen(model, sp1.x, sp1.y, new Point());
|
||||||
IsoUtil.tileToScreen(model, sp2.x, sp2.y, p[1] = new Point());
|
p[1] = IsoUtil.tileToScreen(model, sp2.x, sp2.y, new Point());
|
||||||
IsoUtil.tileToScreen(model, sp1.x, sp2.y, p[2] = new Point());
|
p[2] = IsoUtil.tileToScreen(model, sp1.x, sp2.y, new Point());
|
||||||
IsoUtil.tileToScreen(model, sp2.x, sp1.y, p[3] = new Point());
|
p[3] = IsoUtil.tileToScreen(model, sp2.x, sp1.y, new Point());
|
||||||
|
|
||||||
// locate the indexes of min/max for x and y
|
// locate the indexes of min/max for x and y
|
||||||
minx = maxx = miny = maxy = 0;
|
minx = maxx = miny = maxy = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user