Oh the vast sweeping changes, and they're not even close to complete, but
things compile and most things run so this is a good time to checkpoint. Let me recall: - Refactored the whole scene deal. - Revamped the XML parser stuff (now uses Digester). - Rethought the tile management. - Started tile bundle stuff. - Wrote some tests. - Did a bit of Mike-ification. Onward and moreward. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@621 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,74 +1,100 @@
|
||||
//
|
||||
// $Id: EditableMisoScene.java,v 1.4 2001/10/17 22:21:22 shaper Exp $
|
||||
// $Id: EditableMisoScene.java,v 1.5 2001/11/18 04:09:23 mdb Exp $
|
||||
|
||||
package com.threerings.miso.scene;
|
||||
package com.threerings.miso.tools;
|
||||
|
||||
import com.threerings.media.tile.ObjectTile;
|
||||
import com.threerings.media.tile.Tile;
|
||||
|
||||
import com.threerings.miso.tile.MisoTile;
|
||||
import com.threerings.miso.scene.DisplayMisoScene;
|
||||
import com.threerings.miso.scene.MisoSceneModel;
|
||||
|
||||
/**
|
||||
* The editable Miso scene interface provides the means for modifying a
|
||||
* Miso scene which is needed by things like the scene editor. This is
|
||||
* separated from the read-only interface to avoid implying to users of
|
||||
* the Miso scene interface that editing scenes is a safe thing to do. In
|
||||
* fact it should only be done under special circumstances.
|
||||
* The editable Miso scene interface is used in the offline scene building
|
||||
* tools as well as by the tools that load those prototype scenes into the
|
||||
* runtime database. Accordingly, it provides a means for modifying scene
|
||||
* values and for obtaining access to the underlying scene models that
|
||||
* represent the underlying scene information.
|
||||
*
|
||||
* @see DisplayMisoScene
|
||||
*/
|
||||
public interface EditableMisoScene
|
||||
extends MisoScene
|
||||
extends DisplayMisoScene
|
||||
{
|
||||
/**
|
||||
* Updates the scene's unique identifier.
|
||||
* Returns the default base tile.
|
||||
*/
|
||||
public void setId (int sceneId);
|
||||
public MisoTile getDefaultBaseTile ();
|
||||
|
||||
/**
|
||||
* Updates the scene's name.
|
||||
*/
|
||||
public void setName (String name);
|
||||
|
||||
/**
|
||||
* Updates the scene's default tile.
|
||||
*/
|
||||
public void setDefaultTile (MisoTile tile);
|
||||
|
||||
/**
|
||||
* Updates the specified tile in the scene.
|
||||
*/
|
||||
public void setTile (int lnum, int x, int y, Tile tile);
|
||||
|
||||
/**
|
||||
* Set the default entrance portal for this scene.
|
||||
* Sets the default base tile.
|
||||
*
|
||||
* @param entrance the entrance portal.
|
||||
* @param defaultBaseTile the new default base tile.
|
||||
* @param fqTileId the fully-qualified tile id (@see
|
||||
* com.threerings.media.tile.TileUtil#getFQTileId}) of the new default
|
||||
* base tile.
|
||||
*/
|
||||
public void setEntrance (Portal entrance);
|
||||
public void setDefaultBaseTile (MisoTile defaultBaseTile, int fqTileId);
|
||||
|
||||
/**
|
||||
* Update the specified location in the scene. If the cluster
|
||||
* index number is -1, the location will be removed from any
|
||||
* cluster it may reside in.
|
||||
* Updates the tile at the specified location in the base layer.
|
||||
*
|
||||
* @param loc the location.
|
||||
* @param clusteridx the cluster index number.
|
||||
* @param x the x-coordinate of the tile to set.
|
||||
* @param y the y-coordinate of the tile to set.
|
||||
* @param tile the tile to set.
|
||||
* @param fqTileId the fully-qualified tile id (@see
|
||||
* com.threerings.media.tile.TileUtil#getFQTileId}) of the new default
|
||||
* base tile.
|
||||
*/
|
||||
public void updateLocation (Location loc, int clusteridx);
|
||||
public void setBaseTile (int x, int y, MisoTile tile, int fqTileId);
|
||||
|
||||
/**
|
||||
* Add the specified portal to the scene. Adds the portal to the
|
||||
* location list as well if it's not already present and removes
|
||||
* it from any cluster it may reside in.
|
||||
* Updates the tile at the specified location in the fringe layer.
|
||||
*
|
||||
* @param portal the portal.
|
||||
* @param x the x-coordinate of the tile to set.
|
||||
* @param y the y-coordinate of the tile to set.
|
||||
* @param tile the tile to set.
|
||||
* @param fqTileId the fully-qualified tile id (@see
|
||||
* com.threerings.media.tile.TileUtil#getFQTileId}) of the new default
|
||||
* base tile.
|
||||
*/
|
||||
public void addPortal (Portal portal);
|
||||
public void setFringeTile (int x, int y, Tile tile, int fqTileId);
|
||||
|
||||
/**
|
||||
* Remove the given location object from the location list, and
|
||||
* from any containing cluster. If the location is a portal, it
|
||||
* is removed from the portal list as well.
|
||||
* Updates the tile at the specified location in the object layer. Any
|
||||
* previous object tile at that location should be cleared out by the
|
||||
* implementation of this method before the new tile is set to ensure
|
||||
* that footprint tiles associated with the old object are properly
|
||||
* disposed of.
|
||||
*
|
||||
* @param loc the location object.
|
||||
* @param x the x-coordinate of the tile to set.
|
||||
* @param y the y-coordinate of the tile to set.
|
||||
* @param tile the tile to set.
|
||||
* @param fqTileId the fully-qualified tile id (@see
|
||||
* com.threerings.media.tile.TileUtil#getFQTileId}) of the new default
|
||||
* base tile.
|
||||
*/
|
||||
public void removeLocation (Location loc);
|
||||
public void setObjectTile (int x, int y, ObjectTile tile, int fqTileId);
|
||||
|
||||
/**
|
||||
* Clears out the tile at the specified location in the base layer.
|
||||
*/
|
||||
public void clearBaseTile (int x, int y);
|
||||
|
||||
/**
|
||||
* Clears out the tile at the specified location in the fringe layer.
|
||||
*/
|
||||
public void clearFringeTile (int x, int y);
|
||||
|
||||
/**
|
||||
* Clears out the tile at the specified location in the object layer.
|
||||
*/
|
||||
public void clearObjectTile (int x, int y);
|
||||
|
||||
/**
|
||||
* Returns a reference to the miso scene model that reflects the
|
||||
* changes that have been made to this editable miso scene.
|
||||
*/
|
||||
public MisoSceneModel getModel ();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// $Id: EditableMisoSceneImpl.java,v 1.1 2001/11/18 04:09:23 mdb Exp $
|
||||
|
||||
package com.threerings.miso.tools;
|
||||
|
||||
import com.threerings.media.tile.NoSuchTileException;
|
||||
import com.threerings.media.tile.NoSuchTileSetException;
|
||||
import com.threerings.media.tile.ObjectTile;
|
||||
import com.threerings.media.tile.Tile;
|
||||
import com.threerings.media.tile.TileManager;
|
||||
|
||||
import com.threerings.miso.tile.MisoTile;
|
||||
|
||||
import com.threerings.miso.scene.DisplayMisoSceneImpl;
|
||||
import com.threerings.miso.scene.MisoSceneModel;
|
||||
|
||||
/**
|
||||
* The default implementation of the {@link EditableMisoScene} interface.
|
||||
*/
|
||||
public class EditableMisoSceneImpl
|
||||
extends DisplayMisoSceneImpl implements EditableMisoScene
|
||||
{
|
||||
/**
|
||||
* Constructs an instance that will be used to display and edit the
|
||||
* supplied miso scene data. The tiles identified by the scene model
|
||||
* will be loaded via the supplied tile manager.
|
||||
*
|
||||
* @param model the scene data that we'll be displaying.
|
||||
* @param tmgr the tile manager from which to load our tiles.
|
||||
*
|
||||
* @exception NoSuchTileException thrown if the model references a
|
||||
* tile which is not available via the supplied tile manager.
|
||||
*/
|
||||
public EditableMisoSceneImpl (MisoSceneModel model, TileManager tmgr)
|
||||
throws NoSuchTileException, NoSuchTileSetException
|
||||
{
|
||||
super(model, tmgr);
|
||||
|
||||
// we'll need to be keeping this
|
||||
_model = model;
|
||||
|
||||
// we need this to track object layer mods
|
||||
_objectTileIds = new int[_model.baseTileIds.length];
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public MisoTile getDefaultBaseTile ()
|
||||
{
|
||||
return _defaultBaseTile;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setDefaultBaseTile (MisoTile defaultBaseTile, int fqTileId)
|
||||
{
|
||||
_defaultBaseTile = defaultBaseTile;
|
||||
_defaultBaseTileId = fqTileId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setBaseTile (int x, int y, MisoTile tile, int fqTileId)
|
||||
{
|
||||
_base.setTile(x, y, tile);
|
||||
// update the model as well
|
||||
_model.baseTileIds[_model.width*y + x] = fqTileId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setFringeTile (int x, int y, Tile tile, int fqTileId)
|
||||
{
|
||||
_fringe.setTile(x, y, tile);
|
||||
// update the model as well
|
||||
_model.fringeTileIds[_model.width*y + x] = fqTileId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void setObjectTile (int x, int y, ObjectTile tile, int fqTileId)
|
||||
{
|
||||
ObjectTile prev = _object.getTile(x, y);
|
||||
// clear out any previous tile so that shadow tiles are properly
|
||||
// removed
|
||||
if (prev != null) {
|
||||
clearObjectTile(x, y);
|
||||
}
|
||||
_object.setTile(x, y, tile);
|
||||
// stick this value into our non-sparse object layer
|
||||
_objectTileIds[_model.width*y + x] = fqTileId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clearBaseTile (int x, int y)
|
||||
{
|
||||
_base.setTile(x, y, _defaultBaseTile);
|
||||
// clear it out in the model
|
||||
_model.baseTileIds[_model.width*y + x] = _defaultBaseTileId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clearFringeTile (int x, int y)
|
||||
{
|
||||
_fringe.setTile(x, y, null);
|
||||
// clear it out in the model
|
||||
_model.fringeTileIds[_model.width*y + x] = 0;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clearObjectTile (int x, int y)
|
||||
{
|
||||
setObjectTileFootprint(x, y, _defaultBaseTile);
|
||||
// clear it out in our non-sparse array
|
||||
_objectTileIds[_model.width*y + x] = 0;
|
||||
// we don't have to worry about setting the footprint in the model
|
||||
// because footprints are always inferred from the contents of the
|
||||
// object layer and the base layer in the model can simply contain
|
||||
// the default tiles
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public MisoSceneModel getModel ()
|
||||
{
|
||||
// we need to flush the object layer to the model prior to
|
||||
// returning it
|
||||
|
||||
return _model;
|
||||
}
|
||||
|
||||
/** Our scene model, which we always keep in sync with our display
|
||||
* model data. */
|
||||
protected MisoSceneModel _model;
|
||||
|
||||
/** A non-sparse array where we can keep track of the object tile
|
||||
* ids. */
|
||||
protected int[] _objectTileIds;
|
||||
|
||||
/** The default tile with which to fill the base layer. */
|
||||
protected MisoTile _defaultBaseTile;
|
||||
|
||||
/** The fully qualified tile id of the default base tile. */
|
||||
protected int _defaultBaseTileId;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// $Id: MisoSceneRuleSet.java,v 1.1 2001/11/18 04:09:22 mdb Exp $
|
||||
|
||||
package com.threerings.media.tile.xml;
|
||||
|
||||
import org.apache.commons.digester.Digester;
|
||||
import org.apache.commons.digester.RuleSetBase;
|
||||
|
||||
import com.samskivert.xml.SetFieldRule;
|
||||
|
||||
import com.threerings.miso.scene.MisoSceneModel;
|
||||
|
||||
/**
|
||||
* Used to parse a {@link MisoSceneModel} from XML.
|
||||
*/
|
||||
public abstract class MisoSceneRuleSet extends RuleSetBase
|
||||
{
|
||||
/**
|
||||
* Constructs a miso scene rule set which will match scenes with the
|
||||
* supplied prefix. For example, passing <code>scene.miso</code> will
|
||||
* match the scene in the following XML file:
|
||||
*
|
||||
* <pre>
|
||||
* <scene>
|
||||
* <miso>
|
||||
* <width>50</width>
|
||||
* <height>50</height>
|
||||
* <!-- ... -->
|
||||
* </miso>
|
||||
* </scene>
|
||||
* </pre>
|
||||
*/
|
||||
public MisoSceneRuleSet (String prefix)
|
||||
{
|
||||
_prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the necessary rules to the digester to parse our miso scene
|
||||
* data.
|
||||
*/
|
||||
public void addRuleInstances (Digester digester)
|
||||
{
|
||||
// this creates the appropriate instance when we encounter our
|
||||
// prefix tag
|
||||
digester.addObjectCreate(_prefix, MisoSceneModel.class.getName());
|
||||
|
||||
// set up rules to parse and set our fields
|
||||
digester.addRule(_prefix + "/width",
|
||||
new SetFieldRule(digester, "width"));
|
||||
digester.addRule(_prefix + "/height",
|
||||
new SetFieldRule(digester, "height"));
|
||||
digester.addRule(_prefix + "/base",
|
||||
new SetFieldRule(digester, "baseTileIds"));
|
||||
digester.addRule(_prefix + "/fringe",
|
||||
new SetFieldRule(digester, "fringeTileIds"));
|
||||
digester.addRule(_prefix + "/object",
|
||||
new SetFieldRule(digester, "objectTileIds"));
|
||||
}
|
||||
|
||||
/** The prefix at which me match our scenes. */
|
||||
protected String _prefix;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $Id: MisoSceneWriter.java,v 1.1 2001/11/18 04:09:22 mdb Exp $
|
||||
|
||||
package com.threerings.miso.scene.xml;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import com.megginson.sax.DataWriter;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.threerings.miso.scene.MisoSceneModel;
|
||||
|
||||
/**
|
||||
* Generates an XML representation of a {@link MisoSceneModel}.
|
||||
*/
|
||||
public class MisoSceneWriter
|
||||
{
|
||||
/**
|
||||
* Writes the data for the supplied {@link MisoSceneModel} to the XML
|
||||
* writer supplied. The writer will already be configured with the
|
||||
* appropriate indentation level so that this writer can simply output
|
||||
* its elements and allow the calling code to determine where in the
|
||||
* greater scene description file the miso data should live.
|
||||
*/
|
||||
public void writeScene (MisoSceneModel model, DataWriter writer)
|
||||
throws SAXException
|
||||
{
|
||||
writer.startElement("miso");
|
||||
writer.dataElement("width", Integer.toString(model.width));
|
||||
writer.dataElement("height", Integer.toString(model.height));
|
||||
writer.dataElement("base", StringUtil.toString(model.baseTileIds));
|
||||
writer.dataElement("fringe", StringUtil.toString(model.fringeTileIds));
|
||||
writer.dataElement("object", StringUtil.toString(model.objectTileIds));
|
||||
writer.endElement("miso");
|
||||
}
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
//
|
||||
// $Id: XMLSceneGroupParser.java,v 1.8 2001/11/12 20:56:55 mdb Exp $
|
||||
|
||||
package com.threerings.miso.scene.xml;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.xml.sax.*;
|
||||
|
||||
import com.samskivert.util.*;
|
||||
import com.samskivert.xml.SimpleParser;
|
||||
|
||||
import com.threerings.miso.Log;
|
||||
import com.threerings.miso.scene.*;
|
||||
import com.threerings.miso.scene.util.MisoSceneUtil;
|
||||
|
||||
/**
|
||||
* Parses an XML scene group description file, loads the referenced
|
||||
* scenes into the runtime scene repository, and creates bindings
|
||||
* between the portals in the scenes. Does not currently perform
|
||||
* validation on the input XML stream, though the parsing code assumes
|
||||
* the XML document is well-formed.
|
||||
*/
|
||||
public class XMLSceneGroupParser extends SimpleParser
|
||||
{
|
||||
// documentation inherited
|
||||
public void startElement (
|
||||
String uri, String localName, String qName, Attributes attributes)
|
||||
{
|
||||
if (qName.equals("scene")) {
|
||||
// construct a new scene info object
|
||||
_info.curscene = new SceneInfo(attributes.getValue("src"));
|
||||
|
||||
// add it to the list of scene info objects
|
||||
_info.sceneinfo.add(_info.curscene);
|
||||
|
||||
} else if (qName.equals("portal")) {
|
||||
// pull out the portal data
|
||||
String src = attributes.getValue("src");
|
||||
String destScene = attributes.getValue("destscene");
|
||||
String dest = attributes.getValue("dest");
|
||||
|
||||
// construct a new portal info object
|
||||
PortalInfo pinfo = new PortalInfo(src, destScene, dest);
|
||||
|
||||
// add it to the current scene's list of portal info objects
|
||||
_info.curscene.portals.add(pinfo);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void finishElement (
|
||||
String uri, String localName, String qName, String data)
|
||||
{
|
||||
if (qName.equals("name")) {
|
||||
_info.curscene.name = data;
|
||||
|
||||
} else if (qName.equals("entrance")) {
|
||||
_info.curscene.entrance = data;
|
||||
|
||||
} else if (qName.equals("scene")) {
|
||||
// TODO: load scene from scene repository and set
|
||||
// _info.curscene.scene to the resulting scene object
|
||||
|
||||
} else if (qName.equals("scenegroup")) {
|
||||
// now that we've obtained all scene info and fully loaded
|
||||
// the associated scene objects, resolve bindings between
|
||||
// all scenes in the group.
|
||||
_info.resolveBindings();
|
||||
|
||||
// warn about any remaining un-bound portals
|
||||
_info.checkUnboundPortals();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified XML file and return a list of miso scene
|
||||
* objects that have been fully bound and loaded into the scene
|
||||
* repository.
|
||||
*
|
||||
* @param fname the file name.
|
||||
*
|
||||
* @return the list of scene objects, or null if an error occurred.
|
||||
*/
|
||||
public List loadSceneGroup (String fname) throws IOException
|
||||
{
|
||||
_info = new SceneGroupInfo();
|
||||
parseFile(fname);
|
||||
return _info.getScenes();
|
||||
}
|
||||
|
||||
/** The scene group info gathered while parsing. */
|
||||
protected SceneGroupInfo _info;
|
||||
|
||||
/**
|
||||
* A class to hold information on the overall scene group while
|
||||
* parsing, as well as the resulting list of scene objects
|
||||
* produced when finished.
|
||||
*/
|
||||
class SceneGroupInfo
|
||||
{
|
||||
/** The scene info for all scenes described in the group. */
|
||||
public ArrayList sceneinfo;
|
||||
|
||||
/** The current scene info. */
|
||||
public SceneInfo curscene;
|
||||
|
||||
public SceneGroupInfo ()
|
||||
{
|
||||
sceneinfo = new ArrayList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of the scene objects contained within all
|
||||
* scene info objects. Intended to be called once all parsing
|
||||
* and resolving of portal bindings has been completed.
|
||||
*/
|
||||
public List getScenes ()
|
||||
{
|
||||
ArrayList scenes = new ArrayList();
|
||||
int size = sceneinfo.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
scenes.add(((SceneInfo)sceneinfo.get(ii)).scene);
|
||||
}
|
||||
return scenes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scene object associated with the named scene
|
||||
* info object.
|
||||
*
|
||||
* @param name the scene info name.
|
||||
*
|
||||
* @return the scene object or null if the scene info object
|
||||
* isn't found or has no scene object.
|
||||
*/
|
||||
public MisoScene getScene (String name)
|
||||
{
|
||||
int size = sceneinfo.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
SceneInfo sinfo = (SceneInfo)sceneinfo.get(ii);
|
||||
if (sinfo.name.equals(name)) return sinfo.scene;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the portal bindings and entrance portal for all scenes.
|
||||
*/
|
||||
public void resolveBindings ()
|
||||
{
|
||||
int size = sceneinfo.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
// retrieve the next scene info object
|
||||
SceneInfo sinfo = (SceneInfo)sceneinfo.get(ii);
|
||||
|
||||
int psize = sinfo.portals.size();
|
||||
for (int jj = 0; jj < psize; jj++) {
|
||||
// retrieve the next portal info object
|
||||
PortalInfo pinfo = (PortalInfo)sinfo.portals.get(jj);
|
||||
|
||||
// resolve the portal binding
|
||||
resolvePortal(sinfo, pinfo);
|
||||
|
||||
// resolve the entrance portal
|
||||
resolveEntrance(sinfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the binding for the portal in the given scene.
|
||||
*
|
||||
* @param sinfo the scene info.
|
||||
* @param pinfo the portal info.
|
||||
*/
|
||||
protected void resolvePortal (SceneInfo sinfo, PortalInfo pinfo)
|
||||
{
|
||||
// get the source portal object
|
||||
Portal src = MisoSceneUtil.getPortal(sinfo.scene, pinfo.src);
|
||||
if (src == null) {
|
||||
Log.warning("Missing source portal [scene=" + sinfo.name +
|
||||
", pinfo=" + pinfo + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// get the destination scene
|
||||
MisoScene destScene = getScene(pinfo.destScene);
|
||||
if (destScene == null) {
|
||||
Log.warning("Missing destination scene [scene=" + sinfo.name +
|
||||
", pinfo=" + pinfo + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// get the destination portal object
|
||||
Portal dest = MisoSceneUtil.getPortal(destScene, pinfo.dest);
|
||||
if (dest == null) {
|
||||
Log.warning("Missing destination portal [scene=" + sinfo.name +
|
||||
", pinfo=" + pinfo + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// update source portal with full destination information
|
||||
src.setDestination(destScene.getId(), dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the binding for the entrance portal in the given scene.
|
||||
*
|
||||
* @param sinfo the scene info.
|
||||
*/
|
||||
protected void resolveEntrance (SceneInfo sinfo)
|
||||
{
|
||||
Portal entrance = MisoSceneUtil.getPortal(
|
||||
sinfo.scene, sinfo.entrance);
|
||||
if (entrance == null) {
|
||||
Log.warning( "Missing entrance portal [scene=" + sinfo.name +
|
||||
", entrance=" + sinfo.entrance + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
sinfo.scene.setEntrance(entrance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan through all scenes and output a warning message if any
|
||||
* portals are found that aren't bound to a destination
|
||||
* portal. Intended for calling after {@link
|
||||
* #resolveBindings} is called to make sure the scene group
|
||||
* description wasn't lacking a binding for some portal; or,
|
||||
* that the scenes don't contain any unintended or unnecessary
|
||||
* portals.
|
||||
*/
|
||||
public void checkUnboundPortals ()
|
||||
{
|
||||
int size = sceneinfo.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
// retrieve the next scene info object
|
||||
SceneInfo sinfo = (SceneInfo)sceneinfo.get(ii);
|
||||
|
||||
// get the portals in the scene
|
||||
List portals = sinfo.scene.getPortals();
|
||||
|
||||
// check each portal to make sure it has a valid destination
|
||||
int psize = portals.size();
|
||||
for (int jj = 0; jj < size; jj++) {
|
||||
Portal portal = (Portal)portals.get(jj);
|
||||
if (!portal.hasDestination()) {
|
||||
Log.warning("Unbound portal [scene=" + sinfo.name +
|
||||
", portal=" + portal + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to hold information on a single scene's bindings.
|
||||
*/
|
||||
class SceneInfo
|
||||
{
|
||||
/** The logical scene name. */
|
||||
public String name;
|
||||
|
||||
/** The scene description file path. */
|
||||
public String src;
|
||||
|
||||
/** The default scene entrance. */
|
||||
public String entrance;
|
||||
|
||||
/** The list of portal info objects describing portal bindings. */
|
||||
public ArrayList portals;
|
||||
|
||||
/** The scene object obtained from the scene repository. */
|
||||
public MisoSceneImpl scene;
|
||||
|
||||
public SceneInfo (String src)
|
||||
{
|
||||
this.src = src;
|
||||
portals = new ArrayList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to hold information on a single portal's bindings.
|
||||
*/
|
||||
class PortalInfo
|
||||
{
|
||||
/** The source portal name. */
|
||||
public String src;
|
||||
|
||||
/** The destination portal name within the destination scene. */
|
||||
public String dest;
|
||||
|
||||
/** The logical destination scene name. */
|
||||
public String destScene;
|
||||
|
||||
public PortalInfo (String src, String destScene, String dest)
|
||||
{
|
||||
this.src = src;
|
||||
this.destScene = destScene;
|
||||
this.dest = dest;
|
||||
}
|
||||
|
||||
public String toString ()
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
buf.append("[src=").append(src);
|
||||
buf.append(", dest=").append(dest);
|
||||
buf.append(", destScene=").append(destScene);
|
||||
return buf.append("]").toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
//
|
||||
// $Id: XMLSceneParser.java,v 1.24 2001/11/08 03:04:44 mdb Exp $
|
||||
|
||||
package com.threerings.miso.scene.xml;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.xml.sax.*;
|
||||
|
||||
import com.samskivert.util.*;
|
||||
import com.samskivert.xml.SimpleParser;
|
||||
|
||||
import com.threerings.media.tile.*;
|
||||
|
||||
import com.threerings.miso.Log;
|
||||
import com.threerings.miso.scene.*;
|
||||
import com.threerings.miso.tile.MisoTile;
|
||||
|
||||
/**
|
||||
* Parse an XML scene description file and construct a scene object.
|
||||
* Does not currently perform validation on the input XML stream,
|
||||
* though the parsing code assumes the XML document is well-formed.
|
||||
*
|
||||
* @see XMLSceneWriter
|
||||
*/
|
||||
public class XMLSceneParser extends SimpleParser
|
||||
{
|
||||
public XMLSceneParser (IsoSceneViewModel model, TileManager tilemgr)
|
||||
{
|
||||
_model = model;
|
||||
_tilemgr = tilemgr;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void startElement (
|
||||
String uri, String localName, String qName, Attributes attributes)
|
||||
{
|
||||
if (qName.equals("layer")) {
|
||||
_info.lnum = parseInt(attributes.getValue("lnum"));
|
||||
|
||||
} else if (qName.equals("row")) {
|
||||
_info.rownum = parseInt(attributes.getValue("rownum"));
|
||||
_info.colstart = parseInt(attributes.getValue("colstart"));
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void finishElement (
|
||||
String uri, String localName, String qName, String data)
|
||||
{
|
||||
if (qName.equals("name")) {
|
||||
_info.scene.name = data;
|
||||
|
||||
} else if (qName.equals("version")) {
|
||||
int version = parseInt(data);
|
||||
if (version < 0 || version > XMLSceneVersion.VERSION) {
|
||||
Log.warning(
|
||||
"Unrecognized scene file format version, will attempt " +
|
||||
"to continue parsing file but your mileage may vary " +
|
||||
"[version=" + version +
|
||||
", known_version=" + XMLSceneVersion.VERSION + "].");
|
||||
}
|
||||
|
||||
} else if (qName.equals("locations")) {
|
||||
int vals[] = StringUtil.parseIntArray(data);
|
||||
addLocations(_info.scene.locations, vals);
|
||||
|
||||
} else if (qName.equals("cluster")) {
|
||||
int vals[] = StringUtil.parseIntArray(data);
|
||||
_info.scene.clusters.add(toCluster(_info.scene.locations, vals));
|
||||
|
||||
} else if (qName.equals("portals")) {
|
||||
String vals[] = StringUtil.parseStringArray(data);
|
||||
addPortals(_info.scene.portals, _info.scene.locations, vals);
|
||||
|
||||
} else if (qName.equals("entrance")) {
|
||||
_info.scene.entrance = getEntrancePortal(data);
|
||||
|
||||
} else if (qName.equals("row")) {
|
||||
addTileRow(_info, data);
|
||||
|
||||
} else if (qName.equals("scene")) {
|
||||
// nothing for now
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the tiles described by the given data to the scene.
|
||||
*/
|
||||
protected void addTileRow (SceneInfo info, String data)
|
||||
{
|
||||
try {
|
||||
if (info.lnum == MisoScene.LAYER_BASE) {
|
||||
readRowData(info, data);
|
||||
} else {
|
||||
readSparseRowData(info, data);
|
||||
}
|
||||
|
||||
} catch (TileException te) {
|
||||
Log.warning("Exception reading scene tile data " +
|
||||
"[te=" + te + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string of comma-delimited tuples as (tileset id, tile
|
||||
* id), populate the scene info tile array with tiles to suit.
|
||||
*
|
||||
* @param info the scene info.
|
||||
* @param data the tile data.
|
||||
*/
|
||||
protected void readRowData (SceneInfo info, String data)
|
||||
throws TileException
|
||||
{
|
||||
int[] vals = StringUtil.parseIntArray(data);
|
||||
|
||||
// make sure we have a suitable number of tiles
|
||||
int validLen = _model.scenewid * 2;
|
||||
if (vals.length != validLen) {
|
||||
Log.warning(
|
||||
"Invalid number of tiles in full row data set, skipping set " +
|
||||
"[rownum=" + info.rownum + ", len=" + vals.length +
|
||||
", valid_len=" + validLen + ", data=" + data + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// create the tile objects in the tile array
|
||||
Tile[][] tiles = info.scene.getTiles(info.lnum);
|
||||
for (int xx = 0; xx < vals.length; xx += 2) {
|
||||
Tile tile = _tilemgr.getTile(vals[xx], vals[xx + 1]);
|
||||
tiles[xx / 2][info.rownum] = tile;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string of comma-delimited tuples as (tileset id, tile
|
||||
* id) and having previously set up the scene info object's
|
||||
* <code>rownum</code> and <code>colstart</code> member data by
|
||||
* retrieving the attribute values when the <code>row</code>
|
||||
* element tag was noted, this method then proceeds to populate
|
||||
* the info object's tile array with tiles to suit.
|
||||
*
|
||||
* @param info the scene info.
|
||||
* @param data the tile data.
|
||||
*/
|
||||
protected void readSparseRowData (SceneInfo info, String data)
|
||||
throws TileException
|
||||
{
|
||||
int[] vals = StringUtil.parseIntArray(data);
|
||||
|
||||
// make sure we have a suitable number of tiles
|
||||
if ((vals.length % 2) == 1) {
|
||||
Log.warning(
|
||||
"Odd number of tiles in sparse row data set, skipping set " +
|
||||
"[rownum=" + info.rownum + ", colstart=" + info.colstart +
|
||||
", len=" + vals.length + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// create the tile objects in the tile array
|
||||
Tile[][] tiles = info.scene.getTiles(info.lnum);
|
||||
for (int xx = 0; xx < vals.length; xx += 2) {
|
||||
Tile tile = _tilemgr.getTile(vals[xx], vals[xx + 1]);
|
||||
int xidx = info.colstart + (xx / 2);
|
||||
tiles[xidx][info.rownum] = tile;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of integer values, return a <code>Cluster</code>
|
||||
* object containing the location objects identified by location
|
||||
* index number in the integer array.
|
||||
*
|
||||
* @param locs the locations list.
|
||||
* @param vals the integer values.
|
||||
*
|
||||
* @return the cluster object.
|
||||
*/
|
||||
protected Cluster toCluster (ArrayList locs, int[] vals)
|
||||
{
|
||||
Cluster cluster = new Cluster();
|
||||
for (int ii = 0; ii < vals.length; ii++) {
|
||||
cluster.add((Location)locs.get(vals[ii]));
|
||||
}
|
||||
return cluster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of integer values, add the <code>Location</code>
|
||||
* objects represented therein to the given list, constructed from
|
||||
* each successive triplet of values as (x, y, orientation) in the
|
||||
* integer array.
|
||||
*
|
||||
* @param vals the integer values.
|
||||
*/
|
||||
protected void addLocations (ArrayList list, int[] vals)
|
||||
{
|
||||
// make sure we have a seemingly-appropriate number of points
|
||||
if ((vals.length % 3) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// read in all of the locations and add to the list
|
||||
for (int ii = 0; ii < vals.length; ii += 3) {
|
||||
Location loc = new Location(
|
||||
vals[ii], vals[ii+1], vals[ii+2]);
|
||||
list.add(loc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of string values, add the <code>Portal</code>
|
||||
* objects constructed from each successive triplet of values as
|
||||
* (locidx, portal name) in the array to the given portal list.
|
||||
* The list of <code>Location</code> objects must have already
|
||||
* been fully read previously.
|
||||
*
|
||||
* <p> This is something of a hack since we perhaps ought to parse
|
||||
* the original String into its constituent components ourselves,
|
||||
* but I'm unable to restrain myself from using the handy
|
||||
* <code>StringUtil.toString()</code> method to take care of
|
||||
* tokenizing things for us, so, there you have it.
|
||||
*
|
||||
* @param portals the portal list.
|
||||
* @param locs the location list.
|
||||
* @param vals the String values.
|
||||
*/
|
||||
protected void addPortals (
|
||||
ArrayList portals, ArrayList locs, String[] vals)
|
||||
{
|
||||
// make sure we have an appropriate number of values
|
||||
if ((vals.length % 2) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// read in all of the portals
|
||||
for (int ii = 0; ii < vals.length; ii += 2) {
|
||||
int locidx = parseInt(vals[ii]);
|
||||
|
||||
// create the portal and add to the list
|
||||
Portal portal = new Portal((Location)locs.get(locidx), vals[ii+1]);
|
||||
portals.add(portal);
|
||||
|
||||
// upgrade the corresponding location in the location list
|
||||
locs.set(locidx, portal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default entrance portal for the scene, or
|
||||
* <code>null</code> if an error occurs.
|
||||
*/
|
||||
protected Portal getEntrancePortal (String data)
|
||||
{
|
||||
ArrayList locs = _info.scene.locations;
|
||||
int size = locs.size();
|
||||
int pidx = parseInt(data);
|
||||
|
||||
if (size == 0 || pidx < 0 || pidx > size - 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (Portal)locs.get(pidx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified XML file and return a miso scene object with
|
||||
* the data contained therein.
|
||||
*
|
||||
* @param path the full path to the scene description file.
|
||||
*
|
||||
* @return the scene object, or null if an error occurred.
|
||||
*/
|
||||
public EditableMisoScene loadScene (String path) throws IOException
|
||||
{
|
||||
return loadScene(getInputStream(path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the specified XML file and return a miso scene object with
|
||||
* the data contained therein.
|
||||
*
|
||||
* @param stream the input stream from which the XML scene description
|
||||
* can be read.
|
||||
*
|
||||
* @return the scene object, or null if an error occurred.
|
||||
*/
|
||||
public EditableMisoScene loadScene (InputStream stream) throws IOException
|
||||
{
|
||||
_info = new SceneInfo();
|
||||
parseStream(stream);
|
||||
// place shadow tiles for any objects in the scene
|
||||
_info.scene.generateAllObjectShadows();
|
||||
// return the final scene object
|
||||
return _info.scene;
|
||||
}
|
||||
|
||||
/** The iso scene view data model. */
|
||||
protected IsoSceneViewModel _model;
|
||||
|
||||
/** The tile manager object for use in constructing scenes. */
|
||||
protected TileManager _tilemgr;
|
||||
|
||||
/** Temporary storage of scene info while parsing. */
|
||||
protected SceneInfo _info;
|
||||
|
||||
/**
|
||||
* A class to hold the information gathered while parsing.
|
||||
*/
|
||||
class SceneInfo
|
||||
{
|
||||
/** The scene populated with data while parsing. */
|
||||
public MisoSceneImpl scene;
|
||||
|
||||
/** The current layer number being processed. */
|
||||
public int lnum;
|
||||
|
||||
/** The current row number being processed. */
|
||||
public int rownum;
|
||||
|
||||
/** The column at which the current row data begins. */
|
||||
public int colstart;
|
||||
|
||||
public SceneInfo ()
|
||||
{
|
||||
scene = new MisoSceneImpl(_model, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
//
|
||||
// $Id: XMLSceneRepository.java,v 1.15 2001/11/08 18:36:56 mdb Exp $
|
||||
|
||||
package com.threerings.miso.scene.xml;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.util.Config;
|
||||
import com.threerings.media.tile.TileManager;
|
||||
import com.threerings.miso.Log;
|
||||
import com.threerings.miso.scene.IsoSceneViewModel;
|
||||
import com.threerings.miso.scene.MisoScene;
|
||||
import com.threerings.miso.scene.EditableMisoScene;
|
||||
import com.threerings.miso.util.MisoUtil;
|
||||
|
||||
/**
|
||||
* The xml scene repository provides a mechanism for reading scenes
|
||||
* from and writing scenes to XML files. These files are template
|
||||
* scene files from which actual runtime game scenes will be
|
||||
* constructed.
|
||||
*/
|
||||
public class XMLSceneRepository
|
||||
{
|
||||
/**
|
||||
* Initializes the xml scene repository.
|
||||
*
|
||||
* @param config the config object.
|
||||
* @param tilemgr the tile manager object.
|
||||
*/
|
||||
public void init (Config config, TileManager tilemgr)
|
||||
{
|
||||
// keep these for later
|
||||
_config = config;
|
||||
_tilemgr = tilemgr;
|
||||
|
||||
// get path-related information
|
||||
_sceneRoot = _config.getValue(SCENEROOT_KEY, DEF_SCENEROOT);
|
||||
|
||||
// create an iso scene view model detailing scene dimensions
|
||||
_model = new IsoSceneViewModel(config);
|
||||
|
||||
// construct the scene parser and writer objects for later use
|
||||
_parser = new XMLSceneParser(_model, _tilemgr);
|
||||
_writer = new XMLSceneWriter(_model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns a miso scene object for the scene described in
|
||||
* the specified XML file.
|
||||
*
|
||||
* @param path the full pathname to the file.
|
||||
*
|
||||
* @return the scene object.
|
||||
*/
|
||||
public EditableMisoScene loadScene (String path) throws IOException
|
||||
{
|
||||
Log.info("Loading scene [path=" + path + "].");
|
||||
return _parser.loadScene(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and returns a miso scene object for the scene described in
|
||||
* the XML file available via the supplied input stream.
|
||||
*
|
||||
* @param path the full pathname to the file.
|
||||
*
|
||||
* @return the scene object.
|
||||
*/
|
||||
public EditableMisoScene loadScene (InputStream stream)
|
||||
throws IOException
|
||||
{
|
||||
return _parser.loadScene(stream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a scene to the specified file in the scene root
|
||||
* directory in XML format. The filename should be relative to
|
||||
* the scene root directory.
|
||||
*
|
||||
* @param scene the scene to save.
|
||||
* @param path the full path of the file to write the scene to.
|
||||
*/
|
||||
public void saveScene (MisoScene scene, String path) throws IOException
|
||||
{
|
||||
Log.info("Saving scene [path=" + path + "].");
|
||||
_writer.saveScene(scene, path);
|
||||
}
|
||||
|
||||
/** The config object. */
|
||||
protected Config _config;
|
||||
|
||||
/** The tile manager from which the scenes obtain their tiles. */
|
||||
protected TileManager _tilemgr;
|
||||
|
||||
/** The root scene directory path. */
|
||||
protected String _sceneRoot;
|
||||
|
||||
/** The iso scene view data model. */
|
||||
protected IsoSceneViewModel _model;
|
||||
|
||||
/** The parser object for reading scenes from files. */
|
||||
protected XMLSceneParser _parser;
|
||||
|
||||
/** The writer object for writing scenes to files. */
|
||||
protected XMLSceneWriter _writer;
|
||||
|
||||
/** The config key for the root scene directory. */
|
||||
protected static final String SCENEROOT_KEY =
|
||||
MisoUtil.CONFIG_KEY + ".sceneroot";
|
||||
|
||||
/** The default root scene directory path. */
|
||||
protected static final String DEF_SCENEROOT = "rsrc/scenes";
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// $Id: XMLSceneVersion.java,v 1.1 2001/09/21 02:30:35 mdb Exp $
|
||||
|
||||
package com.threerings.miso.scene.xml;
|
||||
|
||||
/**
|
||||
* This class tracks the version number of the XML scene file format. When
|
||||
* modifications are made to the file format, the version number in this
|
||||
* class should be increased.
|
||||
*/
|
||||
public class XMLSceneVersion
|
||||
{
|
||||
/** The latest scene file format version. */
|
||||
public static int VERSION = 1;
|
||||
}
|
||||
@@ -1,368 +0,0 @@
|
||||
//
|
||||
// $Id: XMLSceneWriter.java,v 1.18 2001/10/25 16:36:43 shaper Exp $
|
||||
|
||||
package com.threerings.miso.scene.xml;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
import com.samskivert.util.ListUtil;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
import com.megginson.sax.DataWriter;
|
||||
|
||||
import com.threerings.media.tile.Tile;
|
||||
|
||||
import com.threerings.miso.Log;
|
||||
import com.threerings.miso.scene.*;
|
||||
import com.threerings.miso.tile.ShadowTile;
|
||||
|
||||
/**
|
||||
* The <code>XMLSceneWriter</code> writes a {@link
|
||||
* com.threerings.miso.scene.MisoScene} object to an XML file.
|
||||
*
|
||||
* <p> The scene id is omitted as the scene id is assigned when the
|
||||
* scene template is actually loaded into a server. Similarly,
|
||||
* portals are named and bound to their target scene ids later.
|
||||
*/
|
||||
public class XMLSceneWriter extends DataWriter
|
||||
{
|
||||
/**
|
||||
* Construct an XMLSceneWriter object.
|
||||
*/
|
||||
public XMLSceneWriter (IsoSceneViewModel model)
|
||||
{
|
||||
_model = model;
|
||||
setIndentStep(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the scenes to the specified output file in XML format.
|
||||
*
|
||||
* @param fname the file to write to.
|
||||
*/
|
||||
public void saveScene (MisoScene scene, String fname) throws IOException
|
||||
{
|
||||
FileOutputStream fos = new FileOutputStream(fname);
|
||||
setOutput(new OutputStreamWriter(fos));
|
||||
|
||||
try {
|
||||
startDocument();
|
||||
|
||||
startElement("scene");
|
||||
|
||||
dataElement("name", scene.getName());
|
||||
dataElement("version", "" + XMLSceneVersion.VERSION);
|
||||
dataElement("locations", getLocationData(scene));
|
||||
|
||||
startElement("clusters");
|
||||
writeClusters(scene);
|
||||
endElement("clusters");
|
||||
|
||||
dataElement("portals", getPortalData(scene));
|
||||
|
||||
dataElement("entrance", getEntranceData(scene));
|
||||
|
||||
startElement("tiles");
|
||||
for (int lnum = 0; lnum < MisoScene.NUM_LAYERS; lnum++) {
|
||||
writeLayer(scene, lnum);
|
||||
}
|
||||
endElement("tiles");
|
||||
|
||||
endElement("scene");
|
||||
endDocument();
|
||||
|
||||
} catch (SAXException saxe) {
|
||||
Log.warning("Exception writing scene to file " +
|
||||
"[scene=" + scene + ", fname=" + fname +
|
||||
", saxe=" + saxe + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output XML detailing the cluster objects. Clusters are
|
||||
* described by a list of location object indexes that are
|
||||
* contained within the cluster.
|
||||
*
|
||||
* @param scene the scene object.
|
||||
*/
|
||||
protected void writeClusters (MisoScene scene) throws SAXException
|
||||
{
|
||||
List clusters = scene.getClusters();
|
||||
List locs = scene.getLocations();
|
||||
|
||||
int size = clusters.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Cluster cluster = (Cluster)clusters.get(ii);
|
||||
List clusterlocs = cluster.getLocations();
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int clustersize = clusterlocs.size();
|
||||
for (int jj = 0; jj < clustersize; jj++) {
|
||||
Location cloc = (Location)clusterlocs.get(jj);
|
||||
buf.append(locs.indexOf(cloc));
|
||||
if (jj < clustersize - 1) {
|
||||
buf.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
dataElement("cluster", buf.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output XML detailing the tiles at the specified layer in the
|
||||
* given scene. The first layer is outputted in its entirety,
|
||||
* whereas subsequent layers are outputted in a sparse notation
|
||||
* that details each contiguous horizontal chunk of tiles in each
|
||||
* row separately.
|
||||
*
|
||||
* @param scene the scene object.
|
||||
* @param lnum the layer number.
|
||||
*/
|
||||
protected void writeLayer (MisoScene scene, int lnum) throws SAXException
|
||||
{
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute("", "lnum", "", "CDATA", "" + lnum);
|
||||
|
||||
startElement("", "layer", "", attrs);
|
||||
for (int yy = 0; yy < _model.scenehei; yy++) {
|
||||
if (lnum == MisoScene.LAYER_BASE) {
|
||||
writeTileRowData(scene, yy, lnum);
|
||||
} else {
|
||||
writeSparseTileRowData(scene, yy, lnum);
|
||||
}
|
||||
}
|
||||
endElement("layer");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the portals in the scene. Each
|
||||
* portal is specified by a comma-delimited tuple of (location
|
||||
* index, portal name) values.
|
||||
*
|
||||
* @param scene the scene object.
|
||||
*
|
||||
* @return the portals in String format.
|
||||
*/
|
||||
protected String getPortalData (MisoScene scene)
|
||||
{
|
||||
List locs = scene.getLocations();
|
||||
List portals = scene.getPortals();
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int size = portals.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Portal portal = (Portal)portals.get(ii);
|
||||
buf.append(locs.indexOf(portal)).append(",");
|
||||
buf.append(portal.name);
|
||||
if (ii < size - 1) {
|
||||
buf.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the locations in the scene.
|
||||
* Each location is specified by a comma-delimited triplet of
|
||||
* (x, y, orientation) values.
|
||||
*
|
||||
* @return the locations in String format.
|
||||
*/
|
||||
protected String getLocationData (MisoScene scene)
|
||||
{
|
||||
List locs = scene.getLocations();
|
||||
|
||||
StringBuffer buf = new StringBuffer();
|
||||
int size = locs.size();
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
Location loc = (Location)locs.get(ii);
|
||||
buf.append(loc.x).append(",");
|
||||
buf.append(loc.y).append(",");
|
||||
buf.append(loc.orient);
|
||||
if (ii < size - 1) {
|
||||
buf.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string detailing the location index of the default
|
||||
* entrance portal for the scene, or <code>"-1"</code> if no
|
||||
* default portal is specified or an error occurs.
|
||||
*/
|
||||
protected String getEntranceData (MisoScene scene)
|
||||
{
|
||||
List locs = scene.getLocations();
|
||||
Portal entrance = scene.getEntrance();
|
||||
|
||||
if (locs.size() == 0 || entrance == null) {
|
||||
return "-1";
|
||||
}
|
||||
|
||||
return String.valueOf(locs.indexOf(entrance));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string representation of the tiles at the specified
|
||||
* row and layer in the given scene. Only <code>len</code> tiles
|
||||
* starting at column <code>colstart</code> are included in the
|
||||
* string.
|
||||
*
|
||||
* @param scene the scene object.
|
||||
* @param rownum the row number.
|
||||
* @param lnum the layer number.
|
||||
* @param colstart the first column of data.
|
||||
* @param len the number of columns of data.
|
||||
*
|
||||
* @return the tile data in String format.
|
||||
*/
|
||||
protected String getTileData (MisoScene scene, int rownum, int lnum,
|
||||
int colstart, int len)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Tile[][][] tiles = scene.getTiles();
|
||||
|
||||
int numtiles = colstart + len;
|
||||
for (int ii = colstart; ii < numtiles; ii++) {
|
||||
Tile tile = tiles[lnum][ii][rownum];
|
||||
if (tile == null) {
|
||||
Log.warning("Null tile [x=" + ii + ", rownum=" + rownum +
|
||||
", lnum=" + lnum + "].");
|
||||
continue;
|
||||
}
|
||||
|
||||
// replace shadow tiles with the default tile for the
|
||||
// scene since they'll be re-created when the object's
|
||||
// footprint is stamped into the scene upon its
|
||||
// un-serialization
|
||||
if (tile instanceof ShadowTile) {
|
||||
tile = scene.getDefaultTile();
|
||||
}
|
||||
|
||||
buf.append(tile.tsid).append(",");
|
||||
buf.append(tile.tid);
|
||||
if (ii != numtiles - 1) {
|
||||
buf.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the row data for a specified row in the scene tile array.
|
||||
*
|
||||
* <p> The row is written as a <code>row</code> element. Each
|
||||
* tile is specified by a comma-delimited tuple of (tile set id,
|
||||
* tile id) numbers, with the associated row number detailed in
|
||||
* the <code>rownum</code> attribute of the <code>row</code>
|
||||
* element.
|
||||
*
|
||||
* @param scene the scene object.
|
||||
* @param rownum the row in the scene tile array.
|
||||
* @param lnum the layer number in the scene tile array.
|
||||
*/
|
||||
protected void writeTileRowData (MisoScene scene, int rownum, int lnum)
|
||||
throws SAXException
|
||||
{
|
||||
// set up the attributes for this row
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute("", "rownum", "", "CDATA", "" + rownum);
|
||||
|
||||
// output the full row data element
|
||||
String data = getTileData(scene, rownum, lnum, 0, _model.scenewid);
|
||||
dataElement("", "row", "", attrs, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility routine used by <code>writeSparseTileRowData</code> to
|
||||
* obtain the sets of contiguous tile sets in each row.
|
||||
*
|
||||
* <p> The search for contiguous tiles starts at the column
|
||||
* specified in <code>info[0]</code.
|
||||
*
|
||||
* <p> Results are returned in the <code>info</code> array as
|
||||
* <code>{ colstart, len }</code>. colstart is -1 if no
|
||||
* tiles were found in the rest of the row.
|
||||
*
|
||||
* @param scene the scene object.
|
||||
* @param rownum the row number.
|
||||
* @param lnum the layer number.
|
||||
* @param info the info array.
|
||||
*
|
||||
* @return true if any tiles were found, false if not.
|
||||
*/
|
||||
protected boolean getSparseColumn (
|
||||
MisoScene scene, int rownum, int lnum, int info[])
|
||||
{
|
||||
Tile[][][] tiles = scene.getTiles();
|
||||
int start = -1, len = 0;
|
||||
for (int xx = info[0]; xx < _model.scenewid; xx++) {
|
||||
Tile tile = tiles[lnum][xx][rownum];
|
||||
if (tile == null) {
|
||||
if (start == -1) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start == -1) {
|
||||
start = xx;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
|
||||
info[0] = start;
|
||||
info[1] = len;
|
||||
|
||||
return (start != -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the row data for a specified row in the scene tile array
|
||||
* in sparse row format.
|
||||
*
|
||||
* <p> Sparse row format is identical to the format detailed in
|
||||
* <code>writeTileRowData()</code> except that a separate
|
||||
* <code>row</code> element is outputted for each contiguous set
|
||||
* of tiles, with the starting column detailed in the
|
||||
* <code>colstart</code> attribute of the <code>row</code>
|
||||
* element.
|
||||
*
|
||||
* @param scene the scene object.
|
||||
* @param rownum the row in the scene tile array.
|
||||
* @param lnum the layer number in the scene tile array.
|
||||
*/
|
||||
protected void
|
||||
writeSparseTileRowData (MisoScene scene, int rownum, int lnum)
|
||||
throws SAXException
|
||||
{
|
||||
// set up the attributes for this row
|
||||
AttributesImpl attrs = new AttributesImpl();
|
||||
attrs.addAttribute("", "rownum", "", "CDATA", "" + rownum);
|
||||
attrs.addAttribute("", "colstart", "", "CDATA", "0");
|
||||
|
||||
int info[] = new int[] { 0, 0 };
|
||||
while (getSparseColumn(scene, rownum, lnum, info)) {
|
||||
// update the colstart attribute
|
||||
attrs.setAttribute(1, "", "colstart", "", "CDATA", "" + info[0]);
|
||||
|
||||
// output the partial row data element
|
||||
String data = getTileData(scene, rownum, lnum, info[0], info[1]);
|
||||
dataElement("", "row", "", attrs, data);
|
||||
|
||||
// update the colstart value
|
||||
info[0] = info[0] + info[1];
|
||||
}
|
||||
}
|
||||
|
||||
/** The iso scene view data model. */
|
||||
protected IsoSceneViewModel _model;
|
||||
}
|
||||
Reference in New Issue
Block a user