Handle directional wall constraints, attach only to walls, check space constraints selectively with respect to direction.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3609 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Andrzej Kapolka
2005-06-21 01:26:06 +00:00
parent 1e311871c3
commit 264d0e65d5
2 changed files with 87 additions and 81 deletions
@@ -36,15 +36,13 @@ import com.threerings.media.image.Colorization;
public class ObjectTileSet extends SwissArmyTileSet
implements RecolorableTileSet
{
/** A constraint indicating that the object must be attached to another
* object in the indicated direction. */
public static final String ATTACH_N = "ATTACH_N", ATTACH_E = "ATTACH_E",
ATTACH_S = "ATTACH_S", ATTACH_W = "ATTACH_W";
/** 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 indicating that the object must have empty space in the
* indicated direction. */
public static final String SPACE_N = "SPACE_N", SPACE_E = "SPACE_E",
SPACE_S = "SPACE_S", SPACE_W = "SPACE_W";
/** A constraint prefix indicating that the object must have empty space in
* the suffixed direction (N, E, S, or W). */
public static final String SPACE = "SPACE_";
/** A constraint indicating that the object is a surface (e.g., table). */
public static final String SURFACE = "SURFACE";
@@ -52,11 +50,13 @@ public class ObjectTileSet extends SwissArmyTileSet
/** A constraint indicating that the object must be placed on a surface. */
public static final String ON_SURFACE = "ON_SURFACE";
/** A constraint indicating that the object is a wall. */
public static final String WALL = "WALL";
/** A constraint prefix indicating that the object is a wall facing the
* suffixed direction (N, E, S, or W). */
public static final String WALL = "WALL_";
/** A constraint indicating that the object must be placed on a wall. */
public static final String ON_WALL = "ON_WALL";
/** A constraint prefix indicating that the object must be placed on a wall
* facing the suffixed direction (N, E, S, or W). */
public static final String ON_WALL = "ON_WALL_";
/**
* Sets the widths (in unit tile count) of the objects in this
@@ -13,6 +13,7 @@ import com.samskivert.util.ListUtil;
import com.samskivert.util.StringUtil;
import com.threerings.util.DirectionCodes;
import com.threerings.util.DirectionUtil;
import com.threerings.util.MessageBundle;
import com.threerings.media.tile.ObjectTile;
@@ -148,26 +149,27 @@ public class PlacementConstraints
!isOnSurface(added[i], added, removed)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.not_on_surface");
} else if (added[i].tile.hasConstraint(ObjectTileSet.ON_WALL) &&
!isOnWall(added[i], added, removed)) {
}
int dir = getConstraintDirection(added[i], ObjectTileSet.ON_WALL);
if (dir != NONE && !isOnWall(added[i], added, removed, dir)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.not_on_wall");
}
int dir = getConstraintDirection(added[i], "ATTACH");
dir = getConstraintDirection(added[i], ObjectTileSet.ATTACH);
if (dir != NONE && !isAttached(added[i], added, removed, dir)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.not_attached");
}
dir = getConstraintDirection(added[i], "SPACE");
dir = getConstraintDirection(added[i], ObjectTileSet.SPACE);
if (dir != NONE && !hasSpace(added[i], added, removed, dir)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.no_space");
}
if (!checkAdjacentSpace(added[i], added, removed)) {
if (hasSpaceConstrainedAdjacent(added[i], added, removed)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.no_space_adj");
}
@@ -178,15 +180,18 @@ public class PlacementConstraints
hasOnSurface(removed[i], added, removed)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.has_on_surface");
}
} else if (removed[i].tile.hasConstraint(ObjectTileSet.WALL) &&
hasOnWall(removed[i], added, removed)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.has_on_wall");
int dir = getConstraintDirection(removed[i], ObjectTileSet.WALL);
if (dir != NONE) {
if (hasOnWall(removed[i], added, removed, dir)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.has_on_wall");
} else if (!checkAdjacentAttached(removed[i], added, removed)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.has_attached");
} else if (hasAttached(removed[i], added, removed, dir)) {
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
"m.has_attached");
}
}
}
@@ -203,33 +208,14 @@ public class PlacementConstraints
}
/**
* Determines whether the specified object is on a wall.
* Determines whether the specified object is on a wall facing the
* specified direction.
*/
protected boolean isOnWall (ObjectData data, ObjectData[] added,
ObjectData[] removed)
ObjectData[] removed, int dir)
{
return isCovered(data.bounds, added, removed, ObjectTileSet.WALL);
}
/**
* Verifies that the objects adjacent to the given object will still have
* their attachment constraints met if the object is removed.
*/
protected boolean checkAdjacentAttached (ObjectData data,
ObjectData[] added, ObjectData[] removed)
{
Rectangle rect = new Rectangle(data.bounds);
rect.grow(1, 1);
ArrayList objects = getObjectData(rect, added, removed);
for (int i = 0, size = objects.size(); i < size; i++) {
ObjectData odata = (ObjectData)objects.get(i);
int dir = getConstraintDirection(odata, "ATTACH");
if (dir != NONE && !isAttached(odata, added, removed, dir)) {
return false;
}
}
return true;
return isCovered(data.bounds, added, removed,
getDirectionalConstraint(ObjectTileSet.WALL, dir));
}
/**
@@ -240,7 +226,7 @@ public class PlacementConstraints
ObjectData[] removed, int dir)
{
return isCovered(getAdjacentEdge(data.bounds, dir), added, removed,
ObjectTileSet.WALL);
getDirectionalConstraint(ObjectTileSet.WALL, dir));
}
/**
@@ -272,24 +258,27 @@ public class PlacementConstraints
}
/**
* Verifies that that objects adjacent to the given object will still have
* Verifies that the objects adjacent to the given object will still have
* their space constraints met if the object is added.
*/
protected boolean checkAdjacentSpace (ObjectData data, ObjectData[] added,
ObjectData[] removed)
protected boolean hasSpaceConstrainedAdjacent (ObjectData data,
ObjectData[] added, ObjectData[] removed)
{
Rectangle rect = new Rectangle(data.bounds);
rect.grow(1, 1);
ArrayList objects = getObjectData(rect, added, removed);
for (int i = 0, size = objects.size(); i < size; i++) {
ObjectData odata = (ObjectData)objects.get(i);
int dir = getConstraintDirection(odata, "SPACE");
if (dir != NONE && !hasSpace(odata, added, removed, dir)) {
return false;
}
}
return true;
return hasSpaceConstrainedAdjacent(data, added, removed, NORTH) ||
hasSpaceConstrainedAdjacent(data, added, removed, EAST) ||
hasSpaceConstrainedAdjacent(data, added, removed, SOUTH) ||
hasSpaceConstrainedAdjacent(data, added, removed, WEST);
}
/**
* Checks space constraints for objects in the specified direction.
*/
protected boolean hasSpaceConstrainedAdjacent (ObjectData data,
ObjectData[] added, ObjectData[] removed, int dir)
{
int oppDir = DirectionUtil.getOpposite(dir);
return hasConstrained(getAdjacentEdge(data.bounds, dir), added,
removed, getDirectionalConstraint(ObjectTileSet.SPACE, oppDir));
}
/**
@@ -344,10 +333,21 @@ public class PlacementConstraints
* Determines whether the specified wall has anything on it.
*/
protected boolean hasOnWall (ObjectData data, ObjectData[] added,
ObjectData[] removed)
ObjectData[] removed, int dir)
{
return hasConstrained(data.bounds, added, removed,
ObjectTileSet.ON_WALL);
getDirectionalConstraint(ObjectTileSet.ON_WALL, dir));
}
/**
* Determines whether the specified wall has anything attached to it.
*/
protected boolean hasAttached (ObjectData data, ObjectData[] added,
ObjectData[] removed, int dir)
{
int oppDir = DirectionUtil.getOpposite(dir);
return hasConstrained(getAdjacentEdge(data.bounds, oppDir), added,
removed, getDirectionalConstraint(ObjectTileSet.ATTACH, dir));
}
/**
@@ -369,26 +369,32 @@ public class PlacementConstraints
/**
* Returns the direction in which the specified object is constrained by
* appending "_[NESW]" to the given constraint prefix. Returns
* appending "[NESW]" to the given constraint prefix. Returns
* <code>NONE</code> if there is no such directional constraint.
*/
protected int getConstraintDirection (ObjectData data, String prefix)
{
if (data.tile.hasConstraint(prefix + "_N")) {
return NORTH;
} else if (data.tile.hasConstraint(prefix + "_E")) {
return EAST;
} else if (data.tile.hasConstraint(prefix + "_S")) {
return SOUTH;
} else if (data.tile.hasConstraint(prefix + "_W")) {
return WEST;
} else {
String[] constraints = data.tile.getConstraints();
if (constraints == null) {
return NONE;
}
for (int i = 0; i < constraints.length; i++) {
if (constraints[i].startsWith(prefix)) {
return DirectionUtil.fromShortString(
constraints[i].substring(prefix.length()));
}
}
return NONE;
}
/**
* Given a constraint prefix and a direction, returns the directional
* constraint.
*/
protected String getDirectionalConstraint (String prefix, int dir)
{
return prefix + DirectionUtil.toShortString(dir);
}
/**