The amazing revamp four hundred billion. Let's see:
- Reworked colorization repository such that we now have arbitrary named "colorization classes" which can be used by various and sundry entities to colorize themselves. - Added support for individual object colorizations as well as "spots" that go along with objects (will be used to automatically create portals into buildings and automatically position users properly when at a "station"). - Repackaged things in miso to more closely mimic what we do everywhere else (no more miso.scene, now we have miso.data and miso.client). - Fixed up miso scene XML representation so that objects can more easily be expanded to have yet more stuff if we think of more stuff that they might aught to have in the future. Structured the miso scene model so that "uninteresting" objects (those that simply sit somewhere and don't do anything) take up a lot less memory than "interesting" objects (those that have action strings, "spots", colorizations and the works). I may want to roll colorizations into the "uninteresting" realm, but that remains to be seen. - Made it possible for object tilesets to specify default render priorities for objects in that tileset. This will hopefully allow us to get by without any "custom" render priorities that are specified on scene objects, instead relying on the default priorities to resolve common conflicts. There are surely other cleanups in there, but I think that was the major thrust of it. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2228 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -0,0 +1,377 @@
|
||||
//
|
||||
// $Id: ColorPository.java,v 1.1 2003/01/31 23:10:45 mdb Exp $
|
||||
|
||||
package com.threerings.media.image;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.media.Log;
|
||||
import com.threerings.resource.ResourceManager;
|
||||
import com.threerings.util.CompiledConfig;
|
||||
import com.threerings.util.RandomUtil;
|
||||
|
||||
/**
|
||||
* A repository of image recoloration information. It was called the
|
||||
* recolor repository but the re-s cancelled one another out.
|
||||
*/
|
||||
public class ColorPository implements Serializable
|
||||
{
|
||||
/**
|
||||
* Used to store information on a class of colors. These are public to
|
||||
* simplify the XML parsing process, so pay them no mind.
|
||||
*/
|
||||
public static class ClassRecord implements Serializable
|
||||
{
|
||||
/** An integer identifier for this class. */
|
||||
public int classId;
|
||||
|
||||
/** The name of the color class. */
|
||||
public String name;
|
||||
|
||||
/** The source color to use when recoloring colors in this class. */
|
||||
public Color source;
|
||||
|
||||
/** Data identifying the range of colors around the source color
|
||||
* that will be recolored when recoloring using this class. */
|
||||
public float[] range;
|
||||
|
||||
/** The default starting legality value for this color class. See
|
||||
* {@link ColorRecord#starter}. */
|
||||
public boolean starter;
|
||||
|
||||
/** A table of target colors included in this class. */
|
||||
public HashIntMap colors = new HashIntMap();
|
||||
|
||||
/** Used when parsing the color definitions. */
|
||||
public void addColor (ColorRecord record)
|
||||
{
|
||||
// validate the color id
|
||||
if (record.colorId > 255) {
|
||||
Log.warning("Refusing to add color record; colorId > 255 " +
|
||||
"[class=" + this + ", record=" + record + "].");
|
||||
} else {
|
||||
record.cclass = this;
|
||||
colors.put(record.colorId, record);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a random starting id from the entries in this
|
||||
* class. */
|
||||
public ColorRecord randomStartingColor ()
|
||||
{
|
||||
// figure out our starter ids if we haven't already
|
||||
if (_starters == null) {
|
||||
ArrayList list = new ArrayList();
|
||||
Iterator iter = colors.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
ColorRecord color = (ColorRecord)iter.next();
|
||||
if (color.starter) {
|
||||
list.add(color);
|
||||
}
|
||||
}
|
||||
_starters = (ColorRecord[])
|
||||
list.toArray(new ColorRecord[list.size()]);
|
||||
}
|
||||
|
||||
// return a random entry from the array
|
||||
return _starters[RandomUtil.getInt(_starters.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this instance.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
return "[id=" + classId + ", name=" + name + ", source=#" +
|
||||
Integer.toString(source.getRGB() & 0xFFFFFF, 16) +
|
||||
", range=" + StringUtil.toString(range) +
|
||||
", starter=" + starter + ", colors=" +
|
||||
StringUtil.toString(colors.values().iterator()) + "]";
|
||||
}
|
||||
|
||||
protected transient ColorRecord[] _starters;
|
||||
|
||||
/** Increase this value when object's serialized state is impacted
|
||||
* by a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to store information on a particular color. These are public
|
||||
* to simplify the XML parsing process, so pay them no mind.
|
||||
*/
|
||||
public static class ColorRecord implements Serializable
|
||||
{
|
||||
/** The colorization class to which we belong. */
|
||||
public ClassRecord cclass;
|
||||
|
||||
/** A unique colorization identifier (used in fingerprints). */
|
||||
public int colorId;
|
||||
|
||||
/** The name of the target color. */
|
||||
public String name;
|
||||
|
||||
/** Data indicating the offset (in HSV color space) from the
|
||||
* source color to recolor to this color. */
|
||||
public float[] offsets;
|
||||
|
||||
/** Tags this color as a legal starting color or not. This is a
|
||||
* shameful copout, placing application-specific functionality
|
||||
* into a general purpose library class. */
|
||||
public boolean starter;
|
||||
|
||||
/**
|
||||
* Returns a value that is the composite of our class id and color
|
||||
* id which can be used to identify a colorization record. This
|
||||
* value will always be a positive integer that fits into 16 bits.
|
||||
*/
|
||||
public int getColorPrint ()
|
||||
{
|
||||
return ((cclass.classId << 8) | colorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data in this record configured as a colorization
|
||||
* instance.
|
||||
*/
|
||||
public Colorization getColorization ()
|
||||
{
|
||||
return new Colorization(getColorPrint(), cclass.source,
|
||||
cclass.range, offsets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this instance.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
return "[id=" + colorId + ", name=" + name +
|
||||
", offsets=" + StringUtil.toString(offsets) +
|
||||
", starter=" + starter + "]";
|
||||
}
|
||||
|
||||
/** Increase this value when object's serialized state is impacted
|
||||
* by a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over all color classes in this pository.
|
||||
*/
|
||||
public Iterator enumerateClasses ()
|
||||
{
|
||||
return _classes.values().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing the records for the colors in the
|
||||
* specified class.
|
||||
*/
|
||||
public ColorRecord[] enumerateColors (String className)
|
||||
{
|
||||
// make sure the class exists
|
||||
ClassRecord record = getClassRecord(className);
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// create the array
|
||||
ColorRecord[] crecs = new ColorRecord[record.colors.size()];
|
||||
Iterator iter = record.colors.values().iterator();
|
||||
for (int i = 0; iter.hasNext(); i++) {
|
||||
crecs[i] = ((ColorRecord)iter.next());
|
||||
}
|
||||
return crecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing the ids of the colors in the specified
|
||||
* class.
|
||||
*/
|
||||
public int[] enumerateColorIds (String className)
|
||||
{
|
||||
// make sure the class exists
|
||||
ClassRecord record = getClassRecord(className);
|
||||
if (record == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int[] cids = new int[record.colors.size()];
|
||||
Iterator crecs = record.colors.values().iterator();
|
||||
for (int i = 0; crecs.hasNext(); i++) {
|
||||
cids[i] = ((ColorRecord)crecs.next()).colorId;
|
||||
}
|
||||
return cids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified color is legal for use at character
|
||||
* creation time. false is always returned for non-existent colors or
|
||||
* classes.
|
||||
*/
|
||||
public boolean isLegalStartColor (int classId, int colorId)
|
||||
{
|
||||
ColorRecord color = getColorRecord(classId, colorId);
|
||||
return (color == null) ? false : color.starter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random starting color from the specified color class.
|
||||
*/
|
||||
public ColorRecord getRandomStartingColor (String className)
|
||||
{
|
||||
// make sure the class exists
|
||||
ClassRecord record = getClassRecord(className);
|
||||
return (record == null) ? null : record.randomStartingColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a colorization by id.
|
||||
*/
|
||||
public Colorization getColorization (int classId, int colorId)
|
||||
{
|
||||
ColorRecord color = getColorRecord(classId, colorId);
|
||||
return (color == null) ? null : color.getColorization();
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a colorization by color print.
|
||||
*/
|
||||
public Colorization getColorization (int colorPrint)
|
||||
{
|
||||
return getColorization(colorPrint >> 8, colorPrint & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a colorization by name.
|
||||
*/
|
||||
public Colorization getColorization (String className, int colorId)
|
||||
{
|
||||
ClassRecord crec = getClassRecord(className);
|
||||
if (crec != null) {
|
||||
ColorRecord color = (ColorRecord)crec.colors.get(colorId);
|
||||
if (color != null) {
|
||||
color.getColorization();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads up a colorization class by name and logs a warning if it
|
||||
* doesn't exist.
|
||||
*/
|
||||
public ClassRecord getClassRecord (String className)
|
||||
{
|
||||
Iterator iter = _classes.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
ClassRecord crec = (ClassRecord)iter.next();
|
||||
if (crec.name.equals(className)) {
|
||||
return crec;
|
||||
}
|
||||
}
|
||||
Log.warning("No such color class [class=" + className + "].");
|
||||
Thread.dumpStack();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the requested color record.
|
||||
*/
|
||||
protected ColorRecord getColorRecord (int classId, int colorId)
|
||||
{
|
||||
ClassRecord record = (ClassRecord)_classes.get(classId);
|
||||
if (record == null) {
|
||||
// if they request color class zero, we assume they're just
|
||||
// decoding a blank colorprint, otherwise we complain
|
||||
if (classId != 0) {
|
||||
Log.warning("Requested unknown color class " +
|
||||
"[classId=" + classId +
|
||||
", colorId=" + colorId + "].");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return (ColorRecord)record.colors.get(colorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a fully configured color class record to the pository. This is
|
||||
* only called by the XML parsing code, so pay it no mind.
|
||||
*/
|
||||
public void addClass (ClassRecord record)
|
||||
{
|
||||
// validate the class id
|
||||
if (record.classId > 255) {
|
||||
Log.warning("Refusing to add class; classId > 255 " + record + ".");
|
||||
} else {
|
||||
_classes.put(record.classId, record);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads up a serialized color pository from the supplied resource
|
||||
* manager.
|
||||
*/
|
||||
public static ColorPository loadColorPository (ResourceManager rmgr)
|
||||
{
|
||||
try {
|
||||
return loadColorPository(rmgr.getResource(CONFIG_PATH));
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Failure loading color pository [path=" + CONFIG_PATH +
|
||||
", error=" + ioe + "].");
|
||||
return new ColorPository();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads up a serialized color pository from the supplied resource
|
||||
* manager.
|
||||
*/
|
||||
public static ColorPository loadColorPository (InputStream source)
|
||||
{
|
||||
try {
|
||||
return (ColorPository)CompiledConfig.loadConfig(source);
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Failure loading color pository: " + ioe + ".");
|
||||
return new ColorPository();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes and saves color pository to the supplied file.
|
||||
*/
|
||||
public static void saveColorPository (ColorPository posit, File root)
|
||||
{
|
||||
File path = new File(root, CONFIG_PATH);
|
||||
try {
|
||||
CompiledConfig.saveConfig(path, posit);
|
||||
} catch (IOException ioe) {
|
||||
Log.warning("Failure saving color pository " +
|
||||
"[path=" + path + ", error=" + ioe + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/** Our mapping from class names to class records. */
|
||||
protected HashIntMap _classes = new HashIntMap();
|
||||
|
||||
/** Increase this value when object's serialized state is impacted by
|
||||
* a class change (modification of fields, inheritance). */
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/**
|
||||
* The path (relative to the resource directory) at which the
|
||||
* serialized recolorization repository should be loaded and stored.
|
||||
*/
|
||||
protected static final String CONFIG_PATH = "config/media/colordefs.dat";
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// $Id: DumpColorPository.java,v 1.1 2003/01/31 23:10:45 mdb Exp $
|
||||
|
||||
package com.threerings.media.image.tools;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.threerings.media.image.ColorPository;
|
||||
|
||||
/**
|
||||
* Simple tool for dumping a serialized color pository.
|
||||
*/
|
||||
public class DumpColorPository
|
||||
{
|
||||
public static void main (String[] args)
|
||||
{
|
||||
if (args.length == 0) {
|
||||
System.err.println("Usage: DumpColorPository colorpos.dat");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
try {
|
||||
ColorPository pos = ColorPository.loadColorPository(
|
||||
new FileInputStream(args[0]));
|
||||
Iterator iter = pos.enumerateClasses();
|
||||
while (iter.hasNext()) {
|
||||
System.out.println(iter.next());
|
||||
}
|
||||
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// $Id: ColorPositoryParser.java,v 1.1 2003/01/31 23:10:45 mdb Exp $
|
||||
|
||||
package com.threerings.media.image.tools.xml;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.apache.commons.digester.Digester;
|
||||
import org.apache.commons.digester.Rule;
|
||||
import com.samskivert.xml.SetPropertyFieldsRule;
|
||||
|
||||
import com.threerings.tools.xml.CompiledConfigParser;
|
||||
|
||||
import com.threerings.media.image.ColorPository.ClassRecord;
|
||||
import com.threerings.media.image.ColorPository.ColorRecord;
|
||||
import com.threerings.media.image.ColorPository;
|
||||
|
||||
/**
|
||||
* Parses the XML color repository definition and creates a {@link
|
||||
* ColorPository} instance that reflects its contents.
|
||||
*/
|
||||
public class ColorPositoryParser extends CompiledConfigParser
|
||||
{
|
||||
// documentation inherited
|
||||
protected Serializable createConfigObject ()
|
||||
{
|
||||
return new ColorPository();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void addRules (Digester digest)
|
||||
{
|
||||
// create and configure class record instances
|
||||
String prefix = "colors/class";
|
||||
digest.addObjectCreate(prefix, ClassRecord.class.getName());
|
||||
digest.addRule(prefix, new SetPropertyFieldsRule(digest));
|
||||
digest.addSetNext(prefix, "addClass", ClassRecord.class.getName());
|
||||
|
||||
// create and configure color record instances
|
||||
prefix += "/color";
|
||||
digest.addRule(prefix, new Rule(digest) {
|
||||
public void begin (Attributes attributes) throws Exception {
|
||||
// we want to inherit settings from the color class when
|
||||
// creating the record, so we do some custom stuff
|
||||
ColorRecord record = new ColorRecord();
|
||||
ClassRecord clrec = (ClassRecord)digester.peek();
|
||||
record.starter = clrec.starter;
|
||||
digester.push(record);
|
||||
}
|
||||
|
||||
public void end () throws Exception {
|
||||
digester.pop();
|
||||
}
|
||||
});
|
||||
digest.addRule(prefix, new SetPropertyFieldsRule(digest));
|
||||
digest.addSetNext(prefix, "addColor", ColorRecord.class.getName());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user