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:
@@ -36,15 +36,13 @@ import com.threerings.media.image.Colorization;
|
|||||||
public class ObjectTileSet extends SwissArmyTileSet
|
public class ObjectTileSet extends SwissArmyTileSet
|
||||||
implements RecolorableTileSet
|
implements RecolorableTileSet
|
||||||
{
|
{
|
||||||
/** A constraint indicating that the object must be attached to another
|
/** A constraint prefix indicating that the object must be attached to a
|
||||||
* object in the indicated direction. */
|
* wall facing the suffixed direction (N, E, S, or W). */
|
||||||
public static final String ATTACH_N = "ATTACH_N", ATTACH_E = "ATTACH_E",
|
public static final String ATTACH = "ATTACH_";
|
||||||
ATTACH_S = "ATTACH_S", ATTACH_W = "ATTACH_W";
|
|
||||||
|
|
||||||
/** A constraint indicating that the object must have empty space in the
|
/** A constraint prefix indicating that the object must have empty space in
|
||||||
* indicated direction. */
|
* the suffixed direction (N, E, S, or W). */
|
||||||
public static final String SPACE_N = "SPACE_N", SPACE_E = "SPACE_E",
|
public static final String SPACE = "SPACE_";
|
||||||
SPACE_S = "SPACE_S", SPACE_W = "SPACE_W";
|
|
||||||
|
|
||||||
/** A constraint indicating that the object is a surface (e.g., table). */
|
/** A constraint indicating that the object is a surface (e.g., table). */
|
||||||
public static final String SURFACE = "SURFACE";
|
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. */
|
/** 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 indicating that the object is a wall. */
|
/** A constraint prefix indicating that the object is a wall facing the
|
||||||
public static final String WALL = "WALL";
|
* 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. */
|
/** A constraint prefix indicating that the object must be placed on a wall
|
||||||
public static final String ON_WALL = "ON_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
|
* 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.samskivert.util.StringUtil;
|
||||||
|
|
||||||
import com.threerings.util.DirectionCodes;
|
import com.threerings.util.DirectionCodes;
|
||||||
|
import com.threerings.util.DirectionUtil;
|
||||||
import com.threerings.util.MessageBundle;
|
import com.threerings.util.MessageBundle;
|
||||||
|
|
||||||
import com.threerings.media.tile.ObjectTile;
|
import com.threerings.media.tile.ObjectTile;
|
||||||
@@ -148,26 +149,27 @@ public class PlacementConstraints
|
|||||||
!isOnSurface(added[i], added, removed)) {
|
!isOnSurface(added[i], added, removed)) {
|
||||||
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
"m.not_on_surface");
|
"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,
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
"m.not_on_wall");
|
"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)) {
|
if (dir != NONE && !isAttached(added[i], added, removed, dir)) {
|
||||||
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
"m.not_attached");
|
"m.not_attached");
|
||||||
}
|
}
|
||||||
|
|
||||||
dir = getConstraintDirection(added[i], "SPACE");
|
dir = getConstraintDirection(added[i], ObjectTileSet.SPACE);
|
||||||
if (dir != NONE && !hasSpace(added[i], added, removed, dir)) {
|
if (dir != NONE && !hasSpace(added[i], added, removed, dir)) {
|
||||||
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
"m.no_space");
|
"m.no_space");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkAdjacentSpace(added[i], added, removed)) {
|
if (hasSpaceConstrainedAdjacent(added[i], added, removed)) {
|
||||||
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
"m.no_space_adj");
|
"m.no_space_adj");
|
||||||
}
|
}
|
||||||
@@ -178,15 +180,18 @@ public class PlacementConstraints
|
|||||||
hasOnSurface(removed[i], added, removed)) {
|
hasOnSurface(removed[i], added, removed)) {
|
||||||
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
"m.has_on_surface");
|
"m.has_on_surface");
|
||||||
|
}
|
||||||
|
|
||||||
} else if (removed[i].tile.hasConstraint(ObjectTileSet.WALL) &&
|
int dir = getConstraintDirection(removed[i], ObjectTileSet.WALL);
|
||||||
hasOnWall(removed[i], added, removed)) {
|
if (dir != NONE) {
|
||||||
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
if (hasOnWall(removed[i], added, removed, dir)) {
|
||||||
"m.has_on_wall");
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
|
"m.has_on_wall");
|
||||||
|
|
||||||
} else if (!checkAdjacentAttached(removed[i], added, removed)) {
|
} else if (hasAttached(removed[i], added, removed, dir)) {
|
||||||
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
return MessageBundle.qualify(STAGE_MESSAGE_BUNDLE,
|
||||||
"m.has_attached");
|
"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,
|
protected boolean isOnWall (ObjectData data, ObjectData[] added,
|
||||||
ObjectData[] removed)
|
ObjectData[] removed, int dir)
|
||||||
{
|
{
|
||||||
return isCovered(data.bounds, added, removed, ObjectTileSet.WALL);
|
return isCovered(data.bounds, added, removed,
|
||||||
}
|
getDirectionalConstraint(ObjectTileSet.WALL, dir));
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -240,7 +226,7 @@ public class PlacementConstraints
|
|||||||
ObjectData[] removed, int dir)
|
ObjectData[] removed, int dir)
|
||||||
{
|
{
|
||||||
return isCovered(getAdjacentEdge(data.bounds, dir), added, removed,
|
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.
|
* their space constraints met if the object is added.
|
||||||
*/
|
*/
|
||||||
protected boolean checkAdjacentSpace (ObjectData data, ObjectData[] added,
|
protected boolean hasSpaceConstrainedAdjacent (ObjectData data,
|
||||||
ObjectData[] removed)
|
ObjectData[] added, ObjectData[] removed)
|
||||||
{
|
{
|
||||||
Rectangle rect = new Rectangle(data.bounds);
|
return hasSpaceConstrainedAdjacent(data, added, removed, NORTH) ||
|
||||||
rect.grow(1, 1);
|
hasSpaceConstrainedAdjacent(data, added, removed, EAST) ||
|
||||||
ArrayList objects = getObjectData(rect, added, removed);
|
hasSpaceConstrainedAdjacent(data, added, removed, SOUTH) ||
|
||||||
|
hasSpaceConstrainedAdjacent(data, added, removed, WEST);
|
||||||
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)) {
|
* Checks space constraints for objects in the specified direction.
|
||||||
return false;
|
*/
|
||||||
}
|
protected boolean hasSpaceConstrainedAdjacent (ObjectData data,
|
||||||
}
|
ObjectData[] added, ObjectData[] removed, int dir)
|
||||||
return true;
|
{
|
||||||
|
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.
|
* Determines whether the specified wall has anything on it.
|
||||||
*/
|
*/
|
||||||
protected boolean hasOnWall (ObjectData data, ObjectData[] added,
|
protected boolean hasOnWall (ObjectData data, ObjectData[] added,
|
||||||
ObjectData[] removed)
|
ObjectData[] removed, int dir)
|
||||||
{
|
{
|
||||||
return hasConstrained(data.bounds, added, removed,
|
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
|
* 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.
|
* <code>NONE</code> if there is no such directional constraint.
|
||||||
*/
|
*/
|
||||||
protected int getConstraintDirection (ObjectData data, String prefix)
|
protected int getConstraintDirection (ObjectData data, String prefix)
|
||||||
{
|
{
|
||||||
if (data.tile.hasConstraint(prefix + "_N")) {
|
String[] constraints = data.tile.getConstraints();
|
||||||
return NORTH;
|
if (constraints == null) {
|
||||||
|
|
||||||
} 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 {
|
|
||||||
return NONE;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user