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