Second pass on AS recoloring, fixed a bunch of bugs and tied to tiles/tilesets.

git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@936 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
Mike Thomas
2010-07-07 18:04:52 +00:00
parent 91b0a812ba
commit 1254841995
10 changed files with 89 additions and 50 deletions
@@ -138,13 +138,14 @@ public class ClassRecord
public static function fromXml (xml :XML) :ClassRecord
{
var rec :ClassRecord = new ClassRecord();
rec.classId = xml.@classId;
for each (var colorXml :XML in xml.color) {
rec.colors.put(colorXml.@colorId, ColorRecord.fromXml(colorXml));
rec.colors.put(int(colorXml.@colorId), ColorRecord.fromXml(colorXml, rec));
}
rec.name = xml.@name;
var srcStr :String = xml.@source;
rec.source = parseInt(srcStr.substring(1, srcStr.length - 1), 16);
rec.source = parseInt(srcStr.substr(1, srcStr.length - 1), 16);
rec.range = toNumArray(xml.@range);
rec.defaultId = xml.@defaultId;
@@ -157,7 +158,7 @@ public class ClassRecord
return null;
}
return str.split(",").map(function(element :*, index :int, arr :Array) :int {
return str.split(",").map(function(element :*, index :int, arr :Array) :Number {
return Number(element);
});
}
@@ -22,6 +22,7 @@ package com.threerings.media.image {
import com.threerings.util.Log;
import com.threerings.util.Map;
import com.threerings.util.Maps;
import com.threerings.util.StringUtil;
public class ColorPository
{
@@ -120,12 +121,27 @@ public class ColorPository
return null;
}
/**
* Looks up a colorization by class and color Id.
*/
public function getColorizationByNameAndId (className :String, colorId :int) :Colorization
{
var crec :ClassRecord = getClassRecordByName(className);
if (crec != null) {
var color :ColorRecord = crec.colors.get(colorId);
if (color != null) {
return color.getColorization();
}
}
return null;
}
/**
* Loads up a colorization class by name and logs a warning if it doesn't exist.
*/
public function getClassRecordByName (className :String) :ClassRecord
{
for each (var crec :ClassRecord in _classes) {
for each (var crec :ClassRecord in _classes.values()) {
if (crec.name == className) {
return crec;
}
@@ -72,13 +72,14 @@ public class ColorRecord
}
public static function fromXml (xml :XML) :ColorRecord
public static function fromXml (xml :XML, cclass :ClassRecord) :ColorRecord
{
var rec :ColorRecord = new ColorRecord();
rec.colorId = xml.@colorId;
rec.name = xml.@name;
rec.offsets = toNumArray(xml.@offsets);
rec.starter = xml.@starter;
rec.cclass = cclass;
return rec;
}
@@ -89,8 +90,8 @@ public class ColorRecord
return null;
}
return str.split(",").map(function(element :*, index :int, arr :Array) :int {
return Number(element);
return str.split(",").map(function(element :String, index :int, arr :Array) :Number {
return Number(StringUtil.trim(element));
});
}
@@ -55,7 +55,7 @@ public class Colorization
// compute our HSV and fixed HSV
_hsv = ColorUtil.RGBtoHSB(ColorUtil.getRed(rootColor), ColorUtil.getGreen(rootColor),
ColorUtil.getBlue(rootColor));
_fhsv = toFixedHSV(_hsv, null);
_fhsv = toFixedHSV(_hsv);
}
/**
@@ -154,14 +154,12 @@ public class Colorization
* @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
public static function toFixedHSV (hsv :Array) :Array
{
if (fhsv == null) {
fhsv = new Array(hsv.length);
}
var fhsv :Array = 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);
fhsv[ii] = int(hsv[ii] * Short.MAX_VALUE);
}
return fhsv;
}
@@ -78,23 +78,23 @@ public class PngRecolorUtil
}
public static function recolorPNG (pngBytes :ByteArray,
colors :Array/* of Colorization */) :void
colors :Array/* of Colorization */) :ByteArray
{
if (colors.length == 0) {
return;
if (colors == null || colors.length == 0) {
return pngBytes;
}
// first, lets make sure we really have a PNG
if (!isPng(pngBytes)) {
log.warning("recolorPNG received invalid pngBytes", new Error());
return;
return pngBytes;
}
var chunks :Array = findChunks(pngBytes, [HEADER_CHUNK, PALETTE_CHUNK]);
if (chunks.length != 2 || (chunks[0] as PngChunk).type != HEADER_CHUNK) {
log.warning("recolorPNG received an unexected PNG format", "requiredChunksFound",
chunks.length, new Error());
return;
return pngBytes;
}
var header :PngChunk = chunks[0] as PngChunk;
var palette :PngChunk = chunks[1] as PngChunk;
@@ -103,7 +103,7 @@ public class PngRecolorUtil
if (colorType != INDEXED_COLOR_TYPE) {
log.warning(
"Color Type in PNG header is not indexed-color", "type", colorType, new Error());
return;
return pngBytes;
}
initializeCRCTable();
@@ -118,12 +118,16 @@ public class PngRecolorUtil
var green :uint = pngBytes.readUnsignedByte();
var blue :uint = pngBytes.readUnsignedByte();
var hsb :Array = ColorUtil.RGBtoHSB(red, green, blue);
var hsv :Array = ColorUtil.RGBtoHSB(red, green, blue);
var fhsv :Array = Colorization.toFixedHSV(hsv);
for each (var color :Colorization in colors) {
var newRgb :uint = color.recolorColor(hsb);
pngBytes[ii] = ColorUtil.getRed(newRgb);
pngBytes[ii + 1] = ColorUtil.getGreen(newRgb);
pngBytes[ii + 2] = ColorUtil.getBlue(newRgb);
if (color != null && color.matches(hsv, fhsv)) {
var newRgb :uint = color.recolorColor(hsv);
pngBytes[ii] = red = ColorUtil.getRed(newRgb);
pngBytes[ii + 1] = green = ColorUtil.getGreen(newRgb);
pngBytes[ii + 2] = blue = ColorUtil.getBlue(newRgb);
break;
}
}
crc = F.foldl([red, green, blue], crc, crcCalc);
@@ -132,6 +136,8 @@ public class PngRecolorUtil
// write out the CRC for the modified color table
pngBytes.position = palette.idx + palette.length;
pngBytes.writeUnsignedInt(crc);
return pngBytes;
}
protected static function initializeCRCTable () :void
@@ -172,8 +178,6 @@ public class PngRecolorUtil
protected static const COLOR_TYPE_IDX :int = 9;
protected static const INDEXED_COLOR_TYPE :int = 3;
protected static const JAVA_SHORT_MAX :int = 0x7FFF;
protected static var _crcTable :Array;
}
}
@@ -264,9 +264,12 @@ public class ObjectTileSet extends SwissArmyTileSet
_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("|");
});
if (constraintStrArr != null) {
_constraints =
constraintStrArr.map(function(element :*, index :int, arr :Array) :Array {
return element.split("|");
});
}
}
/** The width (in tile units) of our object tiles. */
@@ -177,24 +177,34 @@ public class SwissArmyTileSet extends TileSet
_widths = toIntArray(xml.widths);
_heights = toIntArray(xml.heights);
var offsetPosArr :Array = toIntArray(xml.offsetPos);
_offsetPos = new Point(offsetPosArr[0], offsetPosArr[1]);
if (offsetPosArr != null) {
_offsetPos = new Point(offsetPosArr[0], offsetPosArr[1]);
} else {
_offsetPos = new Point(0, 0);
}
var gapSizeArr :Array = toIntArray(xml.gapSize);
_gapSize = new Point(gapSizeArr[0], gapSizeArr[1]);
if (gapSizeArr != null) {
_gapSize = new Point(gapSizeArr[0], gapSizeArr[1]);
} else {
_gapSize = new Point(0, 0);
}
computeTileCount();
}
protected static function toStrArray (str :String) :Array
{
if (str == null) {
if (str == null || str.length == 0) {
return null;
}
return str.split(",");
return str.split(",").map(function(element :String, index :int, arr :Array) :String {
return StringUtil.trim(element);
});
}
protected static function toBoolArray (str :String) :Array
{
if (str == null) {
if (str == null || str.length == 0) {
return null;
}
@@ -205,7 +215,7 @@ public class SwissArmyTileSet extends TileSet
protected static function toIntArray (str :String) :Array
{
if (str == null) {
if (str == null || str.length == 0) {
return null;
}
@@ -34,6 +34,7 @@ import nochump.util.zip.ZipEntry;
import nochump.util.zip.ZipError;
import nochump.util.zip.ZipFile;
import com.threerings.media.image.PngRecolorUtil;
import com.threerings.util.DataPack;
import com.threerings.util.MultiLoader;
@@ -85,23 +86,17 @@ public class TileDataPack extends DataPack
public function getTileSetImage (path :String, zations :Array, callback :Function) :void
{
// TODO - DO SOMETHING WITH ZATIONS
getDisplayObjects(path, callback);
MultiLoader.getContents(PngRecolorUtil.recolorPNG(getFile(path), zations), 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);
}
getTileSetImage(path, zations, function(result :Bitmap) :void {
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));
});
}
}
@@ -32,6 +32,7 @@ import flash.events.MouseEvent;
import com.threerings.crowd.client.PlaceView;
import com.threerings.crowd.data.PlaceObject;
import com.threerings.media.tile.Colorizer;
import com.threerings.media.tile.NoSuchTileSetError;
import com.threerings.media.tile.TileSet;
import com.threerings.media.tile.TileUtil;
@@ -166,7 +167,8 @@ public class MisoScenePanel extends Sprite
scene.addChild(
new ObjectTileIsoSprite(objInfo.x, objInfo.y, objTileId,
objTileSet.getTile(TileUtil.getTileIndex(objTileId)), _metrics));
objTileSet.getTile(TileUtil.getTileIndex(objTileId), getColorizer(objInfo)),
_metrics));
}
time = getTimer();
@@ -175,6 +177,15 @@ public class MisoScenePanel extends Sprite
_isoView.addScene(scene);
}
/**
* Derived classes can override this method and provide a colorizer that will be used to
* colorize the supplied scene object when rendering.
*/
protected function getColorizer (oinfo :ObjectInfo) :Colorizer
{
return null;
}
protected var _model :MisoSceneModel;
protected var _isoView :IsoView;
@@ -86,7 +86,7 @@ public class TileIsoSprite extends IsoDisplayObject
image.x = -tile.getOriginX() + _metrics.tilewid *
((tile.getBaseWidth() - tile.getBaseHeight())/2);;
image.y = -tile.getOriginY() + _metrics.tilehei *
(1 + (tile.getBaseWidth() + tile.getBaseHeight())/2);
((tile.getBaseWidth() + tile.getBaseHeight())/2);
sprite.sprites = [image];
sprite.setSize(tile.getBaseWidth(), tile.getBaseHeight(), 1);
addChild(sprite);