Added support for "low" walls/attachments.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3697 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Andrzej Kapolka
2005-09-07 23:19:17 +00:00
parent dd44bb4f69
commit 00ae2e251c
2 changed files with 80 additions and 26 deletions
@@ -35,11 +35,7 @@ import com.threerings.media.image.Colorization;
*/ */
public class ObjectTileSet extends SwissArmyTileSet public class ObjectTileSet extends SwissArmyTileSet
implements RecolorableTileSet implements RecolorableTileSet
{ {
/** A constraint prefix indicating that the object must be attached to a
* wall facing the suffixed direction (N, E, S, or W). */
public static final String ATTACH = "ATTACH_";
/** A constraint prefix indicating that the object must have empty space in /** A constraint prefix indicating that the object must have empty space in
* the suffixed direction (N, E, S, or W). */ * the suffixed direction (N, E, S, or W). */
public static final String SPACE = "SPACE_"; public static final String SPACE = "SPACE_";
@@ -50,14 +46,23 @@ public class ObjectTileSet extends SwissArmyTileSet
/** A constraint indicating that the object must be placed on a surface. */ /** A constraint indicating that the object must be placed on a surface. */
public static final String ON_SURFACE = "ON_SURFACE"; public static final String ON_SURFACE = "ON_SURFACE";
/** A constraint prefix indicating that the object is a wall facing the /** A constraint prefix indicating that the object is a normal-height wall
* suffixed direction (N, E, S, or W). */ * facing the suffixed direction (N, E, S, or W). */
public static final String WALL = "WALL_"; public static final String WALL = "WALL_";
/** A constraint prefix indicating that the object must be placed on a wall /** A constraint prefix indicating that the object must be placed on a
* facing the suffixed direction (N, E, S, or W). */ * normal-height wall facing the suffixed direction (N, E, S, or W). */
public static final String ON_WALL = "ON_WALL_"; public static final String ON_WALL = "ON_WALL_";
/** A constraint prefix indicating that the object must be attached to a
* wall facing the suffixed direction (N, E, S, or W). */
public static final String ATTACH = "ATTACH_";
/** The low suffix for walls and attachments. Low attachments can be placed
* on low or normal walls; normal attachments can only be placed on normal
* walls. */
public static final String LOW = "_LOW";
/** /**
* Sets the widths (in unit tile count) of the objects in this * Sets the widths (in unit tile count) of the objects in this
* tileset. This must be accompanied by a call to {@link * tileset. This must be accompanied by a call to {@link
@@ -155,6 +155,8 @@ public class PlacementConstraints
protected String allowModifyObjects (ObjectData[] added, protected String allowModifyObjects (ObjectData[] added,
ObjectData[] removed) ObjectData[] removed)
{ {
DirectionHeight dirheight = new DirectionHeight();
for (int i = 0; i < added.length; i++) { for (int i = 0; i < added.length; i++) {
if (added[i].tile.hasConstraint(ObjectTileSet.ON_SURFACE) && if (added[i].tile.hasConstraint(ObjectTileSet.ON_SURFACE) &&
!isOnSurface(added[i], added, removed)) { !isOnSurface(added[i], added, removed)) {
@@ -168,8 +170,9 @@ public class PlacementConstraints
"m.not_on_wall"); "m.not_on_wall");
} }
dir = getConstraintDirection(added[i], ObjectTileSet.ATTACH); if (getConstraintDirectionHeight(added[i], ObjectTileSet.ATTACH,
if (dir != NONE && !isAttached(added[i], added, removed, dir)) { dirheight) && !isAttached(added[i], added, removed,
dirheight.dir, dirheight.low)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE, return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.not_attached"); "m.not_attached");
} }
@@ -252,12 +255,15 @@ public class PlacementConstraints
protected boolean hasAttached (ObjectData data, ObjectData[] added, protected boolean hasAttached (ObjectData data, ObjectData[] added,
ObjectData[] removed, int dir) ObjectData[] removed, int dir)
{ {
DirectionHeight dirheight = new DirectionHeight();
ArrayList objects = getObjectData(getAdjacentEdge(data.bounds, ArrayList objects = getObjectData(getAdjacentEdge(data.bounds,
DirectionUtil.getOpposite(dir)), added, removed); DirectionUtil.getOpposite(dir)), added, removed);
for (int i = 0, size = objects.size(); i < size; i++) { for (int i = 0, size = objects.size(); i < size; i++) {
ObjectData odata = (ObjectData)objects.get(i); ObjectData odata = (ObjectData)objects.get(i);
if (getConstraintDirection(odata, ObjectTileSet.ATTACH) == dir && if (getConstraintDirectionHeight(odata, ObjectTileSet.ATTACH,
!isAttached(odata, added, removed, dir)) { dirheight) && !isAttached(odata, added, removed,
dirheight.dir, dirheight.low)) {
return true; return true;
} }
} }
@@ -303,7 +309,8 @@ public class PlacementConstraints
protected boolean isOnSurface (ObjectData data, ObjectData[] added, protected boolean isOnSurface (ObjectData data, ObjectData[] added,
ObjectData[] removed) ObjectData[] removed)
{ {
return isCovered(data.bounds, added, removed, ObjectTileSet.SURFACE); return isCovered(data.bounds, added, removed, ObjectTileSet.SURFACE,
null);
} }
/** /**
@@ -314,27 +321,29 @@ public class PlacementConstraints
ObjectData[] removed, int dir) ObjectData[] removed, int dir)
{ {
return isCovered(data.bounds, added, removed, return isCovered(data.bounds, added, removed,
getDirectionalConstraint(ObjectTileSet.WALL, dir)); getDirectionalConstraint(ObjectTileSet.WALL, dir), null);
} }
/** /**
* Determines whether the specified object is attached to another object in * Determines whether the specified object is attached to another object in
* the specified direction. * the specified direction and at the specified height.
*/ */
protected boolean isAttached (ObjectData data, ObjectData[] added, protected boolean isAttached (ObjectData data, ObjectData[] added,
ObjectData[] removed, int dir) ObjectData[] removed, int dir, boolean low)
{ {
return isCovered(getAdjacentEdge(data.bounds, dir), added, removed, return isCovered(getAdjacentEdge(data.bounds, dir), added, removed,
getDirectionalConstraint(ObjectTileSet.WALL, dir)); getDirectionalConstraint(ObjectTileSet.WALL, dir), low ?
getDirectionalConstraint(ObjectTileSet.WALL, dir, true) : null);
} }
/** /**
* Given a rectangle, determines whether all of the tiles within * Given a rectangle, determines whether all of the tiles within
* the rectangle intersect an object. If the constraint parameter is * the rectangle intersect an object. If the constraint parameter is
* non-null, the intersected objects must have that constraint. * non-null, the intersected objects must have that constraint (or the
* alternate constraint, if specified).
*/ */
protected boolean isCovered (Rectangle rect, ObjectData[] added, protected boolean isCovered (Rectangle rect, ObjectData[] added,
ObjectData[] removed, String constraint) ObjectData[] removed, String constraint, String altstraint)
{ {
ArrayList objects = getObjectData(rect, added, removed); ArrayList objects = getObjectData(rect, added, removed);
for (int y = rect.y, ymax = rect.y + rect.height; y < ymax; y++) { for (int y = rect.y, ymax = rect.y + rect.height; y < ymax; y++) {
@@ -343,7 +352,9 @@ public class PlacementConstraints
for (int i = 0, size = objects.size(); i < size; i++) { for (int i = 0, size = objects.size(); i < size; i++) {
ObjectData data = (ObjectData)objects.get(i); ObjectData data = (ObjectData)objects.get(i);
if (data.bounds.contains(x, y) && (constraint == null || if (data.bounds.contains(x, y) && (constraint == null ||
data.tile.hasConstraint(constraint))) { data.tile.hasConstraint(constraint) ||
(altstraint != null &&
data.tile.hasConstraint(altstraint)))) {
covered = true; covered = true;
break; break;
} }
@@ -389,19 +400,39 @@ public class PlacementConstraints
* <code>NONE</code> if there is no such directional constraint. * <code>NONE</code> if there is no such directional constraint.
*/ */
protected int getConstraintDirection (ObjectData data, String prefix) protected int getConstraintDirection (ObjectData data, String prefix)
{
DirectionHeight dirheight = new DirectionHeight();
return getConstraintDirectionHeight(data, prefix, dirheight) ?
dirheight.dir : NONE;
}
/**
* Populates the supplied {@link DirectionHeight} object with the direction
* and height of the constraint identified by the given prefix.
*
* @return true if the object was successfully populated, false if there is
* no such constraint
*/
protected boolean getConstraintDirectionHeight (ObjectData data,
String prefix, DirectionHeight dirheight)
{ {
String[] constraints = data.tile.getConstraints(); String[] constraints = data.tile.getConstraints();
if (constraints == null) { if (constraints == null) {
return NONE; return false;
} }
for (int i = 0; i < constraints.length; i++) { for (int i = 0; i < constraints.length; i++) {
if (constraints[i].startsWith(prefix)) { if (constraints[i].startsWith(prefix)) {
return DirectionUtil.fromShortString( int fromidx = prefix.length(),
constraints[i].substring(prefix.length())); toidx = constraints[i].indexOf('_', fromidx);
dirheight.dir = DirectionUtil.fromShortString(toidx == -1 ?
constraints[i].substring(fromidx) :
constraints[i].substring(fromidx, toidx));
dirheight.low = constraints[i].endsWith(ObjectTileSet.LOW);
return true;
} }
} }
return NONE; return false;
} }
/** /**
@@ -410,7 +441,18 @@ public class PlacementConstraints
*/ */
protected String getDirectionalConstraint (String prefix, int dir) protected String getDirectionalConstraint (String prefix, int dir)
{ {
return prefix + DirectionUtil.toShortString(dir); return getDirectionalConstraint(prefix, dir, false);
}
/**
* Given a constraint prefix, direction, and height, returns the
* directional constraint.
*/
protected String getDirectionalConstraint (String prefix, int dir,
boolean low)
{
return prefix + DirectionUtil.toShortString(dir) +
(low ? ObjectTileSet.LOW : "");
} }
/** /**
@@ -476,6 +518,13 @@ public class PlacementConstraints
} }
} }
/** Contains the direction and height of a constraint. */
protected class DirectionHeight
{
public int dir;
public boolean low;
}
/** The tile manager to use for object dimensions and constraints. */ /** The tile manager to use for object dimensions and constraints. */
protected TileManager _tilemgr; protected TileManager _tilemgr;