The amazing revamp four hundred billion. Let's see:

- Reworked colorization repository such that we now have arbitrary named
  "colorization classes" which can be used by various and sundry entities
  to colorize themselves.

- Added support for individual object colorizations as well as "spots"
  that go along with objects (will be used to automatically create portals
  into buildings and automatically position users properly when at a
  "station").

- Repackaged things in miso to more closely mimic what we do everywhere
  else (no more miso.scene, now we have miso.data and miso.client).

- Fixed up miso scene XML representation so that objects can more easily
  be expanded to have yet more stuff if we think of more stuff that they
  might aught to have in the future. Structured the miso scene model so
  that "uninteresting" objects (those that simply sit somewhere and don't
  do anything) take up a lot less memory than "interesting" objects (those
  that have action strings, "spots", colorizations and the works). I may
  want to roll colorizations into the "uninteresting" realm, but that
  remains to be seen.

- Made it possible for object tilesets to specify default render
  priorities for objects in that tileset. This will hopefully allow us to
  get by without any "custom" render priorities that are specified on
  scene objects, instead relying on the default priorities to resolve
  common conflicts.

There are surely other cleanups in there, but I think that was the major
thrust of it.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2228 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2003-01-31 23:10:46 +00:00
parent a11f45dec4
commit e6796b2d55
30 changed files with 1082 additions and 486 deletions
@@ -0,0 +1,377 @@
//
// $Id: ColorPository.java,v 1.1 2003/01/31 23:10:45 mdb Exp $
package com.threerings.media.image;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import com.samskivert.util.HashIntMap;
import com.samskivert.util.StringUtil;
import com.threerings.media.Log;
import com.threerings.resource.ResourceManager;
import com.threerings.util.CompiledConfig;
import com.threerings.util.RandomUtil;
/**
* A repository of image recoloration information. It was called the
* recolor repository but the re-s cancelled one another out.
*/
public class ColorPository implements Serializable
{
/**
* Used to store information on a class of colors. These are public to
* simplify the XML parsing process, so pay them no mind.
*/
public static class ClassRecord implements Serializable
{
/** An integer identifier for this class. */
public int classId;
/** The name of the color class. */
public String name;
/** The source color to use when recoloring colors in this class. */
public Color source;
/** Data identifying the range of colors around the source color
* that will be recolored when recoloring using this class. */
public float[] range;
/** The default starting legality value for this color class. See
* {@link ColorRecord#starter}. */
public boolean starter;
/** A table of target colors included in this class. */
public HashIntMap colors = new HashIntMap();
/** Used when parsing the color definitions. */
public void addColor (ColorRecord record)
{
// validate the color id
if (record.colorId > 255) {
Log.warning("Refusing to add color record; colorId > 255 " +
"[class=" + this + ", record=" + record + "].");
} else {
record.cclass = this;
colors.put(record.colorId, record);
}
}
/** Returns a random starting id from the entries in this
* class. */
public ColorRecord randomStartingColor ()
{
// figure out our starter ids if we haven't already
if (_starters == null) {
ArrayList list = new ArrayList();
Iterator iter = colors.values().iterator();
while (iter.hasNext()) {
ColorRecord color = (ColorRecord)iter.next();
if (color.starter) {
list.add(color);
}
}
_starters = (ColorRecord[])
list.toArray(new ColorRecord[list.size()]);
}
// return a random entry from the array
return _starters[RandomUtil.getInt(_starters.length)];
}
/**
* Returns a string representation of this instance.
*/
public String toString ()
{
return "[id=" + classId + ", name=" + name + ", source=#" +
Integer.toString(source.getRGB() & 0xFFFFFF, 16) +
", range=" + StringUtil.toString(range) +
", starter=" + starter + ", colors=" +
StringUtil.toString(colors.values().iterator()) + "]";
}
protected transient ColorRecord[] _starters;
/** Increase this value when object's serialized state is impacted
* by a class change (modification of fields, inheritance). */
private static final long serialVersionUID = 2;
}
/**
* Used to store information on a particular color. These are public
* to simplify the XML parsing process, so pay them no mind.
*/
public static class ColorRecord implements Serializable
{
/** The colorization class to which we belong. */
public ClassRecord cclass;
/** A unique colorization identifier (used in fingerprints). */
public int colorId;
/** The name of the target color. */
public String name;
/** Data indicating the offset (in HSV color space) from the
* source color to recolor to this color. */
public float[] offsets;
/** Tags this color as a legal starting color or not. This is a
* shameful copout, placing application-specific functionality
* into a general purpose library class. */
public boolean starter;
/**
* Returns a value that is the composite of our class id and color
* id which can be used to identify a colorization record. This
* value will always be a positive integer that fits into 16 bits.
*/
public int getColorPrint ()
{
return ((cclass.classId << 8) | colorId);
}
/**
* Returns the data in this record configured as a colorization
* instance.
*/
public Colorization getColorization ()
{
return new Colorization(getColorPrint(), cclass.source,
cclass.range, offsets);
}
/**
* Returns a string representation of this instance.
*/
public String toString ()
{
return "[id=" + colorId + ", name=" + name +
", offsets=" + StringUtil.toString(offsets) +
", starter=" + starter + "]";
}
/** Increase this value when object's serialized state is impacted
* by a class change (modification of fields, inheritance). */
private static final long serialVersionUID = 2;
}
/**
* Returns an iterator over all color classes in this pository.
*/
public Iterator enumerateClasses ()
{
return _classes.values().iterator();
}
/**
* Returns an array containing the records for the colors in the
* specified class.
*/
public ColorRecord[] enumerateColors (String className)
{
// make sure the class exists
ClassRecord record = getClassRecord(className);
if (record == null) {
return null;
}
// create the array
ColorRecord[] crecs = new ColorRecord[record.colors.size()];
Iterator iter = record.colors.values().iterator();
for (int i = 0; iter.hasNext(); i++) {
crecs[i] = ((ColorRecord)iter.next());
}
return crecs;
}
/**
* Returns an array containing the ids of the colors in the specified
* class.
*/
public int[] enumerateColorIds (String className)
{
// make sure the class exists
ClassRecord record = getClassRecord(className);
if (record == null) {
return null;
}
int[] cids = new int[record.colors.size()];
Iterator crecs = record.colors.values().iterator();
for (int i = 0; crecs.hasNext(); i++) {
cids[i] = ((ColorRecord)crecs.next()).colorId;
}
return cids;
}
/**
* Returns true if the specified color is legal for use at character
* creation time. false is always returned for non-existent colors or
* classes.
*/
public boolean isLegalStartColor (int classId, int colorId)
{
ColorRecord color = getColorRecord(classId, colorId);
return (color == null) ? false : color.starter;
}
/**
* Returns a random starting color from the specified color class.
*/
public ColorRecord getRandomStartingColor (String className)
{
// make sure the class exists
ClassRecord record = getClassRecord(className);
return (record == null) ? null : record.randomStartingColor();
}
/**
* Looks up a colorization by id.
*/
public Colorization getColorization (int classId, int colorId)
{
ColorRecord color = getColorRecord(classId, colorId);
return (color == null) ? null : color.getColorization();
}
/**
* Looks up a colorization by color print.
*/
public Colorization getColorization (int colorPrint)
{
return getColorization(colorPrint >> 8, colorPrint & 0xFF);
}
/**
* Looks up a colorization by name.
*/
public Colorization getColorization (String className, int colorId)
{
ClassRecord crec = getClassRecord(className);
if (crec != null) {
ColorRecord color = (ColorRecord)crec.colors.get(colorId);
if (color != null) {
color.getColorization();
}
}
return null;
}
/**
* Loads up a colorization class by name and logs a warning if it
* doesn't exist.
*/
public ClassRecord getClassRecord (String className)
{
Iterator iter = _classes.values().iterator();
while (iter.hasNext()) {
ClassRecord crec = (ClassRecord)iter.next();
if (crec.name.equals(className)) {
return crec;
}
}
Log.warning("No such color class [class=" + className + "].");
Thread.dumpStack();
return null;
}
/**
* Looks up the requested color record.
*/
protected ColorRecord getColorRecord (int classId, int colorId)
{
ClassRecord record = (ClassRecord)_classes.get(classId);
if (record == null) {
// if they request color class zero, we assume they're just
// decoding a blank colorprint, otherwise we complain
if (classId != 0) {
Log.warning("Requested unknown color class " +
"[classId=" + classId +
", colorId=" + colorId + "].");
Thread.dumpStack();
}
return null;
}
return (ColorRecord)record.colors.get(colorId);
}
/**
* Adds a fully configured color class record to the pository. This is
* only called by the XML parsing code, so pay it no mind.
*/
public void addClass (ClassRecord record)
{
// validate the class id
if (record.classId > 255) {
Log.warning("Refusing to add class; classId > 255 " + record + ".");
} else {
_classes.put(record.classId, record);
}
}
/**
* Loads up a serialized color pository from the supplied resource
* manager.
*/
public static ColorPository loadColorPository (ResourceManager rmgr)
{
try {
return loadColorPository(rmgr.getResource(CONFIG_PATH));
} catch (IOException ioe) {
Log.warning("Failure loading color pository [path=" + CONFIG_PATH +
", error=" + ioe + "].");
return new ColorPository();
}
}
/**
* Loads up a serialized color pository from the supplied resource
* manager.
*/
public static ColorPository loadColorPository (InputStream source)
{
try {
return (ColorPository)CompiledConfig.loadConfig(source);
} catch (IOException ioe) {
Log.warning("Failure loading color pository: " + ioe + ".");
return new ColorPository();
}
}
/**
* Serializes and saves color pository to the supplied file.
*/
public static void saveColorPository (ColorPository posit, File root)
{
File path = new File(root, CONFIG_PATH);
try {
CompiledConfig.saveConfig(path, posit);
} catch (IOException ioe) {
Log.warning("Failure saving color pository " +
"[path=" + path + ", error=" + ioe + "].");
}
}
/** Our mapping from class names to class records. */
protected HashIntMap _classes = new HashIntMap();
/** Increase this value when object's serialized state is impacted by
* a class change (modification of fields, inheritance). */
private static final long serialVersionUID = 1;
/**
* The path (relative to the resource directory) at which the
* serialized recolorization repository should be loaded and stored.
*/
protected static final String CONFIG_PATH = "config/media/colordefs.dat";
}
@@ -0,0 +1,36 @@
//
// $Id: DumpColorPository.java,v 1.1 2003/01/31 23:10:45 mdb Exp $
package com.threerings.media.image.tools;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import com.threerings.media.image.ColorPository;
/**
* Simple tool for dumping a serialized color pository.
*/
public class DumpColorPository
{
public static void main (String[] args)
{
if (args.length == 0) {
System.err.println("Usage: DumpColorPository colorpos.dat");
System.exit(-1);
}
try {
ColorPository pos = ColorPository.loadColorPository(
new FileInputStream(args[0]));
Iterator iter = pos.enumerateClasses();
while (iter.hasNext()) {
System.out.println(iter.next());
}
} catch (IOException ioe) {
ioe.printStackTrace(System.err);
}
}
}
@@ -0,0 +1,59 @@
//
// $Id: ColorPositoryParser.java,v 1.1 2003/01/31 23:10:45 mdb Exp $
package com.threerings.media.image.tools.xml;
import java.io.Serializable;
import org.xml.sax.Attributes;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import com.samskivert.xml.SetPropertyFieldsRule;
import com.threerings.tools.xml.CompiledConfigParser;
import com.threerings.media.image.ColorPository.ClassRecord;
import com.threerings.media.image.ColorPository.ColorRecord;
import com.threerings.media.image.ColorPository;
/**
* Parses the XML color repository definition and creates a {@link
* ColorPository} instance that reflects its contents.
*/
public class ColorPositoryParser extends CompiledConfigParser
{
// documentation inherited
protected Serializable createConfigObject ()
{
return new ColorPository();
}
// documentation inherited
protected void addRules (Digester digest)
{
// create and configure class record instances
String prefix = "colors/class";
digest.addObjectCreate(prefix, ClassRecord.class.getName());
digest.addRule(prefix, new SetPropertyFieldsRule(digest));
digest.addSetNext(prefix, "addClass", ClassRecord.class.getName());
// create and configure color record instances
prefix += "/color";
digest.addRule(prefix, new Rule(digest) {
public void begin (Attributes attributes) throws Exception {
// we want to inherit settings from the color class when
// creating the record, so we do some custom stuff
ColorRecord record = new ColorRecord();
ClassRecord clrec = (ClassRecord)digester.peek();
record.starter = clrec.starter;
digester.push(record);
}
public void end () throws Exception {
digester.pop();
}
});
digest.addRule(prefix, new SetPropertyFieldsRule(digest));
digest.addSetNext(prefix, "addColor", ColorRecord.class.getName());
}
}
@@ -1,7 +1,7 @@
//
// $Id: DirtyItemList.java,v 1.17 2002/10/16 01:53:10 ray Exp $
// $Id: DirtyItemList.java,v 1.18 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.Color;
import java.awt.Graphics2D;
@@ -17,7 +17,7 @@ import com.samskivert.util.StringUtil;
import com.threerings.media.Log;
import com.threerings.media.sprite.Sprite;
import com.threerings.media.tile.ObjectTile;
import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.client.util.IsoUtil;
/**
* The dirty item list keeps track of dirty sprites and object tiles
@@ -48,10 +48,10 @@ public class DirtyItemList
* @param footprint the footprint of the object tile if it should be
* rendered, null otherwise.
*/
public void appendDirtyObject (SceneObject scobj, Shape footprint)
public void appendDirtyObject (DisplayObjectInfo info, Shape footprint)
{
DirtyItem item = getDirtyItem();
item.init(scobj, scobj.bounds, footprint, scobj.x, scobj.y);
item.init(info, info.bounds, footprint, info.x, info.y);
_items.add(item);
}
@@ -234,8 +234,8 @@ public class DirtyItemList
// rightmost tiles are equivalent
lx = rx = ox;
ly = ry = oy;
if (obj instanceof SceneObject) {
ObjectTile tile = ((SceneObject)obj).tile;
if (obj instanceof DisplayObjectInfo) {
ObjectTile tile = ((DisplayObjectInfo)obj).tile;
lx -= (tile.getBaseWidth() - 1);
ry -= (tile.getBaseHeight() - 1);
}
@@ -258,7 +258,7 @@ public class DirtyItemList
if (obj instanceof Sprite) {
((Sprite)obj).paint(gfx);
} else {
((SceneObject)obj).tile.paint(gfx, bounds.x, bounds.y);
((DisplayObjectInfo)obj).tile.paint(gfx, bounds.x, bounds.y);
}
}
@@ -289,7 +289,7 @@ public class DirtyItemList
// }
// // objects are equivalent if they are the same object
// if ((obj instanceof SceneObject) && (b.obj instanceof SceneObject)) {
// if ((obj instanceof DisplayObjectInfo) && (b.obj instanceof DisplayObjectInfo)) {
// return (obj == b.obj);
// }
@@ -534,10 +534,10 @@ public class DirtyItemList
// priority scene; this allows us to avoid all sorts of sticky
// business wherein the render order between two overlapping
// objects cannot be determined without a z-buffer
if ((da.obj instanceof SceneObject) &&
(db.obj instanceof SceneObject)) {
SceneObject soa = (SceneObject)da.obj;
SceneObject sob = (SceneObject)db.obj;
if ((da.obj instanceof DisplayObjectInfo) &&
(db.obj instanceof DisplayObjectInfo)) {
DisplayObjectInfo soa = (DisplayObjectInfo)da.obj;
DisplayObjectInfo sob = (DisplayObjectInfo)db.obj;
if (IsoUtil.objectFootprintsOverlap(soa, sob)) {
return (soa.priority - sob.priority);
}
@@ -1,14 +1,14 @@
//
// $Id: DisplayMisoScene.java,v 1.8 2003/01/13 22:53:56 mdb Exp $
// $Id: DisplayMisoScene.java,v 1.9 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.Rectangle;
import com.threerings.media.tile.ObjectTile;
import com.threerings.media.tile.Tile;
import com.threerings.miso.scene.util.ObjectSet;
import com.threerings.miso.client.util.ObjectSet;
import com.threerings.miso.tile.BaseTile;
/**
@@ -30,10 +30,10 @@ public interface DisplayMisoScene
public Tile getFringeTile (int x, int y);
/**
* Populates the supplied scene object set with all objects whose
* Populates the supplied object set with info on all objects whose
* origin falls in the requested region.
*/
public void getSceneObjects (Rectangle region, ObjectSet set);
public void getObjects (Rectangle region, ObjectSet set);
/**
* Returns true if the supplied traverser can traverse the specified
@@ -1,15 +1,13 @@
//
// $Id: DisplayMisoSceneImpl.java,v 1.64 2003/01/13 22:53:56 mdb Exp $
// $Id: DisplayMisoSceneImpl.java,v 1.65 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Random;
import com.samskivert.util.StringUtil;
import com.threerings.media.tile.NoSuchTileException;
import com.threerings.media.tile.NoSuchTileSetException;
import com.threerings.media.tile.ObjectTile;
@@ -17,7 +15,9 @@ import com.threerings.media.tile.Tile;
import com.threerings.media.tile.TileLayer;
import com.threerings.miso.Log;
import com.threerings.miso.scene.util.ObjectSet;
import com.threerings.miso.client.util.ObjectSet;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.data.ObjectInfo;
import com.threerings.miso.tile.AutoFringer;
import com.threerings.miso.tile.BaseTile;
import com.threerings.miso.tile.BaseTileLayer;
@@ -56,6 +56,62 @@ public class DisplayMisoSceneImpl
setMisoSceneModel(model);
}
/**
* Provides this display miso scene with a tile manager from which it
* can load up all of its tiles.
*/
public void setTileManager (MisoTileManager tmgr)
{
_tmgr = tmgr;
_fringer = tmgr.getAutoFringer();
populateLayers();
}
// documentation inherited from interface
public BaseTile getBaseTile (int x, int y)
{
return _base.getTile(x, y);
}
// documentation inherited from interface
public Tile getFringeTile (int x, int y)
{
return _fringe.getTile(x, y);
}
// documentation inherited from interface
public void getObjects (Rectangle region, ObjectSet set)
{
// iterate over all of our objects, creating and including scene
// objects for those that intersect the region
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
DisplayObjectInfo scobj = (DisplayObjectInfo)_objects.get(ii);
if (region.contains(scobj.x, scobj.y)) {
set.insert(scobj);
}
}
}
// documentation inherited from interface
public boolean canTraverse (Object trav, int x, int y)
{
BaseTile tile = getBaseTile(x, y);
return (((tile == null) || tile.isPassable()) &&
!_covered[y*_model.width+x]);
}
/**
* Return a string representation of this Miso scene object.
*/
public String toString ()
{
StringBuffer buf = new StringBuffer();
buf.append("[width=").append(_base.getWidth());
buf.append(", height=").append(_base.getHeight());
return buf.append("]").toString();
}
/**
* Instructs this miso scene to use the supplied model instead of its
* current model. This should be followed up by a called to {@link
@@ -73,17 +129,20 @@ public class DisplayMisoSceneImpl
_base = new BaseTileLayer(new BaseTile[swid*shei], swid, shei);
_fringe = new TileLayer(new Tile[swid*shei], swid, shei);
_covered = new boolean[swid*shei];
}
/**
* Provides this display miso scene with a tile manager from which it
* can load up all of its tiles.
*/
public void setTileManager (MisoTileManager tmgr)
{
_tmgr = tmgr;
_fringer = tmgr.getAutoFringer();
populateLayers();
// create display object infos for our uninteresting objects
int ocount = (_model.objectTileIds == null) ? 0 :
_model.objectTileIds.length;
for (int ii = 0; ii < ocount; ii++) {
_objects.add(new DisplayObjectInfo(_model.objectTileIds[ii],
_model.objectXs[ii],
_model.objectYs[ii]));
}
// create display object infos for our interesting objects
for (int ii = 0, ll = _model.objectInfo.length; ii < ll; ii++) {
_objects.add(new DisplayObjectInfo(_model.objectInfo[ii]));
}
}
/**
@@ -127,132 +186,57 @@ public class DisplayMisoSceneImpl
}
}
// sanity check the object layer info
int ocount = _model.objectTileIds.length;
if (ocount % 3 != 0) {
throw new IllegalArgumentException(
"model.objectTileIds.length % 3 != 0");
}
// create object tile instances for our objects
for (int ii = 0; ii < ocount; ii += 3) {
int col = _model.objectTileIds[ii];
int row = _model.objectTileIds[ii+1];
int fqTid = _model.objectTileIds[ii+2];
int tsid = (fqTid >> 16) & 0xFFFF, tid = (fqTid & 0xFFFF);
try {
expandObject(col, row, tsid, tid, fqTid, ii/3);
} catch (NoSuchTileSetException te) {
Log.warning("Scene contains non-existent object tile " +
"[tsid=" + tsid + ", tid=" + tid +
", col=" + col + ", row=" + row + "].");
}
// populate our display objects with object tiles
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
populateObject((DisplayObjectInfo)_objects.get(ii));
}
}
/**
* Called to expand each object read from the model into an actual
* object tile instance with the appropriate additional data.
*
* @return the scene object record for the newly created object tile
* (which will have been put into all the appropriate lists and
* tables).
* Called to populate an object with its object tile when we have been
* configured with a tile manager from which to obtain such things.
*/
protected SceneObject expandObject (
int col, int row, int tsid, int tid, int fqTid, int objidx)
throws NoSuchTileException, NoSuchTileSetException
protected void populateObject (DisplayObjectInfo info)
{
// create and initialize an object info record for this object
SceneObject scobj = createSceneObject(
col, row, (ObjectTile)_tmgr.getTile(tsid, tid));
int tsid = (info.tileId >> 16) & 0xFFFF, tid = (info.tileId & 0xFFFF);
try {
initObject(info, (ObjectTile)_tmgr.getTile(tsid, tid));
} catch (NoSuchTileSetException te) {
Log.warning("Scene contains non-existent object tile " +
"[info=" + info + ", tsid=" + tsid +
", tid=" + tid + "].");
}
}
// assign the object's remaining attributes
if (!StringUtil.blank(_model.objectActions[objidx])) {
scobj.action = _model.objectActions[objidx];
}
// if we have object priorities, use 'em
if (_model.objectPrios != null) {
scobj.priority = _model.objectPrios[objidx];
}
/**
* Initializes the supplied object with its object tile and configures
* any necessary peripheral scene business that couldn't be configured
* prior to the object having its tile.
*/
protected void initObject (DisplayObjectInfo info, ObjectTile tile)
{
// configure the object info with its object tile
info.setObjectTile(tile);
// generate a "shadow" for this object tile by toggling the
// "covered" flag on in all base tiles below it (to prevent
// sprites from walking on those tiles)
setObjectTileFootprint(scobj.tile, col, row, true);
// add the info record to the list
_objects.add(scobj);
// return the object info so that derived classes may access it
return scobj;
}
// documentation inherited from interface
public BaseTile getBaseTile (int x, int y)
{
return _base.getTile(x, y);
}
// documentation inherited from interface
public Tile getFringeTile (int x, int y)
{
return _fringe.getTile(x, y);
}
// documentation inherited from interface
public void getSceneObjects (Rectangle region, ObjectSet set)
{
// iterate over all of our objects, creating and including scene
// objects for those that intersect the region
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
SceneObject scobj = (SceneObject)_objects.get(ii);
if (region.contains(scobj.x, scobj.y)) {
set.insert(scobj);
}
}
}
// documentation inherited from interface
public boolean canTraverse (Object trav, int x, int y)
{
BaseTile tile = getBaseTile(x, y);
return (((tile == null) || tile.isPassable()) &&
!_covered[y*_model.width+x]);
setObjectTileFootprint(info.tile, info.x, info.y, true);
}
/**
* Return a string representation of this Miso scene object.
*/
public String toString ()
{
StringBuffer buf = new StringBuffer();
buf.append("[width=").append(_base.getWidth());
buf.append(", height=").append(_base.getHeight());
return buf.append("]").toString();
}
/**
* Creates a scene object record. This allows derived classes to
* provide extended records.
*/
protected SceneObject createSceneObject (int x, int y, ObjectTile tile)
{
return new SceneObject(x, y, tile);
}
/**
* Locates the scene object record for the object tile at the
* Locates the display object info record for the object tile at the
* specified location. Two of the same kind of object tile cannot
* exist at the same location.
*/
protected SceneObject getSceneObject (ObjectTile tile, int x, int y)
protected DisplayObjectInfo getObjectInfo (ObjectTile tile, int x, int y)
{
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
SceneObject scobj = (SceneObject)_objects.get(ii);
if (scobj.tile == tile && scobj.x == x && scobj.y == y) {
return scobj;
DisplayObjectInfo oinfo = (DisplayObjectInfo)_objects.get(ii);
if (oinfo.tile == tile && oinfo.x == x && oinfo.y == y) {
return oinfo;
}
}
return null;
@@ -1,44 +1,56 @@
//
// $Id: DisplayObjectInfo.java,v 1.5 2002/11/28 03:41:58 mdb Exp $
// $Id: DisplayObjectInfo.java,v 1.6 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.Rectangle;
import com.samskivert.util.StringUtil;
import com.threerings.media.tile.ObjectTile;
import com.threerings.miso.data.ObjectInfo;
/**
* Used to track information about an object in the scene.
*/
public class SceneObject
public class DisplayObjectInfo extends ObjectInfo
{
/** A reference to the object tile itself. */
public ObjectTile tile;
/** The x and y tile coordinates of the object. */
public int x = -1, y = -1;
/** The object's render priority. */
public byte priority = 0;
/** The action associated with this object or null if it has no
* action. */
public String action;
/** The object's bounding rectangle. This will be filled in
* automatically by the Miso scene view when the object is used. */
* automatically by the scene view when the object is used. */
public Rectangle bounds;
/**
* Convenience constructor.
*/
public SceneObject (int x, int y, ObjectTile tile)
public DisplayObjectInfo (int tileId, int x, int y)
{
super(tileId, x, y);
}
/**
* Convenience constructor.
*/
public DisplayObjectInfo (ObjectInfo source)
{
super(source);
}
/**
* Provides this display object with a reference to its object tile
* when it becomes available. This must be called before the tile is
* used in any sort of display circumstances.
*/
public void setObjectTile (ObjectTile tile)
{
this.tile = tile;
this.x = x;
this.y = y;
// if we don't already have an overridden render priority; use the
// one from our object tile (assuming we have one)
if (priority == 0 && tile != null) {
priority = (byte)Math.max(
Byte.MIN_VALUE, Math.min(Byte.MAX_VALUE, tile.getPriority()));
}
}
/**
@@ -50,29 +62,4 @@ public class SceneObject
{
return false;
}
// documentation inherited
public boolean equals (Object other)
{
if (other instanceof SceneObject) {
SceneObject oso = (SceneObject)other;
return (x == oso.x && y == oso.y && tile == oso.tile);
} else {
return false;
}
}
// documentation inherited
public int hashCode ()
{
return x ^ y ^ tile.hashCode();
}
/**
* Generates a string representation of this instance.
*/
public String toString ()
{
return StringUtil.fieldsToString(this);
}
}
@@ -1,7 +1,7 @@
//
// $Id: IsoSceneView.java,v 1.130 2003/01/15 21:12:45 shaper Exp $
// $Id: IsoSceneView.java,v 1.131 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
@@ -36,10 +36,10 @@ import com.threerings.media.tile.Tile;
import com.threerings.miso.Log;
import com.threerings.miso.MisoPrefs;
import com.threerings.miso.scene.DirtyItemList.DirtyItem;
import com.threerings.miso.scene.util.AStarPathUtil;
import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.scene.util.ObjectSet;
import com.threerings.miso.client.DirtyItemList.DirtyItem;
import com.threerings.miso.client.util.AStarPathUtil;
import com.threerings.miso.client.util.IsoUtil;
import com.threerings.miso.client.util.ObjectSet;
import com.threerings.miso.tile.BaseTile;
/**
@@ -124,12 +124,12 @@ public class IsoSceneView implements SceneView
// grab all available objects
Rectangle rect = new Rectangle(Short.MIN_VALUE, Short.MIN_VALUE,
2*Short.MAX_VALUE, 2*Short.MAX_VALUE);
_scene.getSceneObjects(rect, _objects);
_scene.getObjects(rect, _objects);
// and fill in the new objects' bounds
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
SceneObject scobj = _objects.get(ii);
DisplayObjectInfo scobj = _objects.get(ii);
if (scobj.bounds == null) {
scobj.bounds = IsoUtil.getObjectBounds(_model, scobj);
}
@@ -194,8 +194,8 @@ public class IsoSceneView implements SceneView
Polygon hpoly = null;
// if we have a hover object, do some business
if (_hobject != null && _hobject instanceof SceneObject) {
SceneObject scobj = (SceneObject)_hobject;
if (_hobject != null && _hobject instanceof DisplayObjectInfo) {
DisplayObjectInfo scobj = (DisplayObjectInfo)_hobject;
if (scobj.action != null || _hmode == HIGHLIGHT_ALWAYS) {
hpoly = IsoUtil.getObjectFootprint(_model, scobj);
}
@@ -421,7 +421,7 @@ public class IsoSceneView implements SceneView
// add any objects impacted by the dirty rectangle
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
SceneObject scobj = (SceneObject)_objects.get(ii);
DisplayObjectInfo scobj = _objects.get(ii);
if (!scobj.bounds.intersects(clip)) {
continue;
}
@@ -467,13 +467,13 @@ public class IsoSceneView implements SceneView
// grab all available objects
Rectangle rect = new Rectangle(Short.MIN_VALUE, Short.MIN_VALUE,
2*Short.MAX_VALUE, 2*Short.MAX_VALUE);
_scene.getSceneObjects(rect, _objects);
addAdditionalSceneObjects(_objects);
_scene.getObjects(rect, _objects);
addAdditionalObjects(_objects);
// and fill in those objects' bounds
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
SceneObject scobj = _objects.get(ii);
DisplayObjectInfo scobj = _objects.get(ii);
scobj.bounds = IsoUtil.getObjectBounds(_model, scobj);
}
}
@@ -482,7 +482,7 @@ public class IsoSceneView implements SceneView
* A place for subclasses to add any additional scene objects they
* may have.
*/
protected void addAdditionalSceneObjects (ObjectSet set)
protected void addAdditionalObjects (ObjectSet set)
{
// nothing by default
}
@@ -581,8 +581,8 @@ public class IsoSceneView implements SceneView
}
// unhover the old
if (_hobject instanceof SceneObject) {
SceneObject oldhov = (SceneObject) _hobject;
if (_hobject instanceof DisplayObjectInfo) {
DisplayObjectInfo oldhov = (DisplayObjectInfo) _hobject;
if (oldhov.setHovered(false)) {
_remgr.invalidateRegion(oldhov.bounds);
}
@@ -593,8 +593,8 @@ public class IsoSceneView implements SceneView
_hobject = newHover;
// hover the new
if (_hobject instanceof SceneObject) {
SceneObject newhov = (SceneObject) _hobject;
if (_hobject instanceof DisplayObjectInfo) {
DisplayObjectInfo newhov = (DisplayObjectInfo) _hobject;
if (newhov.setHovered(true)) {
_remgr.invalidateRegion(newhov.bounds);
}
@@ -622,7 +622,7 @@ public class IsoSceneView implements SceneView
{
int ocount = _objects.size();
for (int ii = 0; ii < ocount; ii++) {
SceneObject scobj = (SceneObject)_objects.get(ii);
DisplayObjectInfo scobj = (DisplayObjectInfo)_objects.get(ii);
Rectangle pbounds = scobj.bounds;
// skip bounding rects that don't contain the point
if (!pbounds.contains(x, y)) {
@@ -1,14 +1,14 @@
//
// $Id: IsoSceneViewModel.java,v 1.27 2003/01/15 21:12:45 shaper Exp $
// $Id: IsoSceneViewModel.java,v 1.28 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.Point;
import java.awt.Rectangle;
import com.threerings.miso.Log;
import com.threerings.miso.MisoConfig;
import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.client.util.IsoUtil;
/**
* Provides a holding place for the myriad parameters and bits of data
@@ -1,7 +1,7 @@
//
// $Id: SceneView.java,v 1.32 2003/01/13 22:53:56 mdb Exp $
// $Id: SceneView.java,v 1.33 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.Graphics2D;
import java.awt.Point;
@@ -79,7 +79,7 @@ public interface SceneView
/**
* Returns information about the object over which the mouse is
* currently hovering (either a {@link SceneObject} or a {@link
* currently hovering (either a {@link DisplayObjectInfo} or a {@link
* Sprite}), or null if the mouse is not hovering over anything of
* interest.
*/
@@ -1,7 +1,7 @@
//
// $Id: SceneViewPanel.java,v 1.48 2003/01/15 21:12:45 shaper Exp $
// $Id: SceneViewPanel.java,v 1.49 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.Dimension;
import java.awt.Graphics2D;
@@ -22,7 +22,7 @@ import com.threerings.media.sprite.Sprite;
import com.threerings.media.sprite.SpriteManager;
import com.threerings.miso.Log;
import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.client.util.IsoUtil;
/**
* The scene view panel is responsible for managing a {@link
@@ -1,7 +1,7 @@
//
// $Id: TilePath.java,v 1.12 2003/01/13 22:53:56 mdb Exp $
// $Id: TilePath.java,v 1.13 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import java.awt.*;
import java.util.List;
@@ -14,7 +14,7 @@ import com.threerings.media.util.PathNode;
import com.threerings.media.util.Pathable;
import com.threerings.miso.Log;
import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.client.util.IsoUtil;
/**
* The tile path represents a path of tiles through a scene. The path is
@@ -1,7 +1,7 @@
//
// $Id: TilePathNode.java,v 1.2 2002/05/31 03:38:03 mdb Exp $
// $Id: TilePathNode.java,v 1.3 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.client;
import com.threerings.media.util.PathNode;
@@ -1,7 +1,7 @@
//
// $Id: AStarPathUtil.java,v 1.24 2003/01/15 21:44:52 shaper Exp $
// $Id: AStarPathUtil.java,v 1.25 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene.util;
package com.threerings.miso.client.util;
import java.awt.Point;
import java.util.*;
@@ -11,7 +11,7 @@ import com.samskivert.util.HashIntMap;
import com.threerings.media.util.MathUtil;
import com.threerings.miso.Log;
import com.threerings.miso.scene.DisplayMisoScene;
import com.threerings.miso.client.DisplayMisoScene;
import com.threerings.miso.tile.BaseTile;
/**
@@ -1,7 +1,7 @@
//
// $Id: IsoUtil.java,v 1.42 2003/01/13 22:53:56 mdb Exp $
// $Id: IsoUtil.java,v 1.43 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene.util;
package com.threerings.miso.client.util;
import java.awt.Point;
import java.awt.Polygon;
@@ -16,8 +16,8 @@ import com.threerings.util.DirectionCodes;
import com.threerings.util.DirectionUtil;
import com.threerings.miso.Log;
import com.threerings.miso.scene.IsoSceneViewModel;
import com.threerings.miso.scene.SceneObject;
import com.threerings.miso.client.IsoSceneViewModel;
import com.threerings.miso.client.DisplayObjectInfo;
/**
* The <code>IsoUtil</code> class is a holding place for miscellaneous
@@ -38,7 +38,7 @@ public class IsoUtil
* @return the bounding polygon.
*/
public static Polygon getObjectFootprint (
IsoSceneViewModel model, SceneObject scobj)
IsoSceneViewModel model, DisplayObjectInfo scobj)
{
Polygon boundsPoly = new SmartPolygon();
Point tpos = tileToScreen(model, scobj.x, scobj.y, new Point());
@@ -84,7 +84,7 @@ public class IsoUtil
* @return the bounding rectangle.
*/
public static Rectangle getObjectBounds (
IsoSceneViewModel model, SceneObject scobj)
IsoSceneViewModel model, DisplayObjectInfo scobj)
{
Point tpos = tileToScreen(model, scobj.x, scobj.y, new Point());
@@ -110,7 +110,7 @@ public class IsoUtil
* the objects occupy the specified coordinates, false if not.
*/
public static boolean objectFootprintsOverlap (
SceneObject so1, SceneObject so2)
DisplayObjectInfo so1, DisplayObjectInfo so2)
{
return (so2.x > so1.x - so1.tile.getBaseWidth() &&
so1.x > so2.x - so2.tile.getBaseWidth() &&
@@ -1,7 +1,7 @@
//
// $Id: ObjectSet.java,v 1.2 2002/10/15 21:01:39 ray Exp $
// $Id: ObjectSet.java,v 1.3 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene.util;
package com.threerings.miso.client.util;
import java.util.Arrays;
import java.util.Comparator;
@@ -9,31 +9,36 @@ import java.util.Comparator;
import com.samskivert.util.ArrayUtil;
import com.samskivert.util.ListUtil;
import com.threerings.miso.scene.SceneObject;
import com.threerings.miso.Log;
import com.threerings.miso.client.DisplayObjectInfo;
/**
* Used to store an (arbitrarily) ordered, low-impact iteratable (doesn't
* require object creation), set of {@link SceneObject} instances.
* require object creation), set of {@link DisplayObjectInfo} instances.
*/
public class ObjectSet
{
/**
* Inserts the supplied scene object into the set.
* Inserts the supplied object into the set.
*
* @return true if it was inserted, false if the object was already in
* the set.
*/
public boolean insert (SceneObject scobj)
public boolean insert (DisplayObjectInfo info)
{
// bail if it's already in the set
int ipos = indexOf(scobj);
int ipos = indexOf(info);
if (ipos >= 0) {
// log a warning because the caller shouldn't be doing this
Log.warning("Requested to add a display object to a set that " +
"already contains such an object [ninfo=" + info +
", oinfo=" + _objs[ipos] + "].");
return false;
}
// otherwise insert it
ipos = -(ipos+1);
_scobjs = ListUtil.insert(_scobjs, ipos, scobj);
_objs = ListUtil.insert(_objs, ipos, info);
_size++;
return true;
}
@@ -42,13 +47,13 @@ public class ObjectSet
* Returns true if the specified object is in the set, false if it is
* not.
*/
public boolean contains (SceneObject scobj)
public boolean contains (DisplayObjectInfo info)
{
return (indexOf(scobj) >= 0);
return (indexOf(info) >= 0);
}
/**
* Returns the number of scene objects in this set.
* Returns the number of objects in this set.
*/
public int size ()
{
@@ -56,12 +61,12 @@ public class ObjectSet
}
/**
* Returns the scene object with the specified index. The index must &
* be between <code>0</code> and {@link #size}<code>-1</code>.
* Returns the object with the specified index. The index must & be
* between <code>0</code> and {@link #size}<code>-1</code>.
*/
public SceneObject get (int index)
public DisplayObjectInfo get (int index)
{
return (SceneObject)_scobjs[index];
return (DisplayObjectInfo)_objs[index];
}
/**
@@ -69,18 +74,18 @@ public class ObjectSet
*/
public void remove (int index)
{
ListUtil.remove(_scobjs, index);
ListUtil.remove(_objs, index);
_size--;
}
/**
* Removes the specified scene object from the set.
* Removes the specified object from the set.
*
* @return true if it was removed, false if it was not in the set.
*/
public boolean remove (SceneObject scobj)
public boolean remove (DisplayObjectInfo info)
{
int opos = indexOf(scobj);
int opos = indexOf(info);
if (opos >= 0) {
remove(opos);
return true;
@@ -95,30 +100,50 @@ public class ObjectSet
public void clear ()
{
_size = 0;
Arrays.fill(_scobjs, null);
Arrays.fill(_objs, null);
}
/**
* Returns a string representation of this instance.
*/
public String toString ()
{
StringBuffer buf = new StringBuffer("[");
for (int ii = 0; ii < _size; ii++) {
if (ii > 0) {
buf.append(", ");
}
buf.append(_objs[ii]);
}
return buf.append("]").toString();
}
/**
* Returns the index of the object or it's insertion index if it is
* not in the set.
*/
protected final int indexOf (SceneObject scobj)
protected final int indexOf (DisplayObjectInfo info)
{
return ArrayUtil.binarySearch(_scobjs, 0, _size, scobj, SCOBJ_COMP);
return ArrayUtil.binarySearch(_objs, 0, _size, info, INFO_COMP);
}
/** Our sorted array of scene objects. */
protected Object[] _scobjs = new Object[DEFAULT_SIZE];
/** Our sorted array of objects. */
protected Object[] _objs = new Object[DEFAULT_SIZE];
/** The number of objects in the set. */
protected int _size;
/** We simply sort the scene objects in order of their hash code. We
* don't care about their orderer, it simply needs to exist to support
* binary search. */
protected static final Comparator SCOBJ_COMP = new Comparator() {
/** We simply sort the objects in order of their hash code. We don't
* care about their order, it exists only to support binary search. */
protected static final Comparator INFO_COMP = new Comparator() {
public int compare (Object o1, Object o2) {
return o1.hashCode() - o2.hashCode();
DisplayObjectInfo do1 = (DisplayObjectInfo)o1;
DisplayObjectInfo do2 = (DisplayObjectInfo)o2;
if (do1.tileId == do2.tileId) {
return ((do1.x << 16) + do1.y) - ((do2.x << 16) + do2.y);
} else {
return do1.tileId - do2.tileId;
}
}
};
@@ -1,14 +1,12 @@
//
// $Id: MisoSceneModel.java,v 1.10 2002/09/23 23:07:11 mdb Exp $
// $Id: MisoSceneModel.java,v 1.11 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene;
package com.threerings.miso.data;
import com.samskivert.util.StringUtil;
import java.util.ArrayList;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.miso.Log;
/**
* The scene model is the bare bones representation of the data for a
* scene in the Miso system. From the scene model, one would create an
@@ -29,24 +27,26 @@ public class MisoSceneModel extends SimpleStreamableObject
/** The viewport height in tiles. */
public int vheight;
/** The combined tile ids (tile set id and tile id)
* in compressed format.
* Don't go poking around in here, use the accessor methods. */
/** The combined tile ids (tile set id and tile id) in compressed
* format. Don't go poking around in here, use the accessor
* methods. */
public int[] baseTileIds;
/** The combined tile ids (tile set id and tile id) of the files in
* the object layer in (x, y, tile id) format. */
/** The combined tile ids (tile set id and tile id) of the
* "uninteresting" tiles in the object layer. */
public int[] objectTileIds;
/** The action strings associated with the object tiles in the order
* that the tiles are specified in the {@link #objectTileIds} array.
* Elements of this array may be null but will be converted to the
* empty string during serialization. */
public String[] objectActions;
/** The x coordinate of the "uninteresting" tiles in the object
* layer. */
public short[] objectXs;
/** Render priorities for each object tile in the scene, which are
* used to resolve overlapped object render order conflicts. */
public byte[] objectPrios;
/** The y coordinate of the "uninteresting" tiles in the object
* layer. */
public short[] objectYs;
/** Information records for the "interesting" objects in the object
* layer. */
public ObjectInfo[] objectInfo;
/**
* Get the fully-qualified tile id of the base tile at the specified
@@ -140,11 +140,37 @@ public class MisoSceneModel extends SimpleStreamableObject
MisoSceneModel model = (MisoSceneModel)super.clone();
model.baseTileIds = (int[])baseTileIds.clone();
model.objectTileIds = (int[])objectTileIds.clone();
model.objectActions = (String[])objectActions.clone();
model.objectPrios = (byte[])objectPrios.clone();
model.objectXs = (short[])objectXs.clone();
model.objectYs = (short[])objectYs.clone();
model.objectInfo = (ObjectInfo[])objectInfo.clone();
return model;
}
/**
* Populates the interesting and uninteresting parts of a miso scene
* model given lists of {@link ObjectInfo} records for each.
*/
public static void populateObjects (MisoSceneModel model,
ArrayList ilist, ArrayList ulist)
{
// set up the uninteresting arrays
int ucount = ulist.size();
model.objectTileIds = new int[ucount];
model.objectXs = new short[ucount];
model.objectYs = new short[ucount];
for (int ii = 0; ii < ucount; ii++) {
ObjectInfo info = (ObjectInfo)ulist.get(ii);
model.objectTileIds[ii] = info.tileId;
model.objectXs[ii] = (short)info.x;
model.objectYs[ii] = (short)info.y;
}
// set up the interesting array
int icount = ilist.size();
model.objectInfo = new ObjectInfo[icount];
ilist.toArray(model.objectInfo);
}
/**
* Creates and returns a blank scene model (with zero width and
* height).
@@ -180,7 +206,8 @@ public class MisoSceneModel extends SimpleStreamableObject
model.vheight = vheight;
model.allocateBaseTileArray();
model.objectTileIds = new int[0];
model.objectActions = new String[0];
model.objectPrios = new byte[0];
model.objectXs = new short[0];
model.objectYs = new short[0];
model.objectInfo = new ObjectInfo[0];
}
}
@@ -0,0 +1,120 @@
//
// $Id: ObjectInfo.java,v 1.1 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.data;
import com.samskivert.util.StringUtil;
import com.threerings.io.SimpleStreamableObject;
/**
* Contains information about an object in a Miso scene.
*/
public class ObjectInfo extends SimpleStreamableObject
{
/** The fully qualified object tile id. */
public int tileId;
/** The x and y tile coordinates of the object. */
public int x, y;
/** The object's render priority. */
public byte priority = 0;
/** The action associated with this object or null if it has no
* action. */
public String action;
/** A "spot" associated with this object (specified as an offset from
* the fine coordinates of the object's origin tile). */
public byte sx, sy;
/** The orientation of the "spot" associated with this object. */
public byte sorient;
/** Up to two colorization assignments for this object. */
public int zations;
/**
* Convenience constructor.
*/
public ObjectInfo (int tileId, int x, int y)
{
this.tileId = tileId;
this.x = x;
this.y = y;
}
/**
* Creates an object info that is a copy of the supplied info.
*/
public ObjectInfo (ObjectInfo other)
{
this.tileId = other.tileId;
this.x = other.x;
this.y = other.y;
this.priority = other.priority;
this.action = other.action;
this.sx = other.sx;
this.sy = other.sy;
this.sorient = other.sorient;
this.zations = zations;
}
/**
* Zero argument constructor needed for unserialization.
*/
public ObjectInfo ()
{
}
/**
* Returns the primary colorization assignment.
*/
public int getPrimaryZation ()
{
return (zations & 0xFFFF);
}
/**
* Returns the secondary colorization assignment.
*/
public int getSecondaryZation ()
{
return ((zations >> 16) & 0xFFFF);
}
/**
* Sets the primary and secondary colorization assignments.
*/
public void setZations (short primary, short secondary)
{
zations = ((secondary << 16) | primary);
}
/**
* Returns true if this object info contains non-default data for
* anything other than the tile id and coordinates.
*/
public boolean isInteresting ()
{
return (!StringUtil.blank(action) || priority != 0 ||
sx != 0 || sy != 0 || zations != 0);
}
// documentation inherited
public boolean equals (Object other)
{
if (other instanceof ObjectInfo) {
ObjectInfo ooi = (ObjectInfo)other;
return (x == ooi.x && y == ooi.y && tileId == ooi.tileId);
} else {
return false;
}
}
// documentation inherited
public int hashCode ()
{
return x ^ y ^ tileId;
}
}
@@ -1,11 +1,11 @@
//
// $Id: RuntimeMisoScene.java,v 1.1 2002/12/11 23:07:21 shaper Exp $
// $Id: RuntimeMisoScene.java,v 1.2 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.server;
import java.util.Iterator;
import com.threerings.miso.scene.SceneObject;
import com.threerings.miso.data.ObjectInfo;
/**
* The Miso scene interface used by the server to deal with scenes.
@@ -13,8 +13,8 @@ import com.threerings.miso.scene.SceneObject;
public interface RuntimeMisoScene
{
/**
* Iterates over the {@link RuntimeSceneObject} instances representing
* all available objects in the scene.
* Iterates over the {@link ObjectInfo} instances representing all
* "interesting" objects in the scene.
*/
public Iterator enumerateSceneObjects ();
public Iterator enumerateObjects ();
}
@@ -1,13 +1,13 @@
//
// $Id: RuntimeMisoSceneImpl.java,v 1.1 2002/12/11 23:07:21 shaper Exp $
// $Id: RuntimeMisoSceneImpl.java,v 1.2 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.server;
import java.util.ArrayList;
import java.util.Iterator;
import com.threerings.miso.scene.MisoSceneModel;
import com.threerings.miso.scene.SceneObject;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.data.ObjectInfo;
/**
* A basic implementation of the {@link RuntimeMisoScene} interface which
@@ -18,41 +18,22 @@ public class RuntimeMisoSceneImpl
{
/**
* Creates an instance that will obtain data from the supplied scene
* model and place config.
* model.
*/
public RuntimeMisoSceneImpl (MisoSceneModel model)
{
// keep a casted reference to our scene model around
_model = model;
// build a list of all objects in the scene
populateSceneObjects();
}
/**
* Gathers and stores information about all objects in the scene.
*/
protected void populateSceneObjects ()
{
int ocount = _model.objectTileIds.length;
for (int ii = 0; ii < ocount; ii += 3) {
RuntimeSceneObject scobj = new RuntimeSceneObject();
scobj.x = _model.objectTileIds[ii];
scobj.y = _model.objectTileIds[ii+1];
scobj.action = _model.objectActions[ii/3];
_objects.add(scobj);
// stick all of the interesting scene objects into an array list
for (int ii = 0, ll = model.objectInfo.length; ii < ll; ii++) {
_objects.add(model.objectInfo[ii]);
}
}
// documentation inherited
public Iterator enumerateSceneObjects ()
public Iterator enumerateObjects ()
{
return _objects.iterator();
}
/** A casted reference to our scene model. */
protected MisoSceneModel _model;
/** The scene object records. */
/** The object info records. */
protected ArrayList _objects = new ArrayList();
}
@@ -1,46 +0,0 @@
//
// $Id: RuntimeSceneObject.java,v 1.1 2002/12/11 23:07:21 shaper Exp $
package com.threerings.miso.server;
import com.samskivert.util.StringUtil;
/**
* Used to track server-side information about an object in a miso scene.
*/
public class RuntimeSceneObject
{
/** The x and y tile coordinates of the object. */
public int x = -1, y = -1;
/** The action associated with this object or null if it has no
* action. */
public String action;
// documentation inherited
public boolean equals (Object other)
{
if (other instanceof RuntimeSceneObject) {
RuntimeSceneObject oso = (RuntimeSceneObject)other;
// TODO: we should probably check the tile type as well, but
// for now we only differentiate runtime miso scene objects by
// their coordinates within the scene since we don't bother
// keeping around tile information server-side
return (x == oso.x && y == oso.y);
} else {
return false;
}
}
// documentation inherited
public int hashCode ()
{
return x ^ y;
}
/** Generates a string representation of this instance. */
public String toString ()
{
return StringUtil.fieldsToString(this);
}
}
@@ -1,5 +1,5 @@
//
// $Id: AutoFringer.java,v 1.17 2003/01/14 02:50:54 mdb Exp $
// $Id: AutoFringer.java,v 1.18 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.tile;
@@ -36,7 +36,7 @@ import com.threerings.media.image.BackedVolatileMirage;
import com.threerings.media.image.ImageManager;
import com.threerings.media.image.Mirage;
import com.threerings.miso.scene.MisoSceneModel;
import com.threerings.miso.data.MisoSceneModel;
/**
* Automatically fringes a scene according to the rules in the
@@ -1,7 +1,7 @@
//
// $Id: EditableMisoScene.java,v 1.18 2002/09/23 21:54:50 mdb Exp $
// $Id: EditableMisoScene.java,v 1.19 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene.tools;
package com.threerings.miso.tools;
import java.awt.Rectangle;
@@ -9,9 +9,9 @@ import com.threerings.media.tile.ObjectTile;
import com.threerings.media.tile.Tile;
import com.threerings.media.tile.TileUtil;
import com.threerings.miso.scene.DisplayMisoScene;
import com.threerings.miso.scene.MisoSceneModel;
import com.threerings.miso.scene.SceneObject;
import com.threerings.miso.client.DisplayMisoScene;
import com.threerings.miso.client.DisplayObjectInfo;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.tile.BaseTile;
import com.threerings.miso.tile.BaseTileSet;
@@ -70,7 +70,7 @@ public interface EditableMisoScene
*
* @return the new scene object instance.
*/
public SceneObject addSceneObject (
public DisplayObjectInfo addObject (
ObjectTile tile, int x, int y, int fqTileId);
/**
@@ -81,7 +81,7 @@ public interface EditableMisoScene
/**
* Removes the specified object from the scene.
*/
public boolean removeSceneObject (SceneObject scobj);
public boolean removeObject (DisplayObjectInfo scobj);
/**
* Returns a reference to the miso scene model that reflects the
@@ -1,11 +1,12 @@
//
// $Id: EditableMisoSceneImpl.java,v 1.24 2002/09/23 23:07:11 mdb Exp $
// $Id: EditableMisoSceneImpl.java,v 1.25 2003/01/31 23:10:45 mdb Exp $
package com.threerings.miso.scene.tools;
package com.threerings.miso.tools;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -21,10 +22,11 @@ import com.threerings.miso.tile.BaseTile;
import com.threerings.miso.tile.BaseTileSet;
import com.threerings.miso.tile.MisoTileManager;
import com.threerings.miso.scene.DisplayMisoSceneImpl;
import com.threerings.miso.scene.MisoSceneModel;
import com.threerings.miso.scene.SceneObject;
import com.threerings.miso.scene.util.IsoUtil;
import com.threerings.miso.client.DisplayMisoSceneImpl;
import com.threerings.miso.client.DisplayObjectInfo;
import com.threerings.miso.client.util.IsoUtil;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.data.ObjectInfo;
/**
* The default implementation of the {@link EditableMisoScene} interface.
@@ -111,20 +113,22 @@ public class EditableMisoSceneImpl
}
// documentation inherited
public SceneObject addSceneObject (
public DisplayObjectInfo addObject (
ObjectTile tile, int x, int y, int fqTileId)
{
// sanity check
if (x > Short.MAX_VALUE || y > Short.MAX_VALUE ||
x < Short.MIN_VALUE || y < Short.MIN_VALUE) {
throw new IllegalArgumentException(
"Invalid tile coordinates [x=" + x + ", y=" + y + "]");
}
// create a scene object record and add it to the list
EditableSceneObject scobj = (EditableSceneObject)
createSceneObject(x, y, tile);
scobj.fqTileId = fqTileId;
_objects.add(scobj);
DisplayObjectInfo info = new DisplayObjectInfo(fqTileId, x, y);
initObject(info, tile);
_objects.add(info);
// toggle the "covered" flag on in all base tiles below this
// object tile
setObjectTileFootprint(tile, x, y, true);
return scobj;
return info;
}
// documentation inherited
@@ -136,12 +140,12 @@ public class EditableMisoSceneImpl
}
// documentation inherited
public boolean removeSceneObject (SceneObject scobj)
public boolean removeObject (DisplayObjectInfo info)
{
if (_objects.remove(scobj)) {
if (_objects.remove(info)) {
// toggle the "covered" flag off on the base tiles in this object
// tile's footprint
setObjectTileFootprint(scobj.tile, scobj.x, scobj.y, false);
setObjectTileFootprint(info.tile, info.x, info.y, false);
return true;
} else {
return false;
@@ -152,68 +156,26 @@ public class EditableMisoSceneImpl
public MisoSceneModel getMisoSceneModel ()
{
// we need to flush the object layer to the model prior to
// returning it
int ocount = _objects.size();
// but only do it if we've actually got some objects
if (ocount > 0) {
int[] otids = new int[ocount*3];
String[] actions = new String[ocount];
byte[] prios = new byte[ocount];
for (int ii = 0; ii < ocount; ii++) {
EditableSceneObject scobj = (EditableSceneObject)
_objects.get(ii);
otids[3*ii] = scobj.x;
otids[3*ii+1] = scobj.y;
otids[3*ii+2] = scobj.fqTileId;
actions[ii] = scobj.action;
prios[ii] = scobj.priority;
// returning it; first split our objects into two lists
ArrayList ilist = new ArrayList();
ArrayList ulist = new ArrayList();
for (int ii = 0, ll = _objects.size(); ii < ll; ii++) {
ObjectInfo info = (ObjectInfo)_objects.get(ii);
if (info.isInteresting()) {
// convert to a plain object info record
ilist.add(new ObjectInfo(info));
} else {
ulist.add(info);
}
// stuff the new arrays into the model
_model.objectTileIds = otids;
_model.objectActions = actions;
_model.objectPrios = prios;
}
// now populate the scene model appropriately
MisoSceneModel.populateObjects(_model, ilist, ulist);
// and we're ready to roll
return _model;
}
// documentation inherited
protected SceneObject createSceneObject (int x, int y, ObjectTile tile)
{
return new EditableSceneObject(x, y, tile);
}
// documentation inherited
protected SceneObject expandObject (
int col, int row, int tsid, int tid, int fqTid, int objidx)
throws NoSuchTileException, NoSuchTileSetException
{
// do the actual object creation
EditableSceneObject scobj = (EditableSceneObject)
super.expandObject(col, row, tsid, tid, fqTid, objidx);
// we need this to track object layer mods
scobj.fqTileId = fqTid;
// pass on the objecty goodness
return scobj;
}
/** Used to report information on objects in this scene. */
protected static class EditableSceneObject extends SceneObject
{
public int fqTileId;
public EditableSceneObject (int x, int y, ObjectTile tile)
{
super(x, y, tile);
}
}
/** The default tileset with which to fill the base layer. */
protected BaseTileSet _defaultBaseTileSet;
@@ -1,15 +1,16 @@
//
// $Id: MisoSceneParser.java,v 1.2 2002/02/02 01:09:53 mdb Exp $
// $Id: MisoSceneParser.java,v 1.3 2003/01/31 23:10:46 mdb Exp $
package com.threerings.miso.scene.tools.xml;
package com.threerings.miso.tools.xml;
import java.io.IOException;
import java.io.FileInputStream;
import org.xml.sax.SAXException;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.RuleSet;
import com.threerings.miso.scene.MisoSceneModel;
import com.threerings.miso.data.MisoSceneModel;
/**
* A simple class for parsing a standalone miso scene model.
@@ -18,17 +19,34 @@ public class MisoSceneParser
{
/**
* Constructs a miso scene parser that parses scenes with the
* specified XML path prefix. See the {@link
* MisoSceneRuleSet#MisoSceneRuleSet} documentation for more
* specified XML path prefix and a standard scene rule set. See the
* {@link MisoSceneRuleSet#MisoSceneRuleSet} documentation for more
* information.
*/
public MisoSceneParser (String prefix)
{
// create and configure our digester
_digester = new Digester();
MisoSceneRuleSet set = new MisoSceneRuleSet();
set.setPrefix(prefix);
_digester.addRuleSet(set);
init(prefix, set);
}
/**
* Constructs a miso scene parser that parses scenes with the
* specified XML path prefix, using the supplied rule set. The rule
* set should leave a {@link MisoSceneModel} at the top of the
* digester's stack.
*/
public MisoSceneParser (String prefix, RuleSet rules)
{
init(prefix, rules);
}
/** Constructor helper function. */
protected void init (String prefix, RuleSet rules)
{
// create and configure our digester
_digester = new Digester();
_digester.addRuleSet(rules);
_digester.addSetNext(prefix, "setSceneModel",
MisoSceneModel.class.getName());
}
@@ -1,16 +1,20 @@
//
// $Id: MisoSceneRuleSet.java,v 1.11 2002/09/23 23:53:33 mdb Exp $
// $Id: MisoSceneRuleSet.java,v 1.12 2003/01/31 23:10:46 mdb Exp $
package com.threerings.miso.scene.tools.xml;
package com.threerings.miso.tools.xml;
import java.util.ArrayList;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.RuleSetBase;
import com.samskivert.xml.CallMethodSpecialRule;
import com.samskivert.xml.SetFieldRule;
import com.samskivert.xml.SetPropertyFieldsRule;
import com.threerings.miso.Log;
import com.threerings.miso.scene.MisoSceneModel;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.data.ObjectInfo;
/**
* Used to parse a {@link MisoSceneModel} from XML.
@@ -58,31 +62,37 @@ public class MisoSceneRuleSet extends RuleSetBase
new SetFieldRule(digester, "vheight"));
digester.addRule(_prefix + "/base",
new SetFieldRule(digester, "baseTileIds"));
digester.addRule(_prefix + "/object",
new SetFieldRule(digester, "objectTileIds"));
digester.addRule(_prefix + "/actions",
new SetFieldRule(digester, "objectActions"));
digester.addRule(_prefix + "/priorities",
new SetFieldRule(digester, "objectPrios"));
// we have to unfuck the objectActions field in the event that
// there's one object in the objects element which has a blank
// action string (which the parser will parse as a zero length
// array, when we want a length one array with a blank string)
digester.addRule(_prefix, new CallMethodSpecialRule(digester) {
digester.addObjectCreate(_prefix + "/objects",
ArrayList.class.getName());
digester.addObjectCreate(_prefix + "/objects/object",
ObjectInfo.class.getName());
digester.addSetNext(_prefix + "/objects/object", "add",
Object.class.getName());
digester.addRule(_prefix + "/objects/object",
new SetPropertyFieldsRule(digester));
digester.addRule(_prefix + "/objects", new CallMethodSpecialRule(
digester) {
public void parseAndSet (String bodyText, Object target)
throws Exception
{
MisoSceneModel model = (MisoSceneModel)target;
if (model.objectTileIds.length > 0 &&
model.objectActions.length == 0) {
model.objectActions = new String[1];
ArrayList ilist = (ArrayList)target;
ArrayList ulist = new ArrayList();
MisoSceneModel model = (MisoSceneModel)this.digester.peek(1);
// filter interesting and uninteresting into two lists
for (int ii = 0; ii < ilist.size(); ii++) {
ObjectInfo info = (ObjectInfo)ilist.get(ii);
if (!info.isInteresting()) {
ilist.remove(ii--);
ulist.add(info);
}
}
// create our object priorities if we don't have 'em
if (model.objectPrios == null) {
model.objectPrios = new byte[model.objectActions.length];
}
// now populate the model
MisoSceneModel.populateObjects(model, ilist, ulist);
}
});
}
@@ -1,13 +1,16 @@
//
// $Id: MisoSceneWriter.java,v 1.8 2002/09/23 23:07:11 mdb Exp $
// $Id: MisoSceneWriter.java,v 1.9 2003/01/31 23:10:46 mdb Exp $
package com.threerings.miso.scene.tools.xml;
package com.threerings.miso.tools.xml;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import com.megginson.sax.DataWriter;
import com.samskivert.util.StringUtil;
import com.threerings.miso.scene.MisoSceneModel;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.data.ObjectInfo;
/**
* Generates an XML representation of a {@link MisoSceneModel}.
@@ -42,11 +45,53 @@ public class MisoSceneWriter
writer.dataElement("viewheight", Integer.toString(model.vheight));
writer.dataElement("base",
StringUtil.toString(model.baseTileIds, "", ""));
writer.dataElement("object",
StringUtil.toString(model.objectTileIds, "", ""));
writer.dataElement("actions",
StringUtil.joinEscaped(model.objectActions));
writer.dataElement("priorities",
StringUtil.toString(model.objectPrios, "", ""));
// write our uninteresting object tile information
writer.startElement("objects");
for (int ii = 0; ii < model.objectTileIds.length; ii++) {
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute("", "tileId", "", "",
String.valueOf(model.objectTileIds[ii]));
attrs.addAttribute("", "x", "", "",
String.valueOf(model.objectXs[ii]));
attrs.addAttribute("", "y", "", "",
String.valueOf(model.objectYs[ii]));
writer.emptyElement("", "object", "", attrs);
}
// write our uninteresting object tile information
for (int ii = 0; ii < model.objectInfo.length; ii++) {
ObjectInfo info = model.objectInfo[ii];
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute("", "tileId", "", "",
String.valueOf(info.tileId));
attrs.addAttribute("", "x", "", "", String.valueOf(info.x));
attrs.addAttribute("", "y", "", "", String.valueOf(info.y));
if (!StringUtil.blank(info.action)) {
attrs.addAttribute("", "action", "", "", info.action);
}
if (info.priority != 0) {
attrs.addAttribute("", "priority", "", "",
String.valueOf(info.priority));
}
if (info.sx != 0 || info.sy != 0) {
attrs.addAttribute("", "sx", "", "",
String.valueOf(info.sx));
attrs.addAttribute("", "sy", "", "",
String.valueOf(info.sy));
attrs.addAttribute("", "sorient", "", "",
String.valueOf(info.sorient));
}
if (info.zations != 0) {
attrs.addAttribute("", "zations", "", "",
String.valueOf(info.zations));
}
writer.emptyElement("", "object", "", attrs);
}
writer.endElement("objects");
}
}
@@ -1,5 +1,5 @@
//
// $Id: SpotSceneManager.java,v 1.23 2003/01/18 22:59:17 mdb Exp $
// $Id: SpotSceneManager.java,v 1.24 2003/01/31 23:10:46 mdb Exp $
package com.threerings.whirled.spot.server;
@@ -41,12 +41,12 @@ public class SpotSceneManager extends SceneManager
SpotSceneManager mgr = (SpotSceneManager)
CrowdServer.plreg.getPlaceManager(body.location);
if (mgr != null) {
SpotSceneModel model = (SpotSceneModel) mgr.getSceneModel();
RuntimeSpotScene scene = (RuntimeSpotScene)mgr.getScene();
try {
mgr.handleChangeLocRequest(body, model.defaultEntranceId);
mgr.handleChangeLocRequest(body, scene.getDefaultEntranceId());
} catch (InvocationException ie) {
Log.warning("Could not walk user to default portal [error=" +
ie + "].");
Log.warning("Could not walk user to default portal " +
"[error=" + ie + "].");
}
}
}
@@ -1,5 +1,5 @@
//
// $Id: EditableSpotSceneImpl.java,v 1.10 2001/12/16 21:22:31 mdb Exp $
// $Id: EditableSpotSceneImpl.java,v 1.11 2003/01/31 23:10:46 mdb Exp $
package com.threerings.whirled.tools.spot;
@@ -201,6 +201,8 @@ public class EditableSpotSceneImpl extends EditableSceneImpl
*/
protected void flushToModel ()
{
super.flushToModel();
List locations = _delegate.getLocations();
// flush the locations
@@ -1,5 +1,5 @@
//
// $Id: EditableSceneImpl.java,v 1.6 2001/12/12 19:06:15 mdb Exp $
// $Id: EditableSceneImpl.java,v 1.7 2003/01/31 23:10:46 mdb Exp $
package com.threerings.whirled.tools;
@@ -121,9 +121,18 @@ public class EditableSceneImpl implements EditableScene
// documentation inherited
public EditableSceneModel getSceneModel ()
{
flushToModel();
return _emodel;
}
/**
* Derived classes should override this method and flush any editable
* modifications to the scene model when this method is called.
*/
protected void flushToModel ()
{
}
/** A reference to our scene model. */
protected SceneModel _model;