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:
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user