First pass at getting miso working with actual tiles and tileset data.

Still to do:
- Handle tile priorities in ISO sorting.
- Handle recoloring tiles (this may result in annoyingly significant changes to Tile/TileSet API)
- Dynamically loading sections rather than loading all the tiles of a scene.
- Better handling of the state where the scene's not yet loaded.
- Portals.
- Dynamic sizing of the MisoScenePanel



git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@932 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Mike Thomas
2010-07-01 22:27:37 +00:00
parent 941a6a83b2
commit e3c79a6be8
25 changed files with 2724 additions and 30 deletions
@@ -0,0 +1,185 @@
//
// 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.media.image {
import com.threerings.display.ColorUtil;
import com.threerings.util.Hashable;
import com.threerings.util.Short;
import com.threerings.util.StringUtil;
public class Colorization
implements Hashable
{
/** Every colorization must have a unique id that can be used to
* compare a particular colorization record with another. */
public var colorizationId :int;
/** The root color for the colorization. */
public var rootColor :uint;
/** The range around the root color that will be colorized (in
* delta-hue, delta-saturation, delta-value. */
public var range :Array;
/** The adjustments to make to hue, saturation and value. */
public var offsets :Array;
/**
* Constructs a colorization record with the specified identifier.
*/
public function Colorization (colorizationId :int, rootColor :uint,
range :Array, offsets :Array)
{
this.colorizationId = colorizationId;
this.rootColor = rootColor;
this.range = range;
this.offsets = offsets;
// compute our HSV and fixed HSV
_hsv = ColorUtil.RGBtoHSB(ColorUtil.getRed(rootColor), ColorUtil.getGreen(rootColor),
ColorUtil.getBlue(rootColor));
_fhsv = toFixedHSV(_hsv, null);
}
/**
* Returns the root color adjusted by the colorization.
*/
public function getColorizedRoot () :uint
{
return recolorColor(_hsv);
}
/**
* Adjusts the supplied color by the offests in this colorization,
* taking the appropriate measures for hue (wrapping it around) and
* saturation and value (clipping).
*
* @return the RGB value of the recolored color.
*/
public function recolorColor (hsv :Array) :uint
{
// for hue, we wrap around
var hue :Number = hsv[0] + offsets[0];
if (hue > 1.0) {
hue -= 1.0;
}
// otherwise we clip
var sat :Number = Math.min(Math.max(hsv[1] + offsets[1], 0), 1);
var val :Number = Math.min(Math.max(hsv[2] + offsets[2], 0), 1);
// convert back to RGB space
return ColorUtil.HSBtoRGB(hue, sat, val);
}
/**
* Returns true if this colorization matches the supplied color, false
* otherwise.
*
* @param hsv the HSV values for the color in question.
* @param fhsv the HSV values converted to fixed point via {@link
* #toFixedHSV} for the color in question.
*/
public function matches (hsv :Array, fhsv :Array) :Boolean
{
// check to see that this color is sufficiently "close" to the
// root color based on the supplied distance parameters
if (distance(fhsv[0], _fhsv[0], Short.MAX_VALUE) >=
range[0] * Short.MAX_VALUE) {
return false;
}
// saturation and value don't wrap around like hue
if (Math.abs(_hsv[1] - hsv[1]) >= range[1] ||
Math.abs(_hsv[2] - hsv[2]) >= range[2]) {
return false;
}
return true;
}
public function hashCode () :int
{
return colorizationId ^ rootColor;
}
public function equals (other :Object) :Boolean
{
if (other is Colorization) {
return (Colorization(other)).colorizationId == colorizationId;
} else {
return false;
}
}
public function toString () :String
{
return String(colorizationId);
}
/**
* Returns a long string representation of this colorization.
*/
public function toVerboseString () :String
{
return StringUtil.toString(this);
}
/**
* Converts floating point HSV values to a fixed point integer
* representation.
*
* @param hsv the HSV values to be converted.
* @param fhsv the destination array into which the fixed values will
* be stored. If this is null, a new array will be created of the
* appropriate length.
*
* @return the <code>fhsv</code> parameter if it was non-null or the
* newly created target array.
*/
public static function toFixedHSV (hsv :Array, fhsv :Array) :Array
{
if (fhsv == null) {
fhsv = new Array(hsv.length);
}
for (var ii :int = 0; ii < hsv.length; ii++) {
// fhsv[i] = (int)(hsv[i]*Integer.MAX_VALUE);
fhsv[ii] = (int)(hsv[ii]*Short.MAX_VALUE);
}
return fhsv;
}
/**
* Returns the distance between the supplied to numbers modulo N.
*/
public static function distance (a :int, b :int, N :int) :int
{
return (a > b) ? Math.min(a - b, b + N - a) : Math.min(b - a, a + N - b);
}
/** Fixed HSV values for our root color; used when calculating
* recolorizations using this colorization. */
protected var _fhsv :Array;
/** HSV values for our root color; used when calculating
* recolorizations using this colorization. */
protected var _hsv :Array;
}
}
@@ -0,0 +1,81 @@
//
// 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.media.tile {
public class BaseTile extends Tile
{
/**
* Returns whether or not this tile can be walked upon by character
* sprites.
*/
public function isPassable () :Boolean
{
return _passable;
}
/**
* Configures this base tile as passable or impassable.
*/
public function setPassable (passable :Boolean) :void
{
_passable = passable;
}
/**
* Returns the x offset into the tile image of the origin (which will be aligned with the
* bottom center of the origin tile) or <code>Integer.MIN_VALUE</code> if the origin is not
* explicitly specified and should be computed from the image size and tile footprint.
*/
public override function getOriginX () :int
{
return getWidth()/2;
}
/**
* Returns the y offset into the tile image of the origin (which will be aligned with the
* bottom center of the origin tile) or <code>Integer.MIN_VALUE</code> if the origin is not
* explicitly specified and should be computed from the image size and tile footprint.
*/
public override function getOriginY () :int
{
return getHeight();
}
/**
* Returns the object footprint width in tile units.
*/
public override function getBaseWidth () :int
{
return 1;
}
/**
* Returns the object footprint height in tile units.
*/
public override function getBaseHeight () :int
{
return 1;
}
/** Whether the tile is passable. */
protected var _passable :Boolean = true;
}
}
@@ -0,0 +1,77 @@
//
// 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.media.tile {
import com.threerings.util.StringUtil;
public class BaseTileSet extends SwissArmyTileSet
{
/**
* Sets the passability information for the tiles in this tileset.
* Each entry in the array corresponds to the tile at that tile index.
*/
public function setPassability (passable :Array) :void
{
_passable = passable;
}
/**
* Returns the passability information for the tiles in this tileset.
*/
public function getPassability () :Array
{
return _passable;
}
protected override function createTile () :Tile
{
return new BaseTile();
}
protected override function initTile (tile :Tile, tileIndex :int, zations :Array) :void
{
super.initTile(tile, tileIndex, zations);
(BaseTile(tile)).setPassable(_passable[tileIndex]);
}
protected override function toStringBuf (buf :String) :String
{
buf = super.toStringBuf(buf);
buf = buf.concat(", passable=", StringUtil.toString(_passable));
return buf;
}
public static function fromXml (xml :XML) :SwissArmyTileSet
{
var set :BaseTileSet = new BaseTileSet();
set.populateFromXml(xml);
return set;
}
protected override function populateFromXml (xml :XML) :void
{
super.populateFromXml(xml);
_passable = toBoolArray(xml.passable);
}
/** Whether each tile is passable. */
protected var _passable :Array;
}
}
@@ -0,0 +1,34 @@
//
// 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.media.tile {
import com.threerings.media.image.Colorization;
public interface Colorizer
{
/**
* Returns the colorization to be used for the specified named colorization class.
*
* @param index the index of the colorization being requested in the tileset's colorization
* list.
*/
function getColorization (index :int, zation :String) :Colorization;
}
}
@@ -0,0 +1,215 @@
//
// 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.media.tile {
import nochump.util.zip.ZipEntry;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.ErrorEvent;
import flash.events.SecurityErrorEvent;
import flash.events.IOErrorEvent;
import flash.utils.ByteArray;
import com.threerings.io.ObjectInputStream;
import com.threerings.media.tile.TileDataPack;
import com.threerings.media.tile.bundle.TileSetBundle;
import com.threerings.util.DataPack;
import com.threerings.util.Integer;
import com.threerings.util.Log;
import com.threerings.util.Maps;
import com.threerings.util.Map;
import com.threerings.util.StringUtil;
public class DataPackTileSetRepository
implements TileSetRepository, TileSetIdMap
{
private static var log :Log = Log.getLog(DataPackTileSetRepository);
public function DataPackTileSetRepository (tileSetUrl :String)
{
_rootUrl = tileSetUrl;
loadTileSetMeta(tileSetUrl + "metadata.jar");
}
protected function loadTileSetMeta (tileSetMetaUrl :String) :void
{
_metaPack = new TileDataPack(tileSetMetaUrl, metaLoadingComplete);
}
protected function parseTileSetMap (map :String) :void
{
var lines :Array = map.split("\n");
var tileCount :int = int(lines[0]);
for (var ii :int = 1; ii < lines.length; ii++) {
var line :String = lines[ii];
var toks :Array = line.split(" := ");
if (toks.length >= 2) {
var id :int = int(toks[1]);
var name :String = String(toks[0]);
_nameMap.put(name, id);
}
}
}
/**
* Handle the successful completion of datapack loading.
*
* @private
*/
protected function metaLoadingComplete (event :Event) :void
{
parseTileSetMap(_metaPack.getFileAsString("tilesetmap.txt"));
for each (var entry :ZipEntry in _metaPack.getFiles()) {
var bundleName :String = entry.name;
if (StringUtil.endsWith(bundleName, "/bundle.xml")) {
loadTileSetsFromPack(bundleName.substr(0, bundleName.length - 11));
}
}
}
public function enumerateTileSetIds () :Array
{
return _idMap.keys();
}
public function enumerateTileSets () :Array
{
return _idMap.values();
}
public function getTileSet (tileSetId :int) :TileSet
{
var tileSet :TileSet = _idMap.get(tileSetId);
// We don't have this tileset loaded just yet.... start grabbing the data pack.
var packName :String = _packMap.get(tileSetId);
if (packName == null) {
log.warning("Attempted to load unknown tile set", "tileSetId", tileSetId);
throw new NoSuchTileSetError(tileSetId);
}
var pack :TileDataPack = _packs.get(packName);
if (pack == null || !pack.isComplete()) {
loadPack(packName, tileSetId, tileSet);
// Loading the pack should've put us in the map, so let's go retrieve it...
tileSet = _idMap.get(tileSetId);
} else {
tileSet.setImageProvider(_packs.get(packName));
}
return tileSet;
}
protected function loadPack (packName :String, tileSetId :int, tileSet :TileSet) :void
{
var pack :TileDataPack = _packs.get(packName);
if (pack != null && pack.isComplete()) {
// Already loaded
return;
}
var completeListener :Function = function () :void {
tileSet.setImageProvider(_packs.get(packName));
tileSet.loaded();
};
var listeners :Array = _packListeners.get(packName);
if (listeners == null) {
listeners = [];
_packListeners.put(packName, listeners);
var packCompleteListener :Function = function () :void {
for each (var listener :Function in listeners) {
listener();
}
_packListeners.remove(packName);
}
pack = new TileDataPack(getPackUrl(packName), packCompleteListener);
_packs.put(packName, pack);
}
listeners.push(completeListener);
}
protected function loadTileSetsFromPack (packName :String) :void
{
var xml :XML = _metaPack.getFileAsXML(packName + "/bundle.xml");
var bundle :TileSetBundle = TileSetBundle.fromXml(xml, this);
bundle.forEach(function(key :*, val :*) :void {
_idMap.put(key, val);
_packMap.put(key, packName);
});
}
protected function getPackUrl (packName :String) :String
{
return _rootUrl + packName + "/bundle.jar";
}
public function getTileSetId (setName :String) :int
{
return _nameMap.get(setName);
}
public function getTileSetByName (setName :String) :TileSet
{
return getTileSet(getTileSetId(setName));
}
protected function getPackName (name :String) :String
{
var lastSlashIdx :int = name.lastIndexOf("/");
if (lastSlashIdx == -1) {
return name;
} else {
return name.substring(0, lastSlashIdx).toLowerCase();
}
}
/** Contains the tileset meta-data for all tilesets. */
protected var _metaPack : DataPack;
/** Maps name to tileSetId. */
protected var _nameMap :Map = Maps.newMapOf(String);
/** Maps tileSetId to actual TileSet. */
protected var _idMap : Map = Maps.newMapOf(int);
/** Maps tileSetId to DataPack name. */
protected var _packMap :Map = Maps.newMapOf(int);
/** The URL for our tilesets. */
protected var _rootUrl :String;
/** Map of pack name to listeners waiting for that pack to resolve. */
protected var _packListeners :Map = Maps.newMapOf(String);
/** The map of packs we've already loaded up and resolved. */
protected var _packs :Map = Maps.newMapOf(String);
}
}
@@ -0,0 +1,50 @@
//
// 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.media.tile {
import flash.display.DisplayObject;
import flash.geom.Rectangle;
public interface ImageProvider
{
/**
* Returns the raw tileset image with the specified path.
*
* @param path the path that identifies the desired image (corresponds to the image path from
* the tileset).
* @param zations if non-null, colorizations to apply to the source image before returning it.
*/
function getTileSetImage (path :String, zations :Array, callback :Function) :void;
/**
* Obtains the tile image with the specified path in the form of a {@link Mirage}. It should be
* cropped from the tileset image identified by the supplied path.
*
* @param path the path that identifies the desired image (corresponds to the image path from
* the tileset).
* @param bounds if non-null, the region of the image to be returned as a mirage. If null, the
* entire image should be returned.
* @param zations if non-null, colorizations to apply to the image before converting it into a
* mirage.
*/
function getTileImage (path :String, bounds :Rectangle, zations :Array, callback :Function)
:void;
}
}
@@ -0,0 +1,31 @@
//
// 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.media.tile {
public class NoSuchTileSetError extends Error
{
public function NoSuchTileSetError (tileSet :*)
{
(tileSet is int) ?
super("No tile set with id '" + int(tileSet) + "'") :
super("No tile set named'" + String(tileSet) + "'");
}
}
}
@@ -0,0 +1,210 @@
//
// 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.media.tile {
import flash.geom.Point;
import com.threerings.media.tile.Tile;
import com.threerings.util.ArrayUtil;
import com.threerings.util.DirectionUtil;
import com.threerings.util.Integer;
import com.threerings.util.StringUtil;
public class ObjectTile extends Tile
{
/**
* Returns the object footprint width in tile units.
*/
public override function getBaseWidth () :int
{
return _base.x;
}
/**
* Returns the object footprint height in tile units.
*/
public override function getBaseHeight () :int
{
return _base.y;
}
/**
* Sets the object footprint in tile units.
*/
public function setBase (width :int, height :int) :void
{
_base.x = width;
_base.y = height;
}
/**
* Returns the x offset into the tile image of the origin (which will be aligned with the
* bottom center of the origin tile) or <code>Integer.MIN_VALUE</code> if the origin is not
* explicitly specified and should be computed from the image size and tile footprint.
*/
public override function getOriginX () :int
{
return _origin.x;
}
/**
* Returns the y offset into the tile image of the origin (which will be aligned with the
* bottom center of the origin tile) or <code>Integer.MIN_VALUE</code> if the origin is not
* explicitly specified and should be computed from the image size and tile footprint.
*/
public override function getOriginY () :int
{
return _origin.y;
}
/**
* Sets the offset in pixels from the origin of the tile image to the origin of the object.
* The object will be rendered such that its origin is at the bottom center of its origin
* tile. If no origin is specified, the bottom of the image is aligned with the bottom of the
* origin tile and the left side of the image is aligned with the left edge of the left-most
* base tile.
*/
public function setOrigin (x :int, y :int) :void
{
_origin.x = x;
_origin.y = y;
}
/**
* Returns this object tile's default render priority.
*/
public function getPriority () :int
{
return _priority;
}
/**
* Sets this object tile's default render priority.
*/
public function setPriority (priority :int) :void
{
_priority = priority;
}
/**
* Configures the "spot" associated with this object.
*/
public function setSpot (x :int, y :int, orient :int) :void
{
_spot = new Point(x, y);
_sorient = orient;
}
/**
* Returns true if this object has a spot.
*/
public function hasSpot () :Boolean
{
return (_spot != null);
}
/**
* Returns the x-coordinate of the "spot" associated with this object.
*/
public function getSpotX () :int
{
return (_spot == null) ? 0 : _spot.x;
}
/**
* Returns the x-coordinate of the "spot" associated with this object.
*/
public function getSpotY () :int
{
return (_spot == null) ? 0 : _spot.y;
}
/**
* Returns the orientation of the "spot" associated with this object.
*/
public function getSpotOrient () :int
{
return _sorient;
}
/**
* Returns the list of constraints associated with this object, or <code>null</code> if the
* object has no constraints.
*/
public function getConstraints () :Array
{
return _constraints;
}
/**
* Checks whether this object has the given constraint.
*/
public function hasConstraint (constraint :String) :Boolean
{
return (_constraints == null) ? false :
ArrayUtil.contains(_constraints, constraint);
}
/**
* Configures this object's constraints.
*/
public function setConstraints (constraints :Array) :void
{
_constraints = constraints;
}
protected override function toStringBuf (buf :String) :String
{
buf = super.toStringBuf(buf);
buf.concat(", base=", StringUtil.toString(_base));
buf.concat(", origin=", StringUtil.toString(_origin));
buf.concat(", priority=", _priority);
if (_spot != null) {
buf.concat(", spot=", StringUtil.toString(_spot));
buf.concat(", sorient=");
buf.concat(DirectionUtil.toShortString(_sorient));
}
if (_constraints != null) {
buf.concat(", constraints=", StringUtil.toString(_constraints));
}
return buf;
}
/** The object footprint width in unit tile units. */
protected var _base :Point = new Point(1, 1);
/** The offset from the origin of the tile image to the object's origin or MIN_VALUE if the
* origin should be calculated based on the footprint. */
protected var _origin :Point = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
/** This object tile's default render priority. */
protected var _priority :int;
/** The coordinates of the "spot" associated with this object. */
protected var _spot :Point;
/** The orientation of the "spot" associated with this object. */
protected var _sorient :int;
/** The list of constraints associated with this object. */
protected var _constraints :Array;
}
}
@@ -0,0 +1,302 @@
//
// 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.media.tile {
import com.threerings.util.ArrayUtil;
import com.threerings.util.StringUtil;
/**
* The object tileset supports the specification of object information for object tiles in
* addition to all of the features of the swiss army tileset.
*
* @see ObjectTile
*/
public class ObjectTileSet extends SwissArmyTileSet
implements RecolorableTileSet
{
/** A constraint prefix indicating that the object must have empty space in
* the suffixed direction (N, E, S, or W). */
public static const SPACE :String = "SPACE_";
/** A constraint indicating that the object is a surface (e.g., table). */
public static const SURFACE :String = "SURFACE";
/** A constraint indicating that the object must be placed on a surface. */
public static const ON_SURFACE :String = "ON_SURFACE";
/** A constraint prefix indicating that the object is a wall facing the
* suffixed direction (N, E, S, or W). */
public static const WALL :String = "WALL_";
/** A constraint prefix indicating that the object must be placed on a
* wall facing the suffixed direction (N, E, S, or W). */
public static const ON_WALL :String = "ON_WALL_";
/** A constraint prefix indicating that the object must be attached to a
* wall facing the suffixed direction (N, E, S, or W). */
public static const ATTACH :String = "ATTACH_";
/** The low suffix for walls and attachments. Low attachments can be placed
* on low or normal walls; normal attachments can only be placed on normal
* walls. */
public static const LOW :String = "_LOW";
/**
* Sets the widths (in unit tile count) of the objects in this tileset. This must be
* accompanied by a call to {@link #setObjectHeights}.
*/
public function setObjectWidths (objectWidths :Array) :void
{
_owidths = objectWidths;
}
/**
* Sets the heights (in unit tile count) of the objects in this tileset. This must be
* accompanied by a call to {@link #setObjectWidths}.
*/
public function setObjectHeights (objectHeights :Array) :void
{
_oheights = objectHeights;
}
/**
* Sets the x offset in pixels to the image origin.
*/
public function setXOrigins (xorigins :Array) :void
{
_xorigins = xorigins;
}
/**
* Sets the y offset in pixels to the image origin.
*/
public function setYOrigins (yorigins :Array) :void
{
_yorigins = yorigins;
}
/**
* Sets the default render priorities for our object tiles.
*/
public function setPriorities (priorities :Array) :void
{
_priorities = priorities;
}
/**
* Provides a set of colorization classes that apply to objects in this tileset.
*/
public function setColorizations (zations :Array) :void
{
_ozations = zations;
}
/**
* Sets the x offset to the "spots" associated with our object tiles.
*/
public function setXSpots (xspots :Array) :void
{
_xspots = xspots;
}
/**
* Sets the y offset to the "spots" associated with our object tiles.
*/
public function setYSpots (yspots :Array) :void
{
_yspots = yspots;
}
/**
* Sets the orientation of the "spots" associated with our object
* tiles.
*/
public function setSpotOrients (sorients :Array) :void
{
_sorients = sorients;
}
/**
* Sets the lists of constraints associated with our object tiles.
*/
public function setConstraints (constraints :Array) :void
{
_constraints = constraints;
}
/**
* Returns the x coordinate of the spot associated with the specified tile index.
*/
public function getXSpot (tileIdx :int) :int
{
return (_xspots == null) ? 0 : _xspots[tileIdx];
}
/**
* Returns the y coordinate of the spot associated with the specified tile index.
*/
public function getYSpot (tileIdx :int) :int
{
return (_yspots == null) ? 0 : _yspots[tileIdx];
}
/**
* Returns the orientation of the spot associated with the specified tile index.
*/
public function getSpotOrient (tileIdx :int) :int
{
return (_sorients == null) ? 0 : _sorients[tileIdx];
}
/**
* Returns the list of constraints associated with the specified tile index, or
* <code>null</code> if the index has no constraints.
*/
public function getConstraints (tileIdx :int) :Array
{
return (_constraints == null) ? null : _constraints[tileIdx];
}
/**
* Checks whether the tile at the specified index has the given constraint.
*/
public function hasConstraint (tileIdx :int, constraint :String) :Boolean
{
return (_constraints == null) ? false :
ArrayUtil.contains(_constraints[tileIdx], constraint);
}
// documentation inherited from interface RecolorableTileSet
public function getColorizations () :Array
{
return _ozations;
}
protected override function toStringBuf (buf :String) :String
{
buf = super.toStringBuf(buf);
buf = buf.concat(", owidths=", StringUtil.toString(_owidths));
buf = buf.concat(", oheights=", StringUtil.toString(_oheights));
buf = buf.concat(", xorigins=", StringUtil.toString(_xorigins));
buf = buf.concat(", yorigins=", StringUtil.toString(_yorigins));
buf = buf.concat(", prios=", StringUtil.toString(_priorities));
buf = buf.concat(", zations=", StringUtil.toString(_ozations));
buf = buf.concat(", xspots=", StringUtil.toString(_xspots));
buf = buf.concat(", yspots=", StringUtil.toString(_yspots));
buf = buf.concat(", sorients=", StringUtil.toString(_sorients));
buf = buf.concat(", constraints=", StringUtil.toString(_constraints));
return buf;
}
protected override function getTileColorizations (tileIndex :int, rizer :Colorizer) :Array
{
var zations :Array = null;
if (rizer != null && _ozations != null) {
zations = new Array(_ozations.length);
for (var ii :int = 0; ii < _ozations.length; ii++) {
zations[ii] = rizer.getColorization(ii, _ozations[ii]);
}
}
return zations;
}
protected override function createTile () :Tile
{
return new ObjectTile();
}
protected override function initTile (tile :Tile, tileIndex :int, zations :Array) :void
{
super.initTile(tile, tileIndex, zations);
var otile :ObjectTile = ObjectTile(tile);
if (_owidths != null) {
otile.setBase(_owidths[tileIndex], _oheights[tileIndex]);
}
if (_xorigins != null) {
otile.setOrigin(_xorigins[tileIndex], _yorigins[tileIndex]);
}
if (_priorities != null) {
otile.setPriority(_priorities[tileIndex]);
}
if (_xspots != null) {
otile.setSpot(_xspots[tileIndex], _yspots[tileIndex], _sorients[tileIndex]);
}
if (_constraints != null) {
otile.setConstraints(_constraints[tileIndex]);
}
}
public static function fromXml (xml :XML) :SwissArmyTileSet
{
var set :ObjectTileSet = new ObjectTileSet();
set.populateFromXml(xml);
return set;
}
protected override function populateFromXml (xml :XML) :void
{
super.populateFromXml(xml);
_owidths = toIntArray(xml.objectWidths);
_oheights = toIntArray(xml.objectHeights);
_xorigins = toIntArray(xml.xOrigins);
_yorigins = toIntArray(xml.yOrigins);
_priorities = toIntArray(xml.priorities);
_ozations = toStrArray(xml.zations);
_xspots = toIntArray(xml.xSpots);
_yspots = toIntArray(xml.ySpots);
_sorients = toIntArray(xml.sorients);
var constraintStrArr :Array = toStrArray(xml.constraints);
_constraints = constraintStrArr.map(function(element :*, index :int, arr :Array) :Array {
return element.split("|");
});
}
/** The width (in tile units) of our object tiles. */
protected var _owidths :Array;
/** The height (in tile units) of our object tiles. */
protected var _oheights :Array;
/** The x offset in pixels to the origin of the tile images. */
protected var _xorigins :Array;
/** The y offset in pixels to the origin of the tile images. */
protected var _yorigins :Array;
/** The default render priorities of our objects. */
protected var _priorities :Array;
/** Colorization classes that apply to our objects. */
protected var _ozations :Array;
/** The x offset to the "spots" associated with our tiles. */
protected var _xspots :Array;
/** The y offset to the "spots" associated with our tiles. */
protected var _yspots :Array;
/** The orientation of the "spots" associated with our tiles. */
protected var _sorients :Array;
/** Lists of constraints associated with our tiles. */
protected var _constraints :Array;
}
}
@@ -0,0 +1,30 @@
//
// 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.media.tile {
public interface RecolorableTileSet
{
/**
* Returns the colorization classes that should be used to recolor
* objects in this tileset.
*/
function getColorizations () :Array
}
}
@@ -0,0 +1,237 @@
//
// $Id: SwissArmyTileSet.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.media.tile {
import flash.geom.Point;
import flash.geom.Rectangle;
import com.threerings.util.StringUtil;
/**
* The swiss army tileset supports a diverse variety of tiles in the tileset image. Each row can
* contain varying numbers of tiles and each row can have its own width and height. Tiles can be
* separated from the edge of the tileset image by some border offset and can be separated from one
* another by a gap distance.
*/
public class SwissArmyTileSet extends TileSet
{
public override function getTileCount () :int
{
return _numTiles;
}
public override function computeTileBounds (tileIndex :int) :Rectangle
{
// find the row number containing the sought-after tile
var ridx :int;
var tcount :int;
var ty :int;
var tx :int;
ridx = tcount = 0;
// start tile image position at image start offset
tx = _offsetPos.x;
ty = _offsetPos.y;
while ((tcount += _tileCounts[ridx]) < tileIndex + 1) {
// increment tile image position by row height and gap distance
ty += (_heights[ridx++] + _gapSize.y);
}
// determine the horizontal index of this tile in the row
var xidx :int = tileIndex - (tcount - _tileCounts[ridx]);
// final image x-position is based on tile width and gap distance
tx += (xidx * (_widths[ridx] + _gapSize.x));
// Log.info("Computed tile bounds [tileIndex=" + tileIndex +
// ", ridx=" + ridx + ", xidx=" + xidx + ", tx=" + tx + ", ty=" + ty + "].");
// crop the tile-sized image chunk from the full image
return new Rectangle(tx, ty, _widths[ridx], _heights[ridx]);
}
/**
* Sets the tile counts which are the number of tiles in each row of the tileset image. Each
* row can have an arbitrary number of tiles.
*/
public function setTileCounts (tileCounts :Array) :void
{
_tileCounts = tileCounts;
// compute our total tile count
computeTileCount();
}
/**
* Returns the tile count settings.
*/
public function getTileCounts () :Array
{
return _tileCounts;
}
/**
* Computes our total tile count from the individual counts for each row.
*/
protected function computeTileCount () :void
{
// compute our number of tiles
_numTiles = 0;
for each (var count :int in _tileCounts) {
_numTiles += count;
}
}
/**
* Sets the tile widths for each row. Each row can have tiles of a different width.
*/
public function setWidths (widths :Array) :void
{
_widths = widths;
}
/**
* Returns the width settings.
*/
public function getWidths () :Array
{
return _widths;
}
/**
* Sets the tile heights for each row. Each row can have tiles of a different height.
*/
public function setHeights (heights :Array) :void
{
_heights = heights;
}
/**
* Returns the height settings.
*/
public function getHeights () :Array
{
return _heights;
}
/**
* Sets the offset in pixels of the upper left corner of the first tile in the first row. If
* the tileset image has a border, this can be set to account for it.
*/
public function setOffsetPos (offsetPos :Point) :void
{
_offsetPos = offsetPos;
}
/**
* Sets the size of the gap between tiles (in pixels). If the tiles have space between them,
* this can be set to account for it.
*/
public function setGapSize (gapSize :Point) :void
{
_gapSize = gapSize;
}
protected override function toStringBuf (buf :String) :String
{
buf = super.toStringBuf(buf);
buf = buf.concat(", widths=", StringUtil.toString(_widths));
buf = buf.concat(", heights=", StringUtil.toString(_heights));
buf = buf.concat(", tileCounts=", StringUtil.toString(_tileCounts));
buf = buf.concat(", offsetPos=", StringUtil.toString(_offsetPos));
buf = buf.concat(", gapSize=", StringUtil.toString(_gapSize));
return buf;
}
public static function fromXml (xml :XML) :SwissArmyTileSet
{
var set :SwissArmyTileSet = new SwissArmyTileSet();
set.populateFromXml(xml);
return set;
}
protected override function populateFromXml (xml :XML) :void
{
super.populateFromXml(xml);
_tileCounts = toIntArray(xml.tileCounts);
_widths = toIntArray(xml.widths);
_heights = toIntArray(xml.heights);
var offsetPosArr :Array = toIntArray(xml.offsetPos);
_offsetPos = new Point(offsetPosArr[0], offsetPosArr[1]);
var gapSizeArr :Array = toIntArray(xml.gapSize);
_gapSize = new Point(gapSizeArr[0], gapSizeArr[1]);
computeTileCount();
}
protected static function toStrArray (str :String) :Array
{
if (str == null) {
return null;
}
return str.split(",");
}
protected static function toBoolArray (str :String) :Array
{
if (str == null) {
return null;
}
return str.split(",").map(function(element :*, index :int, arr :Array) :Boolean {
return Boolean(element);
});
}
protected static function toIntArray (str :String) :Array
{
if (str == null) {
return null;
}
return str.split(",").map(function(element :*, index :int, arr :Array) :int {
return int(element);
});
}
/** The number of tiles in each row. */
protected var _tileCounts :Array;
/** The number of tiles in the tileset. */
protected var _numTiles :int;
/** The width of the tiles in each row in pixels. */
protected var _widths :Array;
/** The height of the tiles in each row in pixels. */
protected var _heights :Array;
/** The offset distance (x, y) in pixels from the top-left of the image to the start of the
* first tile image. */
protected var _offsetPos :Point = new Point();
/** The distance (x, y) in pixels between each tile in each row horizontally, and between each
* row of tiles vertically. */
protected var _gapSize :Point = new Point();
}
}
+147
View File
@@ -0,0 +1,147 @@
//
// 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.media.tile {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
public class Tile
{
/** The key associated with this tile. */
public var key :Tile_Key;
/**
* Configures this tile with its tile image.
*/
public function setImage (image :DisplayObject) :void
{
_image = image;
// Notify them all and clear our list.
for each (var func :Function in _notifyOnLoad) {
func(this);
}
}
public function getImage () :DisplayObject
{
if (_image is Bitmap) {
// TODO - handle this more consistently...
var data :BitmapData = new BitmapData(_image.width, _image.height, true, 0x00000000);
data.draw(_image);
return new Bitmap(data);
} else {
return _image;
}
}
/**
* Returns the width of this tile.
*/
public function getWidth () :int
{
return _image.width;
}
/**
* Returns the height of this tile.
*/
public function getHeight () :int
{
return _image.height;
}
/**
* Returns true if the specified coordinates within this tile contains
* a non-transparent pixel.
*/
public function hitTest (x :int, y :int) :Boolean
{
return _image.hitTestPoint(x, y, true);
}
public function toString () :String
{
return "[" + toStringBuf(new String()) + "]";
}
/**
* This should be overridden by derived classes (which should be sure
* to call <code>super.toString()</code>) to append the derived class
* specific tile information to the string buffer.
*/
protected function toStringBuf (buf :String) :String
{
if (_image == null) {
return buf.concat("null-image");
} else {
return buf.concat(_image.width, "x", _image.height);
}
}
public function notifyOnLoad (func :Function) :void
{
_notifyOnLoad.push(func);
}
/**
* Returns the x offset into the tile image of the origin (which will be aligned with the
* bottom center of the origin tile) or <code>Integer.MIN_VALUE</code> if the origin is not
* explicitly specified and should be computed from the image size and tile footprint.
*/
public function getOriginX () :int
{
throw new Error("abstract");
}
/**
* Returns the y offset into the tile image of the origin (which will be aligned with the
* bottom center of the origin tile) or <code>Integer.MIN_VALUE</code> if the origin is not
* explicitly specified and should be computed from the image size and tile footprint.
*/
public function getOriginY () :int
{
throw new Error("abstract")
}
/**
* Returns the object footprint width in tile units.
*/
public function getBaseWidth () :int
{
throw new Error("abstract");
}
/**
* Returns the object footprint height in tile units.
*/
public function getBaseHeight () :int
{
throw new Error("abstract");
}
/** Our tileset image. */
protected var _image :DisplayObject;
/** Everyone who cares when we're loaded. */
protected var _notifyOnLoad :Array = [];
}
}
@@ -0,0 +1,108 @@
//
// 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.media.tile {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.events.Event;
import flash.utils.ByteArray;
import nochump.util.zip.ZipEntry;
import nochump.util.zip.ZipError;
import nochump.util.zip.ZipFile;
import com.threerings.util.DataPack;
import com.threerings.util.MultiLoader;
/**
* Like a normal data pack, but we don't deal with any data, and all our filenames are a direct
* translation, so we need no metadata file. We also serve as a tile ImageProvider.
*/
public class TileDataPack extends DataPack
implements ImageProvider
{
public function TileDataPack (
source :Object, completeListener :Function = null, errorListener :Function = null)
{
super(source, completeListener, errorListener);
}
protected override function bytesAvailable (bytes :ByteArray) :void
{
bytes.position = 0;
try {
_zip = new ZipFile(bytes);
} catch (zipError :ZipError) {
dispatchError("Unable to read datapack: " + zipError.message);
return;
}
// Put something there so we know we're loaded.
_metadata = <xml></xml>;
// yay, we're completely loaded!
dispatchEvent(new Event(Event.COMPLETE));
}
/**
* We have no metadata, so everything is undefined.
*/
public override function getData (name :String, formatType :String = null) :*
{
return undefined;
}
/**
* We have no XML metadata, so our filename is exactly the original name.
*/
protected override function getFileName (name :String) :String
{
return name;
}
public function getTileSetImage (path :String, zations :Array, callback :Function) :void
{
// TODO - DO SOMETHING WITH ZATIONS
getDisplayObjects(path, callback);
}
public function getTileImage (path :String, bounds :Rectangle, zations :Array,
callback :Function) :void
{
getTileSetImage(path, zations, function(result :DisplayObject) :void {
// TODO - DO SOMETHING TO SUB_REGION THIS
if (result is Bitmap) {
var data :BitmapData =
new BitmapData(bounds.width, bounds.height, true, 0x00000000);
data.copyPixels(Bitmap(result).bitmapData, bounds, new Point(0, 0));
callback(new Bitmap(data));
} else {
callback(result);
}
});
}
}
}
@@ -0,0 +1,138 @@
//
// 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.media.tile {
import com.threerings.util.Log;
/**
* The tile manager provides a simplified interface for retrieving and caching tiles. Tiles can be
* loaded in two different ways. An application can load a tileset by hand, specifying the path to
* the tileset image and all of the tileset metadata necessary for extracting the image tiles, or
* it can provide a tileset repository which loads up tilesets using whatever repository mechanism
* is implemented by the supplied repository. In the latter case, tilesets are loaded by a unique
* identifier.
*
* <p> Loading tilesets by hand is intended for things like toolbar icons or games with a single
* set of tiles (think Stratego, for example). Loading tilesets from a repository supports games
* with vast numbers of tiles to which more tiles may be added on the fly (think the tiles for an
* isometric-display graphical MUD).
*/
public class TileManager
{
private static var log :Log = Log.getLog(TileManager);
/**
* Sets the tileset repository that will be used by the tile manager when tiles are requested
* by tileset id.
*/
public function setTileSetRepository (setrep :TileSetRepository) :void
{
_setrep = setrep;
}
/**
* Returns the tileset repository currently in use.
*/
public function getTileSetRepository () :TileSetRepository
{
return _setrep;
}
/**
* Returns the tileset with the specified id. Tilesets are fetched from the tileset repository
* supplied via {@link #setTileSetRepository}, and are subsequently cached.
*
* @param tileSetId the unique identifier for the desired tileset.
*
* @exception NoSuchTileSetError thrown if no tileset exists with the specified id or if
* an underlying error occurs with the tileset repository's persistence mechanism.
*/
public function getTileSet (tileSetId :int) :TileSet
{
// make sure we have a repository configured
if (_setrep == null) {
throw new NoSuchTileSetError(tileSetId);
}
try {
return _setrep.getTileSet(tileSetId);
} catch (pe :Error) {
log.warning("Failure loading tileset", "id", tileSetId, pe);
throw new NoSuchTileSetError(tileSetId);
}
// Unreachable.
return null;
}
/**
* Returns the tileset with the specified name.
*
* @throws NoSuchTileSetError if no tileset with the specified name is available via our
* configured tile set repository.
*/
public function getTileSetByName (name :String) :TileSet
{
// make sure we have a repository configured
if (_setrep == null) {
throw new NoSuchTileSetError(name);
}
try {
return _setrep.getTileSetByName(name);
} catch (pe :Error) {
log.warning("Failure loading tileset", "name", name, "error", pe);
throw new NoSuchTileSetError(name);
}
// Unreachable.
return null;
}
/**
* Returns the {@link Tile} object with the specified fully qualified tile id. The supplied
* colorizer will be used to recolor the tile.
*
* @see TileUtil#getFQTileId
*/
public function getTile (fqTileId :int, rizer :Colorizer = null) :Tile
{
return getTileBySet(TileUtil.getTileSetId(fqTileId),
TileUtil.getTileIndex(fqTileId), rizer);
}
/**
* Returns the {@link Tile} object from the specified tileset at the specified index.
*
* @param tileSetId the tileset id.
* @param tileIndex the index of the tile to be retrieved.
*
* @return the tile object.
*/
public function getTileBySet (tileSetId :int, tileIndex :int, rizer :Colorizer) :Tile
{
var set :TileSet = getTileSet(tileSetId);
return set.getTile(tileIndex, rizer);
}
/** The tile set repository. */
protected var _setrep :TileSetRepository;
}
}
+368
View File
@@ -0,0 +1,368 @@
//
// 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.media.tile {
import flash.display.DisplayObject;
import flash.geom.Rectangle;
import com.threerings.display.ImageUtil;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.Streamable;
import com.threerings.media.image.Colorization;
import com.threerings.util.Hashable;
import com.threerings.util.Log;
import com.threerings.util.StringUtil;
import com.threerings.util.Throttle;
import com.threerings.util.maps.HashMap;
import com.threerings.util.maps.WeakValueMap;
public /* abstract */ class TileSet
implements Streamable, Hashable
{
private static var log :Log = Log.getLog(TileSet);
public function readObject (oin :ObjectInputStream) :void
{
_imagePath = oin.readUTF();
_name = oin.readUTF();
}
public function writeObject (oout :ObjectOutputStream) :void
{
oout.writeUTF(_imagePath);
oout.writeUTF(_name);
}
/**
* Configures this tileset with an image provider that it can use to load its tileset image.
* This will be called automatically when the tileset is fetched via the {@link TileManager}.
*/
public function setImageProvider (improv :ImageProvider) :void
{
_improv = improv;
if (_improv != null) {
for each (var arr :Array in _pending) {
initTile(arr[0], arr[1], arr[2]);
}
}
_pending = [];
}
/**
* Returns the tileset name.
*/
public function getName () :String
{
return (_name == null) ? _imagePath : _name;
}
/**
* Specifies the tileset name.
*/
public function setName (name :String) :void
{
_name = name;
}
public function hashCode () :int
{
return StringUtil.hashCode(getName());
}
public function equals (other :Object) :Boolean
{
return other === this;
}
/**
* Sets the path to the image that will be used by this tileset. This must be called before the
* first call to {@link #getTile}.
*/
public function setImagePath (imagePath :String) :void
{
_imagePath = imagePath;
}
/**
* Returns the path to the composite image used by this tileset.
*/
public function getImagePath () :String
{
return _imagePath;
}
/**
* Returns the number of tiles in the tileset.
*/
public function getTileCount () :int
{
throw new Error("abstract");
}
/**
* Computes and fills in the bounds for the specified tile based on the mechanism used by the
* derived class to do such things. The width and height of the bounds should be the size of
* the tile image and the x and y offset should be the offset in the tileset image for the
* image data of the specified tile.
*
* @param tileIndex the index of the tile whose bounds are to be computed.
* @param bounds the rectangle object into which to fill the bounds.
*
* @return the rectangle passed into the bounds parameter.
*/
public function computeTileBounds (tileIndex :int) :Rectangle
{
throw new Error("abstract");
}
/**
* Creates a {@link Tile} object from this tileset corresponding to the specified tile id and
* returns that tile. A null tile will never be returned, but one with an error image may be
* returned if a problem occurs loading the underlying tileset image.
*
* @param tileIndex the index of the tile in the tileset. Tile indexes start with zero as the
* upper left tile and increase by one as the tiles move left to right and top to bottom over
* the source image.
* @param zations colorizations to be applied to the tile image prior to returning it. These
* may be null for uncolorized images.
*
* @return the tile object.
*/
public function getTile (tileIndex :int, zations :* = null) :Tile
{
// Default to using our default tileset colorizations.
if (zations == null) {
zations = _zations;
} else if (zations is Colorizer) {
zations = getTileColorizations(tileIndex, zations);
}
var tile :Tile = null;
// first look in the active set; if it's in use by anyone or in the cache, it will be in
// the active set
var key :Tile_Key = new Tile_Key(this, tileIndex, zations);
tile = _atiles.get(key);
// if it's not in the active set, it's not in memory; so load it
if (tile == null) {
tile = createTile();
tile.key = new Tile_Key(this, tileIndex, zations);
initTile(tile, tileIndex, zations);
_atiles.put(tile.key, tile);
}
// periodically report our image cache performance
reportCachePerformance();
return tile;
}
/**
* Returns a prepared version of the image that would be used by the tile at the specified
* index. Because tilesets are often used simply to provide access to a collection of uniform
* images, this method is provided to bypass the creation of a {@link Tile} object when all
* that is desired is access to the underlying image.
*/
public function getTileImage (tileIndex :int, zations :Array, callback :Function)
:void
{
// If they weren't specified, get the default zations for this tile.
if (zations == null) {
zations = getTileColorizations(tileIndex, null);
}
var bounds :Rectangle = computeTileBounds(tileIndex);
var image :DisplayObject = null;
if (checkTileIndex(tileIndex)) {
if (_improv == null) {
log.warning("Aiya! Tile set missing image provider [path=" + _imagePath + "].");
callback(ImageUtil.createErrorImage(bounds.width, bounds.height));
} else {
_improv.getTileImage(_imagePath, bounds, zations,
function(result :DisplayObject) :void {
if (result == null) {
result = ImageUtil.createErrorImage(bounds.width, bounds.height);
}
callback(result);
});
}
} else {
callback(ImageUtil.createErrorImage(bounds.width, bounds.height));
}
}
/**
* Returns colorizations for the specified tile image. The default is to return any
* colorizations associated with the tileset via a call to {@link #clone(Colorization[])},
* however derived classes may have dynamic colorization policies that look up colorization
* assignments from the supplied colorizer.
*/
protected function getTileColorizations (tileIndex :int, rizer :Colorizer) :Array
{
return _zations;
}
/**
* Used to ensure that the specified tile index is valid.
*/
protected function checkTileIndex (tileIndex :int) :Boolean
{
var tcount :int = getTileCount();
if (tileIndex >= 0 && tileIndex < tcount) {
return true;
} else {
log.warning("Requested invalid tile [tset=" + this + ", index=" + tileIndex + "].",
new Error());
return false;
}
}
/**
* Creates a blank tile of the appropriate type for this tileset.
*
* @return a blank tile ready to be populated with its image and metadata.
*/
protected function createTile () :Tile
{
return new Tile();
}
/**
* Initializes the supplied tile. Derived classes can override this method to add
* in their own tile information, but should be sure to call <code>super.initTile()</code>.
*
* @param tile the tile to initialize.
* @param tileIndex the index of the tile.
* @param zations the colorizations to be used when generating the tile image.
*/
protected function initTile (tile :Tile, tileIndex :int, zations :Array) :void
{
if (_improv != null) {
getTileImage(tileIndex, zations, function(result :DisplayObject) :void {
tile.setImage(result);
});
} else {
_pending.push([tile, tileIndex, zations]);
}
}
/**
* Reports statistics detailing the image manager cache performance and the current size of the
* cached images.
*/
protected function reportCachePerformance () :void
{
if (_improv == null ||
_cacheStatThrottle.throttleOp()) {
return;
}
// compute our estimated memory usage
var amem :int = 0;
var asize :int = 0;
// first total up the active tiles
for each (var tile :Tile in _atiles.values()) {
if (tile != null) {
asize++;
}
}
log.info("Tile caches [seen=" + _atiles.size() + ", asize=" + asize + "].");
}
public function toString () :String
{
return "[" + toStringBuf(new String()) + "]";
}
/**
* Derived classes can override this, calling <code>super.toString(buf)</code> and then
* appending additional information to the buffer.
*/
protected function toStringBuf (buf :String) :String
{
buf = buf.concat("name=", _name);
buf = buf.concat(", path=", _imagePath);
buf = buf.concat(", tileCount=", getTileCount());
return buf;
}
public function isLoaded () :Boolean
{
return _isLoaded;
}
public function loaded () :void
{
_isLoaded = true;
// Notify them all and clear our list.
for each (var func :Function in _notifyOnLoad) {
func(this);
}
_notifyOnLoad = [];
}
public function notifyOnLoad (func :Function) :void
{
if (isLoaded()) {
func(this);
} else {
_notifyOnLoad.push(func);
}
}
protected function populateFromXml (xml :XML) :void
{
_name = xml.@name;
_imagePath = xml.imagePath;
}
/** Whether all the media for this tileset is loaded and ready. */
protected var _isLoaded :Boolean;
/** The path to the file containing the tile images. */
protected var _imagePath :String;
/** The tileset name. */
protected var _name :String;
/** Colorizations to be applied to tiles created from this tileset. */
protected var _zations :Array; /* of */ Colorization;
/** The entity from which we obtain our tile image. */
protected var _improv :ImageProvider;
/** Everyone who cares when we're loaded. */
protected var _notifyOnLoad :Array = [];
/** Tiles awaiting an image provider. */
protected var _pending :Array = [];
/** A map containing weak references to all "active" tiles. */
protected static var _atiles :WeakValueMap = new WeakValueMap(new HashMap());
/** Throttle our cache status logging to once every 300 seconds. */
protected static var _cacheStatThrottle :Throttle = new Throttle(1, 300000);
}
}
@@ -0,0 +1,29 @@
//
// 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.media.tile {
public interface TileSetIdMap
{
/**
* Returns the unique identifier for the named tileset.
*/
function getTileSetId (tileSetName :String) :int
}
}
@@ -0,0 +1,70 @@
//
// 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.media.tile {
public interface TileSetRepository {
/**
* Returns an iterator over the identifiers of all {@link TileSet}
* objects available.
*/
function enumerateTileSetIds () :Array;
/**
* Returns an iterator over all {@link TileSet} objects available.
*/
function enumerateTileSets () :Array;
/**
* Returns the {@link TileSet} with the specified tile set
* identifier. The repository is responsible for configuring the tile
* set with an image provider.
*
* @exception NoSuchTileSetException thrown if no tileset exists with
* the specified identifier.
* @exception PersistenceException thrown if an error occurs
* communicating with the underlying persistence mechanism.
*/
function getTileSet (tileSetId :int) :TileSet;
/**
* Returns the unique identifier of the {@link TileSet} with the
* specified tile set name.
*
* @exception NoSuchTileSetException thrown if no tileset exists with
* the specified name.
* @exception PersistenceException thrown if an error occurs
* communicating with the underlying persistence mechanism.
*/
function getTileSetId (setName :String) :int;
/**
* Returns the {@link TileSet} with the specified tile set name. The
* repository is responsible for configuring the tile set with an
* image provider.
*
* @exception NoSuchTileSetException thrown if no tileset exists with
* the specified name.
* @exception PersistenceException thrown if an error occurs
* communicating with the underlying persistence mechanism.
*/
function getTileSetByName (setName :String) :TileSet;
}
}
@@ -0,0 +1,65 @@
//
// 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.media.tile {
import com.threerings.media.image.Colorization;
import com.threerings.util.ArrayUtil;
import com.threerings.util.Hashable;
/** Used when caching tiles. */
public class Tile_Key
implements Hashable
{
public var tileSet :TileSet;
public var tileIndex :int;
public var zations :Array;
public function Tile_Key (tileSet :TileSet, tileIndex :int, zations :Array) {
this.tileSet = tileSet;
this.tileIndex = tileIndex;
this.zations = zations;
}
public function equals (other :Object) :Boolean
{
if (other is Tile_Key) {
var okey :Tile_Key = Tile_Key(other);
return (tileSet == okey.tileSet &&
tileIndex == okey.tileIndex &&
ArrayUtil.equals(zations, okey.zations));
} else {
return false;
}
}
public function hashCode () :int
{
var code :int = (tileSet == null) ? tileIndex :
(tileSet.hashCode() ^ tileIndex);
var zcount :int = (zations == null) ? 0 : zations.length;
for each (var zation :Colorization in zations) {
if (zation != null) {
code ^= zation.hashCode();
}
}
return code;
}
}
}
@@ -0,0 +1,66 @@
//
// 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.media.tile.bundle {
import flash.display.DisplayObject;
import com.threerings.io.ObjectOutputStream;
import com.threerings.io.ObjectInputStream;
import com.threerings.io.Streamable;
import com.threerings.util.DataPack;
import com.threerings.util.maps.DictionaryMap;
import com.threerings.media.tile.BaseTileSet;
import com.threerings.media.tile.ObjectTileSet;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.TileSetIdMap;
public class TileSetBundle extends DictionaryMap
{
public function init (pack :DataPack) :void
{
_pack = pack;
}
public static function fromXml (xml :XML, idMap :TileSetIdMap) :TileSetBundle
{
var bundle :TileSetBundle = new TileSetBundle();
for each (var objXml :XML in xml.object.tileset) {
var objId :int = idMap.getTileSetId(objXml.@name);
bundle.put(objId, ObjectTileSet.fromXml(objXml));
}
for each (var baseXml :XML in xml.base.tileset) {
var baseId :int = idMap.getTileSetId(baseXml.@name);
bundle.put(baseId, BaseTileSet.fromXml(baseXml));
}
return bundle;
}
/**
* Loads the image from our data pack.
*/
public function loadImage (path :String) :DisplayObject
{
return DisplayObject(_pack.getFile(path));
}
/** The data pack from which we can grab images. */
protected var _pack :DataPack;
}
}
@@ -1,20 +1,40 @@
//
// 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.client {
import as3isolib.display.primitive.IsoBox;
import as3isolib.graphics.SolidColorFill;
import com.threerings.media.tile.Tile;
import com.threerings.miso.util.MisoSceneMetrics;
public class BaseTileIsoSprite extends IsoBox
public class BaseTileIsoSprite extends TileIsoSprite
{
public function BaseTileIsoSprite (x :int, y :int, tileId :int)
public function BaseTileIsoSprite (x :int, y :int, tileId :int, tile :Tile,
metrics :MisoSceneMetrics)
{
width = 1;
height = VERT_OFFSET;
length = 1;
super(x, y, tileId, tile, metrics);
}
moveTo(x, y, -VERT_OFFSET);
public override function layout (x :int, y :int, tile :Tile) :void
{
super.layout(x, y, tile);
// TEMP
fill = new SolidColorFill(tileId * 1000, 1.0);
setSize(1, 1, VERT_OFFSET);
}
protected static const VERT_OFFSET :Number = 0.01;
@@ -1,9 +1,30 @@
//
// 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.client {
import flash.utils.getTimer;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
@@ -11,6 +32,9 @@ import flash.events.MouseEvent;
import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.media.tile.NoSuchTileSetError;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.TileUtil;
import com.threerings.miso.client.MisoMetricsTransformation;
import com.threerings.miso.data.MisoSceneModel;
import com.threerings.miso.data.ObjectInfo;
@@ -30,10 +54,13 @@ public class MisoScenePanel extends Sprite
{
public function MisoScenePanel (ctx :MisoContext, metrics :MisoSceneMetrics)
{
_ctx = ctx;
// Excitingly, we get to override this globally for as3isolib...
IsoMath.transformationObject = new MisoMetricsTransformation(metrics,
metrics.tilehei * 3 / 4);
_metrics = metrics;
_isoView = new IsoView();
_isoView.setSize(DEF_WIDTH, DEF_HEIGHT);
@@ -42,11 +69,6 @@ public class MisoScenePanel extends Sprite
addChild(_isoView);
}
public function setSize (width :int, height :int) :void
{
_isoView.setSize(width, height);
}
public function onClick (event :MouseEvent) :void
{
var viewPt :Point = _isoView.globalToLocal(new Point(event.stageX, event.stageY));
@@ -78,13 +100,43 @@ public class MisoScenePanel extends Sprite
var time :int = getTimer();
var baseArr :Array = [];
for (var si :int = -10; si < 3; si++) {
for (var sj :int = -8; sj < 4; sj++) {
for (var si :int = -2; si < 4; si++) {
for (var sj :int = -1; sj < 3; sj++) {
var baseScene :IsoScene = new IsoScene();
for (var ii :int = 10*si; ii < 10*si + 10; ii++) {
for (var jj :int = 10*sj; jj < 10*sj + 10; jj++) {
var tileId :int = _model.getBaseTileId(ii, jj);
if (tileId <= 0) {
var defSet :TileSet;
try {
var setId :int = _model.getDefaultBaseTileSet();
defSet = _ctx.getTileManager().getTileSet(setId);
tileId = TileUtil.getFQTileId(setId,
TileUtil.getTileHash(ii, jj) % defSet.getTileCount());
} catch (err :NoSuchTileSetError) {
// Someone else already complained...
continue;
}
}
var tileSet :TileSet;
try {
tileSet =
_ctx.getTileManager().getTileSet(TileUtil.getTileSetId(tileId));
} catch (err :NoSuchTileSetError) {
// Someone else already complained...
continue;
}
if (tileSet == null) {
trace("TileManager returned null tilset: " +
TileUtil.getTileSetId(tileId));
continue;
}
baseScene.addChild(
new BaseTileIsoSprite(ii, jj, _model.getBaseTileId(ii, jj)));
new BaseTileIsoSprite(ii, jj, tileId,
tileSet.getTile(TileUtil.getTileIndex(tileId)), _metrics));
}
}
baseScene.render();
@@ -97,9 +149,24 @@ public class MisoScenePanel extends Sprite
time = getTimer();
for (ii = 0; ii < set.size(); ii++) {
var objInfo :ObjectInfo = set.get(ii);
if (objInfo.priority == 0) {
scene.addChild(new ObjectTileIsoSprite(objInfo.x, objInfo.y, objInfo.tileId));
var objTileId :int = objInfo.tileId;
var objTileSet :TileSet;
try {
objTileSet =
_ctx.getTileManager().getTileSet(TileUtil.getTileSetId(objTileId));
} catch (err :NoSuchTileSetError) {
// Someone else already complained...
continue;
}
if (objTileSet == null) {
trace("TileManager returned null TileSet: " + TileUtil.getTileSetId(objTileId));
continue;
}
scene.addChild(
new ObjectTileIsoSprite(objInfo.x, objInfo.y, objTileId,
objTileSet.getTile(TileUtil.getTileIndex(objTileId)), _metrics));
}
time = getTimer();
@@ -112,6 +179,10 @@ public class MisoScenePanel extends Sprite
protected var _isoView :IsoView;
protected var _ctx :MisoContext;
protected var _metrics :MisoSceneMetrics;
protected const DEF_WIDTH :int = 985;
protected const DEF_HEIGHT :int = 560;
}
@@ -1,20 +1,41 @@
//
// 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.client {
import as3isolib.display.primitive.IsoBox;
import as3isolib.graphics.SolidColorFill;
import com.threerings.media.tile.Tile;
import com.threerings.miso.util.MisoSceneMetrics;
public class ObjectTileIsoSprite extends IsoBox
public class ObjectTileIsoSprite extends TileIsoSprite
{
public function ObjectTileIsoSprite (x :int, y :int, tileId :int)
public function ObjectTileIsoSprite (x :int, y :int, tileId :int, tile :Tile,
metrics :MisoSceneMetrics)
{
width = 1;
height = 1;
length = 1;
super(x, y, tileId, tile, metrics);
}
moveTo(x, y, 0);
public override function layout (x :int, y :int, tile :Tile) :void
{
super.layout(x, y, tile);
// TEMP
fill = new SolidColorFill(tileId * 1000, 1.0);
setSize(tile.getBaseWidth(), tile.getBaseHeight(), 1);
moveBy(-(tile.getBaseWidth() - 1), -(tile.getBaseHeight() - 1), 0);
}
}
}
@@ -0,0 +1,100 @@
//
// 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.client {
import flash.display.DisplayObject;
import as3isolib.core.IsoDisplayObject;
import as3isolib.display.IsoSprite;
import as3isolib.display.primitive.IsoBox;
import as3isolib.graphics.SolidColorFill;
import com.threerings.media.tile.Tile;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.TileUtil;
import com.threerings.util.Log;
import com.threerings.miso.util.MisoSceneMetrics;
public class TileIsoSprite extends IsoDisplayObject
{
private static var log :Log = Log.getLog(TileIsoSprite);
public function TileIsoSprite (x :int, y :int, tileId :int, tile :Tile,
metrics :MisoSceneMetrics)
{
_tileId = tileId;
_metrics = metrics;
moveTo(x, y, 0);
layout(x, y, tile);
if (tile.getImage() == null) {
var box :IsoBox = new IsoBox();
box.width = width;
box.height = height;
box.length = length;
box.fill = new SolidColorFill(0x808080, 0.5);
addChild(box);
} else {
addSprite(tile);
}
tile.notifyOnLoad(loaded);
}
public function layout (x :int, y :int, tile :Tile) :void
{
moveTo(x, y, 0);
}
/**
* Our tile was loaded, set ourselves up appropriately to use it.
*/
public function loaded (tile :Tile) :void
{
removeAllChildren();
addSprite(tile);
}
protected function addSprite (tile :Tile) :void
{
var sprite :IsoSprite = new IsoSprite();
var image :DisplayObject = tile.getImage();
if (image == null) {
log.warning("TileIsoSprite tile image is null", "tileId", _tileId);
return;
}
// as3isolib uses top instead of bottom.
image.x = -tile.getOriginX() + _metrics.tilewid *
((tile.getBaseWidth() - tile.getBaseHeight())/2);;
image.y = -tile.getOriginY() + _metrics.tilehei *
(1 + (tile.getBaseWidth() + tile.getBaseHeight())/2);
sprite.sprites = [image];
sprite.setSize(tile.getBaseWidth(), tile.getBaseHeight(), 1);
addChild(sprite);
render();
}
protected var _tileId :int;
protected var _metrics :MisoSceneMetrics;
}
}
@@ -0,0 +1,32 @@
//
// 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.tile {
import com.threerings.media.tile.TileManager;
/**
* Extends the basic tile manager and provides support for automatically generating fringes in
* between different types of base tiles in a scene.
*/
public class MisoTileManager extends TileManager
{
// TODO: Fringing.
}
}
@@ -18,11 +18,18 @@
package com.threerings.miso.util {
import com.threerings.miso.tile.MisoTileManager;
/**
* 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
{
/**
* Returns a reference to the tile manager. This reference is valid
* for the lifetime of the application.
*/
function getTileManager () :MisoTileManager;
}
}