Port of the miso scene model and related bits (so, data only, no rendering of any kind yet).

git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@923 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Mike Thomas
2010-06-08 01:48:12 +00:00
parent e3de56d12a
commit 2f634e3a60
11 changed files with 1583 additions and 0 deletions
@@ -0,0 +1,101 @@
//
// $Id: MisoSceneModel.java 872 2010-01-13 18:28:28Z ray $
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.data {
import flash.geom.Rectangle;
import com.threerings.miso.util.ObjectSet;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.io.ObjectInputStream;
import com.threerings.miso.data.ObjectInfo;
import com.threerings.util.ClassUtil;
import com.threerings.util.Cloneable;
import com.threerings.io.ObjectOutputStream;
/**
* Contains basic information for a miso scene model that is shared among
* the specialized model implementations.
*/
public /*abstract*/ class MisoSceneModel extends SimpleStreamableObject
implements Cloneable
{
public function clone () :Object
{
return (ClassUtil.newInstance(this) as MisoSceneModel);
}
/**
* Returns the fully qualified tile id of the base tile at the
* specified coordinates. <code>-1</code> will be returned if there is
* no tile at the specified coordinate.
*/
public function getBaseTileId (arg1 :int, arg2 :int) :int
{
throw new Error("abstract");
}
public function setBaseTile (arg1 :int, arg2 :int, arg3 :int) :Boolean
{
throw new Error("abstract");
}
public function setDefaultBaseTileSet (arg1 :int) :void
{
// nothing doing
}
/**
* Scene models can return a default tileset to be used when no base
* tile data exists for a particular tile.
*/
public function getDefaultBaseTileSet () :int
{
return 0;
}
/**
* Populates the supplied object set with info on all objects whose
* origin falls in the requested region.
*/
public function getObjects (region :Rectangle, set :ObjectSet) :void
{
throw new Error("abstract");
}
public function addObject (info :ObjectInfo) :Boolean
{
throw new Error("abstract");
}
public function updateObject (info :ObjectInfo) :void
{
throw new Error("abstract");
}
public function removeObject (info :ObjectInfo) :Boolean
{
throw new Error("abstract");
}
}
}
@@ -0,0 +1,201 @@
//
// $Id: ObjectInfo.java 872 2010-01-13 18:28:28Z ray $
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.data {
import com.threerings.util.Hashable;
import com.threerings.util.ClassUtil;
import com.threerings.util.Cloneable;
import com.threerings.util.StringUtil;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.miso.data.ObjectInfo;
import com.threerings.media.tile.TileUtil;
/**
* Contains information about an object in a Miso scene.
*/
public class ObjectInfo extends SimpleStreamableObject
implements Cloneable, Hashable
{
/** The fully qualified object tile id. */
public var tileId :int;
/** The x and y tile coordinates of the object. */
public var x :int;
public var y :int;
/** Don't access this directly unless you are serializing this
* instance. Use {@link #getPriority} instead. */
public var priority :int = 0;
/** The action associated with this object or null if it has no
* action. */
public var action :String;
/** A "spot" associated with this object (specified as an offset from
* the fine coordinates of the object's origin tile). */
public var sx :int;
public var sy :int;
/** The orientation of the "spot" associated with this object. */
public var sorient :int;
/** Up to two colorization assignments for this object. */
public var zations :int;
public function ObjectInfo (tileId :int = 0, x :int = 0, y :int = 0)
{
this.tileId = tileId;
this.x = x;
this.y = y;
}
public function hashCode () :int
{
return x ^ y ^ tileId;
}
public function clone () :Object
{
var info :ObjectInfo = (ClassUtil.newInstance(this) as ObjectInfo);
info.tileId = tileId;
info.x = x;
info.y = y;
info.priority = priority;
info.action = action;
info.sx = sx;
info.sy = sy;
info.sorient = sorient;
info.zations = zations;
return info;
}
public function equals (other :Object) :Boolean
{
if (other is ObjectInfo) {
var ooi :ObjectInfo = ObjectInfo(other);
return (x == ooi.x && y == ooi.y && tileId == ooi.tileId);
} else {
return false;
}
}
/**
* Returns the render priority of this object tile.
*/
public function getPriority () :int
{
return priority;
}
/**
* Returns the primary colorization assignment.
*/
public function getPrimaryZation () :int
{
return (zations & 0xFF);
}
/**
* Returns the secondary colorization assignment.
*/
public function getSecondaryZation () :int
{
return ((zations >> 16) & 0xFF);
}
/**
* Returns the tertiary colorization assignment.
*/
public function getTertiaryZation () :int
{
return ((zations >> 24) & 0xFF);
}
/**
* Returns the quaternary colorization assignment.
*/
public function getQuaternaryZation () :int
{
return ((zations >> 8) & 0xFF);
}
/**
* Sets the primary and secondary colorization assignments.
*/
public function setZations (primary :int, secondary :int, tertiary :int, quaternary :int) :void
{
zations = (primary | (secondary << 16) | (tertiary << 24) | (quaternary << 8));
}
/**
* Returns true if this object info contains non-default data for
* anything other than the tile id and coordinates.
*/
public function isInteresting () :Boolean
{
return (!StringUtil.isBlank(action) || priority != 0 ||
sx != 0 || sy != 0 || zations != 0);
}
/** Enhances our {@link SimpleStreamableObject#toString} output. */
public function tileIdToString () :String
{
return (TileUtil.getTileSetId(tileId) + ":" +
TileUtil.getTileIndex(tileId));
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
tileId = ins.readInt();
x = ins.readInt();
y = ins.readInt();
priority = ins.readByte();
action = ins.readField(String);
sx = ins.readByte();
sy = ins.readByte();
sorient = ins.readByte();
zations = ins.readInt();
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeInt(tileId);
out.writeInt(x);
out.writeInt(y);
out.writeByte(priority);
out.writeField(action);
out.writeByte(sx);
out.writeByte(sy);
out.writeByte(sorient);
out.writeInt(zations);
}
}
}
@@ -0,0 +1,248 @@
//
// $Id: SparseMisoSceneModel.java 901 2010-03-11 00:51:30Z mthomas $
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.data {
import flash.geom.Rectangle;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.io.ObjectOutputStream;
import com.threerings.util.ArrayIterator;
import com.threerings.util.ClassUtil;
import com.threerings.util.Iterator;
import com.threerings.util.Joiner;
import com.threerings.util.MathUtil;
import com.threerings.util.StreamableHashMap;
import com.threerings.util.StringUtil;
import com.threerings.miso.util.ObjectSet;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.data.SparseMisoSceneModel;
import com.threerings.miso.data.ObjectInfo;
import com.threerings.miso.data.SparseMisoSceneModel_ObjectVisitor;
import com.threerings.miso.data.SparseMisoSceneModel_Section;
/**
* Contains miso scene data that is broken up into NxN tile sections.
*/
public class SparseMisoSceneModel extends MisoSceneModel
{
public var swidth :int;
public var sheight :int;
/** The dimensions of a section of our scene. */
/** The tileset to use when we have no tile data. */
public var defTileSet :int = 0;
override public function clone () :Object
{
var model :SparseMisoSceneModel = (ClassUtil.newInstance(this) as SparseMisoSceneModel);
model._sections = new StreamableHashMap();
for (var iter :Iterator = getSections(); iter.hasNext(); ) {
var sect :SparseMisoSceneModel_Section = SparseMisoSceneModel_Section(iter.next());
model.setSection(SparseMisoSceneModel_Section(sect.clone()));
}
return model;
}
override public function getBaseTileId (col :int, row :int) :int
{
var sec :SparseMisoSceneModel_Section = getSection(col, row, false);
return (sec == null) ? -1 : sec.getBaseTileId(col, row);
}
override public function setBaseTile (fqBaseTileId :int, col :int, row :int) :Boolean
{
getSection(col, row, true).setBaseTile(col, row, fqBaseTileId);
return true;
}
override public function setDefaultBaseTileSet (tileSetId :int) :void
{
defTileSet = tileSetId;
}
override public function getDefaultBaseTileSet () :int
{
return defTileSet;
}
override public function getObjects (region :Rectangle, set :ObjectSet) :void
{
var minx :int = MathUtil.floorDiv(region.x, swidth)*swidth;
var maxx :int = MathUtil.floorDiv(region.x+region.width-1, swidth)*swidth;
var miny :int = MathUtil.floorDiv(region.y, sheight)*sheight;
var maxy :int = MathUtil.floorDiv(region.y+region.height-1, sheight)*sheight;
for (var yy :int = miny; yy <= maxy; yy += sheight) {
for (var xx :int = minx; xx <= maxx; xx += swidth) {
var sec :SparseMisoSceneModel_Section = getSection(xx, yy, false);
if (sec != null) {
sec.getObjects(region, set);
}
}
}
}
override public function addObject (info :ObjectInfo) :Boolean
{
return getSection(info.x, info.y, true).addObject(info);
}
override public function updateObject (info :ObjectInfo) :void
{
// not efficient, but this is only done in editing situations
removeObject(info);
addObject(info);
}
override public function removeObject (info :ObjectInfo) :Boolean
{
var sec :SparseMisoSceneModel_Section = getSection(info.x, info.y, false);
if (sec != null) {
return sec.removeObject(info);
} else {
return false;
}
}
/**
* Adds all interesting {@link ObjectInfo} records in this scene to
* the supplied list.
*/
public function getInterestingObjects (list :Array) :void
{
for (var iter :Iterator = getSections(); iter.hasNext(); ) {
var sect :SparseMisoSceneModel_Section = SparseMisoSceneModel_Section(iter.next());
for each (var element :ObjectInfo in sect.objectInfo) {
list.add(element);
}
}
}
/**
* Don't call this method! This is only public so that the scene
* writer can generate XML from the raw scene data.
*/
public function getSections () :Iterator
{
return new ArrayIterator(_sections.values());
}
/**
* Adds all {@link ObjectInfo} records in this scene to the supplied list.
*/
public function getAllObjects (list :Array) :void
{
for (var iter :Iterator = getSections(); iter.hasNext(); ) {
iter.next().getAllObjects(list);
}
}
/**
* Informs the supplied visitor of each object in this scene.
*
* @param interestingOnly if true, only the interesting objects will
* be visited.
*/
public function visitObjects (visitor :SparseMisoSceneModel_ObjectVisitor,
interestingOnly :Boolean = false) :void
{
for (var iter :Iterator = getSections(); iter.hasNext(); ) {
var sect :SparseMisoSceneModel_Section = SparseMisoSceneModel_Section(iter.next());
for each (var oinfo :ObjectInfo in sect.objectInfo) {
visitor.visit(oinfo);
}
if (!interestingOnly) {
for (var oo :int = 0; oo < sect.objectTileIds.length; oo++) {
var info :ObjectInfo = new ObjectInfo(sect.objectTileIds[oo],
sect.objectXs[oo], sect.objectYs[oo]);
visitor.visit(info);
}
}
}
}
/**
* Don't call this method! This is only public so that the scene
* parser can construct a scene from raw data. If only Java supported
* class friendship.
*/
public function setSection (section :SparseMisoSceneModel_Section) :void
{
_sections.put(key(section.x, section.y), section);
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
swidth = ins.readShort();
sheight = ins.readShort();
defTileSet = ins.readInt();
_sections = ins.readObject(StreamableHashMap);
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeShort(swidth);
out.writeShort(sheight);
out.writeInt(defTileSet);
out.writeObject(_sections);
}
override protected function toStringJoiner (j :Joiner) :void
{
super.toStringJoiner(j);
j.add("sections", StringUtil.toString(_sections.values()));
}
/**
* Returns the key for the specified section.
*/
protected function key (x :int, y :int) :int
{
var sx :int = MathUtil.floorDiv(x, swidth);
var sy :int = MathUtil.floorDiv(y, sheight);
return (sx << 16) | (sy & 0xFFFF);
}
/** Returns the section for the specified tile coordinate. */
protected function getSection (x :int, y :int, create :Boolean) :SparseMisoSceneModel_Section
{
var key :int = key(x, y);
var sect :SparseMisoSceneModel_Section = _sections.get(key);
if (sect == null && create) {
var sx :int = MathUtil.floorDiv(x, swidth)*swidth;
var sy :int = MathUtil.floorDiv(y, sheight)*sheight;
_sections.put(key, sect = new SparseMisoSceneModel_Section(sx, sy, swidth, sheight));
}
return sect;
}
/** Contains our sections in row major order. */
protected var _sections :StreamableHashMap = new StreamableHashMap();
}
}
@@ -0,0 +1,26 @@
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.data {
public interface SparseMisoSceneModel_ObjectVisitor
{
/** Called for each object in the scene, interesting and not. */
function visit (info :ObjectInfo) :void;
}
}
@@ -0,0 +1,265 @@
//
// $Id: SparseMisoSceneModel_Section.java 901 2010-03-11 00:51:30Z mthomas $
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.data {
import flash.geom.Rectangle;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.io.TypedArray;
import com.threerings.miso.util.ObjectSet;
import com.threerings.util.ArrayUtil;
import com.threerings.util.ClassUtil;
import com.threerings.util.Cloneable;
import com.threerings.util.Log;
import com.threerings.util.StringUtil;
public class SparseMisoSceneModel_Section extends SimpleStreamableObject
implements Cloneable
{
public static const log :Log = Log.getLog(SparseMisoSceneModel_Section);
/** The tile coordinate of our upper leftmost tile. */
public var x :int;
public var y :int;
/** The width of this section in tiles. */
public var width :int;
/** The combined tile ids (tile set id and tile id) for our
* section (in row major order). */
public var baseTileIds :TypedArray;
/** The combined tile ids (tile set id and tile id) of the
* "uninteresting" tiles in the object layer. */
public var objectTileIds :TypedArray = TypedArray.create(int);
/** The x coordinate of the "uninteresting" tiles in the object
* layer. */
public var objectXs :TypedArray = TypedArray.createShort();
/** The y coordinate of the "uninteresting" tiles in the object
* layer. */
public var objectYs :TypedArray = TypedArray.createShort();
/** Information records for the "interesting" objects in the
* object layer. */
public var objectInfo :TypedArray = TypedArray.create(ObjectInfo);
/**
* Creates a new scene section with the specified dimensions.
*/
public function SparseMisoSceneModel_Section (
x :int = 0, y :int = 0, width :int = 0, height :int = 0)
{
this.x = x;
this.y = y;
this.width = width;
baseTileIds = TypedArray.create(int, ArrayUtil.create(width*height));
}
public function getBaseTileId (col :int, row :int) :int
{
if (col < x || col >= (x+width) || row < y || row >= (y+width)) {
log.warning("Requested bogus tile +" + col + "+" + row +
" from " + this + ".");
return -1;
} else {
return baseTileIds[(row-y)*width+(col-x)];
}
}
public function setBaseTile (col :int, row :int, fqBaseTileId :int) :void
{
baseTileIds[(row-y)*width+(col-x)] = fqBaseTileId;
}
public function addObject (info :ObjectInfo) :Boolean
{
// sanity check: see if there is already an object of this
// type at these coordinates
var dupidx :int;
if ((dupidx = ArrayUtil.indexOf(objectInfo, info)) != -1) {
log.warning("Refusing to add duplicate object [ninfo=" + info +
", oinfo=" + objectInfo[dupidx] + "].");
return false;
}
if ((dupidx = indexOfUn(info)) != -1) {
log.warning("Refusing to add duplicate object " +
"[info=" + info + "].");
return false;
}
if (info.isInteresting()) {
objectInfo = TypedArray(objectInfo.concat(info));
} else {
objectTileIds = TypedArray(objectTileIds.concat(info.tileId));
objectXs = TypedArray(objectXs.concat(info.x));
objectYs = TypedArray(objectYs.concat(info.y));
}
return true;
}
public function removeObject (info :ObjectInfo) :Boolean
{
// look for it in the interesting info array
var oidx :int = ArrayUtil.indexOf(objectInfo, info);
if (oidx != -1) {
objectInfo = TypedArray(ArrayUtil.splice(objectInfo, oidx, 1));
return true;
}
// look for it in the uninteresting arrays
oidx = indexOfUn(info);
if (oidx != -1) {
objectTileIds = TypedArray(ArrayUtil.splice(objectTileIds, oidx, 1));
objectXs = TypedArray(ArrayUtil.splice(objectXs, oidx, 1));
objectYs = TypedArray(ArrayUtil.splice(objectYs, oidx, 1));
return true;
}
return false;
}
/**
* Returns the index of the specified object in the uninteresting
* arrays or -1 if it is not in this section as an uninteresting
* object.
*/
protected function indexOfUn (info :ObjectInfo) :int
{
for (var ii :int = 0; ii < objectTileIds.length; ii++) {
if (objectTileIds[ii] == info.tileId &&
objectXs[ii] == info.x && objectYs[ii] == info.y) {
return ii;
}
}
return -1;
}
public function getAllObjects (list :Array) :void
{
for each (var info :ObjectInfo in objectInfo) {
list.add(info);
}
for (var ii :int= 0; ii < objectTileIds.length; ii++) {
var x :int = objectXs[ii];
var y :int = objectYs[ii];
list.add(new ObjectInfo(objectTileIds[ii], x, y));
}
}
public function getObjects (region :Rectangle, set :ObjectSet) :void
{
// first look for intersecting interesting objects
for each (var info :ObjectInfo in objectInfo) {
if (region.contains(info.x, info.y)) {
set.insert(info);
}
}
// now look for intersecting non-interesting objects
for (var ii :int = 0; ii < objectTileIds.length; ii++) {
var x :int = objectXs[ii];
var y :int = objectYs[ii];
if (region.contains(x, y)) {
set.insert(new ObjectInfo(objectTileIds[ii], x, y));
}
}
}
/**
* Returns true if this section contains no data beyond the default.
* Used when saving a sparse scene: we omit blank sections.
*/
public function isBlank () :Boolean
{
if ((objectTileIds.length != 0) || (objectInfo.length != 0)) {
return false;
}
for each (var baseTileId :int in baseTileIds) {
if (baseTileId != 0) {
return false;
}
}
return true;
}
public function clone () :Object
{
var section :SparseMisoSceneModel_Section =
(ClassUtil.newInstance(this) as SparseMisoSceneModel_Section);
section.x = x;
section.y = y;
section.width = width;
section.baseTileIds = TypedArray(ArrayUtil.copyOf(baseTileIds));
section.objectTileIds = TypedArray(ArrayUtil.copyOf(objectTileIds));
section.objectXs = TypedArray(ArrayUtil.copyOf(objectXs));
section.objectYs = TypedArray(ArrayUtil.copyOf(objectYs));
section.objectInfo = TypedArray.create(ObjectInfo);
for (var ii :int = 0; ii < objectInfo.length; ii++) {
section.objectInfo[ii] = objectInfo[ii].clone();
}
return section;
}
override public function toString () :String
{
if (width == 0 || baseTileIds == null) {
return "<no bounds>";
} else {
return width + "x" + (baseTileIds.length / width) + "+" + x + ":" + y + ":" +
objectInfo.length;
}
}
// from interface Streamable
override public function readObject (ins :ObjectInputStream) :void
{
super.readObject(ins);
x = ins.readShort();
y = ins.readShort();
width = ins.readInt();
baseTileIds = ins.readField(TypedArray.getJavaType(int));
objectTileIds = ins.readField(TypedArray.getJavaType(int));
objectXs = ins.readField(TypedArray.getJavaShortType());
objectYs = ins.readField(TypedArray.getJavaShortType());
objectInfo = TypedArray(ins.readObject());
}
// from interface Streamable
override public function writeObject (out :ObjectOutputStream) :void
{
super.writeObject(out);
out.writeShort(x);
out.writeShort(y);
out.writeInt(width);
out.writeField(baseTileIds);
out.writeField(objectTileIds);
out.writeField(objectXs);
out.writeField(objectYs);
out.writeField(objectInfo);
}
}
}
@@ -0,0 +1,56 @@
//
// $Id: VirtualMisoSceneModel.java 868 2010-01-04 21:47:34Z dhoover $
//
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.data {
import com.threerings.io.ObjectInputStream;
import com.threerings.miso.data.ObjectInfo;
import com.threerings.io.ObjectOutputStream;
/**
* A convenient base class for "virtual" scenes which do not allow editing
* and compute the base and object tiles rather than obtain them from some
* data structure.
*/
public /*abstract*/ class VirtualMisoSceneModel extends MisoSceneModel
{
override public function setBaseTile (arg1 :int, arg2 :int, arg3 :int) :Boolean
{
throw new Error("Unsupported");
}
override public function addObject (arg1 :ObjectInfo) :Boolean
{
throw new Error("Unsupported");
}
override public function updateObject (arg1 :ObjectInfo) :void
{
throw new Error("Unsupported");
}
override public function removeObject (arg1 :ObjectInfo) :Boolean
{
throw new Error("Unsupported");
}
}
}
@@ -0,0 +1,28 @@
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.util {
/**
* Provides Miso code with access to the managers that it needs to do its
* thing. For now it is just a stub.
*/
public interface MisoContext
{
}
}
@@ -0,0 +1,160 @@
// Nenya library - tools for developing networked games
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/nenya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.miso.util {
import com.threerings.miso.data.ObjectInfo;
import com.threerings.util.ArrayUtil;
import com.threerings.util.Log;
/**
* Used to store an (arbitrarily) ordered, low-impact iteratable (doesn't
* require object creation), set of {@link ObjectInfo} instances.
*/
public class ObjectSet
{
public static const log :Log = Log.getLog(ObjectSet);
/**
* Inserts the supplied object into the set.
*
* @return true if it was inserted, false if the object was already in
* the set.
*/
public function insert (info :ObjectInfo) :Boolean
{
// bail if it's already in the set
var ipos :int = indexOf(info);
if (ipos >= 0) {
// log a warning because the caller shouldn't be doing this
log.warning("Requested to add an object to a set that already " +
"contains such an object [ninfo=" + info +
", oinfo=" + _objs[ipos] + "].", new Error());
return false;
}
// otherwise insert it
ipos = -(ipos+1);
_objs = _objs.splice(ipos, 0, info);
return true;
}
/**
* Returns true if the specified object is in the set, false if it is
* not.
*/
public function contains (info :ObjectInfo) :Boolean
{
return (indexOf(info) >= 0);
}
/**
* Returns the number of objects in this set.
*/
public function size () :int
{
return _objs.length;
}
/**
* Returns the object with the specified index. The index must & be
* between <code>0</code> and {@link #size}<code>-1</code>.
*/
public function get (index :int) :ObjectInfo
{
return ObjectInfo(_objs[index]);
}
/**
* Removes the object at the specified index.
*/
public function removeAt (index :int) :void
{
ArrayUtil.removeFirst(_objs, index);
}
/**
* Removes the specified object from the set.
*
* @return true if it was removed, false if it was not in the set.
*/
public function remove (info :ObjectInfo) :Boolean
{
var opos :int = indexOf(info);
if (opos >= 0) {
removeAt(opos);
return true;
} else {
return false;
}
}
/**
* Clears out the contents of this set.
*/
public function clear () :void
{
_objs.length = 0;
}
/**
* Converts the contents of this object set to an array.
*/
public function toArray () :Array
{
return ArrayUtil.copyOf(_objs);
}
public function toString () :String
{
var result :String = "[";
for (var ii :int = 0; ii < _objs.length; ii++) {
if (ii > 0) {
result += ", ";
}
result += _objs[ii];
}
return result += "]";
}
/** 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 function searchCompare (o1 :Object, o2 :Object) :int
{
var do1 :ObjectInfo = ObjectInfo(o1);
var do2 :ObjectInfo = ObjectInfo(o2);
if (do1.tileId == do2.tileId) {
return ((do1.x << 16) + do1.y) - ((do2.x << 16) + do2.y);
} else {
return do1.tileId - do2.tileId;
}
};
/**
* Returns the index of the object or it's insertion index if it is
* not in the set.
*/
protected function indexOf (info :ObjectInfo) :int
{
return ArrayUtil.binarySearch(_objs, 0, _objs.length, info, searchCompare);
}
/** Our sorted array of objects. */
protected var _objs :Array = new Array();
}
}