The first steps toward supporting shadows and cropping in the character
compositing system. These changes will not affect systems (like Yohoho) that don't use said features. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3729 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -256,6 +256,8 @@ public class CharacterManager
|
|||||||
for (int ii = 0; ii < ccount; ii++) {
|
for (int ii = 0; ii < ccount; ii++) {
|
||||||
sources[ii] = new ComponentFrames();
|
sources[ii] = new ComponentFrames();
|
||||||
sources[ii].ccomp = _crepo.getComponent(cids[ii]);
|
sources[ii].ccomp = _crepo.getComponent(cids[ii]);
|
||||||
|
|
||||||
|
// load up the main component images
|
||||||
ActionFrames source = sources[ii].ccomp.getFrames(action);
|
ActionFrames source = sources[ii].ccomp.getFrames(action);
|
||||||
if (source == null) {
|
if (source == null) {
|
||||||
String errmsg = "Cannot composite action frames; no such " +
|
String errmsg = "Cannot composite action frames; no such " +
|
||||||
@@ -265,6 +267,17 @@ public class CharacterManager
|
|||||||
}
|
}
|
||||||
sources[ii].frames = (zations == null || zations[ii] == null) ?
|
sources[ii].frames = (zations == null || zations[ii] == null) ?
|
||||||
source : source.cloneColorized(zations[ii]);
|
source : source.cloneColorized(zations[ii]);
|
||||||
|
|
||||||
|
// load up the shadow images if they are needed
|
||||||
|
if (sources[ii].ccomp.componentClass.shadowed) {
|
||||||
|
sources[ii].shadowFrames = sources[ii].ccomp.getFrames(
|
||||||
|
action + StandardActions.SHADOW_SUFFIX);
|
||||||
|
if (sources[ii].shadowFrames == null) {
|
||||||
|
Log.warning("Missing shadow frames for action " +
|
||||||
|
"[action=" + action +
|
||||||
|
", comp=" + sources[ii].ccomp + "].");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use those to create an entity that will lazily composite things
|
// use those to create an entity that will lazily composite things
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
package com.threerings.cast;
|
package com.threerings.cast;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
import com.samskivert.util.ArrayIntSet;
|
import com.samskivert.util.ArrayIntSet;
|
||||||
@@ -116,6 +117,24 @@ public class ComponentClass implements Serializable
|
|||||||
* be null if a system does not use recolorable components. */
|
* be null if a system does not use recolorable components. */
|
||||||
public String[] colors;
|
public String[] colors;
|
||||||
|
|
||||||
|
/** Indicates whether or not components in this class have an associated
|
||||||
|
* shadow image. */
|
||||||
|
public boolean shadowed;
|
||||||
|
|
||||||
|
/** Null for a normal component, the color of the pre-composited shadow for
|
||||||
|
* the special "shadow" component class. */
|
||||||
|
public Color shadowColor;
|
||||||
|
|
||||||
|
/** Zero for a normal component, defines the (inclusive) lower bound of the
|
||||||
|
* range of components whose shadow will be included in this pre-composited
|
||||||
|
* shadow layer for a shadow component. */
|
||||||
|
public int minShadowPri;
|
||||||
|
|
||||||
|
/** Zero for a normal component, defines the (inclusive) upper bound of the
|
||||||
|
* range of components whose shadow will be included in this pre-composited
|
||||||
|
* shadow layer for a shadow component. */
|
||||||
|
public int maxShadowPri;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an uninitialized instance suitable for unserialization or
|
* Creates an uninitialized instance suitable for unserialization or
|
||||||
* population during XML parsing.
|
* population during XML parsing.
|
||||||
@@ -183,8 +202,19 @@ public class ComponentClass implements Serializable
|
|||||||
*/
|
*/
|
||||||
public String toString ()
|
public String toString ()
|
||||||
{
|
{
|
||||||
return "[name=" + name + ", renderPriority=" + renderPriority +
|
StringBuffer buf = new StringBuffer("[");
|
||||||
", colors=" + StringUtil.toString(colors) + "]";
|
buf.append("name=").append(name);
|
||||||
|
buf.append(", pri=").append(renderPriority);
|
||||||
|
if (colors != null) {
|
||||||
|
buf.append(", colors=").append(StringUtil.toString(colors));
|
||||||
|
}
|
||||||
|
if (shadowColor != null) {
|
||||||
|
buf.append(", shadow=");
|
||||||
|
buf.append(StringUtil.toString(shadowColor.getComponents(null)));
|
||||||
|
buf.append(" (").append(minShadowPri).append("-");
|
||||||
|
buf.append(maxShadowPri).append(")");
|
||||||
|
}
|
||||||
|
return buf.append("]").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A list of render priority overrides. */
|
/** A list of render priority overrides. */
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ public class CompositedActionFrames
|
|||||||
|
|
||||||
public ActionFrames frames;
|
public ActionFrames frames;
|
||||||
|
|
||||||
|
public ActionFrames shadowFrames;
|
||||||
|
|
||||||
|
public ActionFrames cropFrames;
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
return ccomp + ":" + frames;
|
return ccomp + ":" + frames;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: StandardActions.java,v 1.2 2004/08/27 02:12:26 mdb Exp $
|
// $Id$
|
||||||
//
|
//
|
||||||
// Narya library - tools for developing networked games
|
// Narya library - tools for developing networked games
|
||||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
@@ -23,9 +23,8 @@ package com.threerings.cast;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Actions are referenced by name and this interface defines constants for
|
* Actions are referenced by name and this interface defines constants for
|
||||||
* two standard actions: standing and walking. Because character sprites
|
* standard actions and action suffixes used by the shadow and cropping
|
||||||
* follow paths, it is helpful for them to take care of switching between
|
* support.
|
||||||
* the standing and walking actions automatically.
|
|
||||||
*/
|
*/
|
||||||
public interface StandardActions
|
public interface StandardActions
|
||||||
{
|
{
|
||||||
@@ -34,4 +33,10 @@ public interface StandardActions
|
|||||||
|
|
||||||
/** The name of the standard walking action. */
|
/** The name of the standard walking action. */
|
||||||
public static final String WALKING = "walking";
|
public static final String WALKING = "walking";
|
||||||
|
|
||||||
|
/** The suffix appended to an action to obtain its shadow image. */
|
||||||
|
public static final String SHADOW_SUFFIX = "_shadow";
|
||||||
|
|
||||||
|
/** The suffix appended to an action to obtain its crop image. */
|
||||||
|
public static final String CROP_SUFFIX = "_crop";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ComponentBundlerTask.java,v 1.21 2004/08/27 02:12:28 mdb Exp $
|
// $Id$
|
||||||
//
|
//
|
||||||
// Narya library - tools for developing networked games
|
// Narya library - tools for developing networked games
|
||||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
@@ -47,6 +47,7 @@ import java.util.zip.Deflater;
|
|||||||
import org.apache.commons.digester.Digester;
|
import org.apache.commons.digester.Digester;
|
||||||
|
|
||||||
import com.samskivert.io.PersistenceException;
|
import com.samskivert.io.PersistenceException;
|
||||||
|
import com.samskivert.util.FileUtil;
|
||||||
import com.samskivert.util.HashIntMap;
|
import com.samskivert.util.HashIntMap;
|
||||||
import com.samskivert.util.SortableArrayList;
|
import com.samskivert.util.SortableArrayList;
|
||||||
import com.samskivert.util.Tuple;
|
import com.samskivert.util.Tuple;
|
||||||
@@ -63,6 +64,7 @@ import com.threerings.media.tile.TrimmedTileSet;
|
|||||||
import com.threerings.media.tile.tools.xml.SwissArmyTileSetRuleSet;
|
import com.threerings.media.tile.tools.xml.SwissArmyTileSetRuleSet;
|
||||||
|
|
||||||
import com.threerings.cast.ComponentIDBroker;
|
import com.threerings.cast.ComponentIDBroker;
|
||||||
|
import com.threerings.cast.StandardActions;
|
||||||
import com.threerings.cast.bundle.BundleUtil;
|
import com.threerings.cast.bundle.BundleUtil;
|
||||||
import com.threerings.cast.tools.xml.ActionRuleSet;
|
import com.threerings.cast.tools.xml.ActionRuleSet;
|
||||||
|
|
||||||
@@ -199,44 +201,27 @@ public class ComponentBundlerTask extends Task
|
|||||||
", action=" + info[2] + "].");
|
", action=" + info[2] + "].");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
aset.setImageProvider(improv);
|
||||||
|
|
||||||
// obtain the component id from our id broker
|
// obtain the component id from our id broker
|
||||||
int cid = broker.getComponentID(info[0], info[1]);
|
int cid = broker.getComponentID(info[0], info[1]);
|
||||||
// add a mapping for this component
|
// add a mapping for this component
|
||||||
mapping.put(cid, new Tuple(info[0], info[1]));
|
mapping.put(cid, new Tuple(info[0], info[1]));
|
||||||
|
|
||||||
// construct the path that'll go in the jar file
|
// process and store the main component image
|
||||||
String ipath = composePath(
|
processComponent(info, aset, cfile, jout);
|
||||||
info, BundleUtil.IMAGE_EXTENSION);
|
|
||||||
jout.putNextEntry(new JarEntry(ipath));
|
|
||||||
|
|
||||||
// create a trimmed tileset based on the source action
|
// pick up any auxiliary images as well like the shadow or
|
||||||
// tileset and stuff the new trimmed image into the
|
// crop files
|
||||||
// jar file at the same time
|
String action = info[2];
|
||||||
aset.setImagePath(cfile.getPath());
|
String ext = BundleUtil.IMAGE_EXTENSION;
|
||||||
aset.setImageProvider(improv);
|
for (int aa = 0; aa < AUX_EXTS.length; aa++) {
|
||||||
|
File afile = new File(
|
||||||
TrimmedTileSet tset = null;
|
FileUtil.resuffix(cfile, ext, AUX_EXTS[aa] + ext));
|
||||||
try {
|
if (afile.exists()) {
|
||||||
tset = TrimmedTileSet.trimTileSet(aset, jout);
|
info[2] = action + AUX_EXTS[aa];
|
||||||
tset.setImagePath(ipath);
|
processComponent(info, aset, afile, jout);
|
||||||
} catch (Throwable t) {
|
}
|
||||||
System.err.println(
|
|
||||||
"Failure trimming tileset " +
|
|
||||||
"[class=" + info[0] + ", name=" + info[1] +
|
|
||||||
", action=" + info[2] +
|
|
||||||
", srcimg=" + aset.getImagePath() + "].");
|
|
||||||
t.printStackTrace(System.err);
|
|
||||||
}
|
|
||||||
|
|
||||||
// then write our trimmed tileset to the jar file
|
|
||||||
if (tset != null) {
|
|
||||||
String tpath = composePath(
|
|
||||||
info, BundleUtil.TILESET_EXTENSION);
|
|
||||||
jout.putNextEntry(new JarEntry(tpath));
|
|
||||||
ObjectOutputStream oout = new ObjectOutputStream(jout);
|
|
||||||
oout.writeObject(tset);
|
|
||||||
oout.flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -263,6 +248,43 @@ public class ComponentBundlerTask extends Task
|
|||||||
saveBroker(_mapfile, broker);
|
saveBroker(_mapfile, broker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void processComponent (
|
||||||
|
String[] info, TileSet aset, File cfile, JarOutputStream jout)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
// construct the path that'll go in the jar file
|
||||||
|
String ipath = composePath(
|
||||||
|
info, BundleUtil.IMAGE_EXTENSION);
|
||||||
|
jout.putNextEntry(new JarEntry(ipath));
|
||||||
|
|
||||||
|
// create a trimmed tileset based on the source action tileset and
|
||||||
|
// stuff the new trimmed image into the jar file at the same time
|
||||||
|
aset.setImagePath(cfile.getPath());
|
||||||
|
|
||||||
|
TrimmedTileSet tset = null;
|
||||||
|
try {
|
||||||
|
tset = TrimmedTileSet.trimTileSet(aset, jout);
|
||||||
|
tset.setImagePath(ipath);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
System.err.println(
|
||||||
|
"Failure trimming tileset " +
|
||||||
|
"[class=" + info[0] + ", name=" + info[1] +
|
||||||
|
", action=" + info[2] +
|
||||||
|
", srcimg=" + aset.getImagePath() + "].");
|
||||||
|
t.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
|
||||||
|
// then write our trimmed tileset to the jar file
|
||||||
|
if (tset != null) {
|
||||||
|
String tpath = composePath(
|
||||||
|
info, BundleUtil.TILESET_EXTENSION);
|
||||||
|
jout.putNextEntry(new JarEntry(tpath));
|
||||||
|
ObjectOutputStream oout = new ObjectOutputStream(jout);
|
||||||
|
oout.writeObject(tset);
|
||||||
|
oout.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean outOfDate (ArrayList sources, File target)
|
protected boolean outOfDate (ArrayList sources, File target)
|
||||||
{
|
{
|
||||||
for (int ii = 0; ii < sources.size(); ii++) {
|
for (int ii = 0; ii < sources.size(); ii++) {
|
||||||
@@ -594,4 +616,8 @@ public class ComponentBundlerTask extends Task
|
|||||||
|
|
||||||
/** Used to separate keys and values in the map file. */
|
/** Used to separate keys and values in the map file. */
|
||||||
protected static final String SEP_STR = " := ";
|
protected static final String SEP_STR = " := ";
|
||||||
|
|
||||||
|
/** Used to process auxilliary tilesets. */
|
||||||
|
protected static final String[] AUX_EXTS = {
|
||||||
|
StandardActions.SHADOW_SUFFIX, StandardActions.CROP_SUFFIX };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ClassRuleSet.java,v 1.4 2004/08/27 02:12:28 mdb Exp $
|
// $Id$
|
||||||
//
|
//
|
||||||
// Narya library - tools for developing networked games
|
// Narya library - tools for developing networked games
|
||||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
package com.threerings.cast.tools.xml;
|
package com.threerings.cast.tools.xml;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
import org.apache.commons.digester.Digester;
|
import org.apache.commons.digester.Digester;
|
||||||
import org.apache.commons.digester.RuleSetBase;
|
import org.apache.commons.digester.RuleSetBase;
|
||||||
|
|
||||||
@@ -74,12 +76,19 @@ public class ClassRuleSet extends RuleSetBase
|
|||||||
ComponentClass.class.getName());
|
ComponentClass.class.getName());
|
||||||
|
|
||||||
// grab the attributes from the <class> tag
|
// grab the attributes from the <class> tag
|
||||||
digester.addRule(_prefix + CLASS_PATH, new SetPropertyFieldsRule());
|
SetPropertyFieldsRule rule = new SetPropertyFieldsRule();
|
||||||
|
rule.addFieldParser("shadowColor", new FieldParser() {
|
||||||
|
public Object parse (String text) {
|
||||||
|
int[] values = StringUtil.parseIntArray(text);
|
||||||
|
return new Color(values[0], values[1], values[2], values[3]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
digester.addRule(_prefix + CLASS_PATH, rule);
|
||||||
|
|
||||||
// parse render priority overrides
|
// parse render priority overrides
|
||||||
String opath = _prefix + CLASS_PATH + "/override";
|
String opath = _prefix + CLASS_PATH + "/override";
|
||||||
digester.addObjectCreate(opath, PriorityOverride.class.getName());
|
digester.addObjectCreate(opath, PriorityOverride.class.getName());
|
||||||
SetPropertyFieldsRule rule = new SetPropertyFieldsRule();
|
rule = new SetPropertyFieldsRule();
|
||||||
rule.addFieldParser("orients", new FieldParser() {
|
rule.addFieldParser("orients", new FieldParser() {
|
||||||
public Object parse (String text) {
|
public Object parse (String text) {
|
||||||
String[] orients = StringUtil.parseStringArray(text);
|
String[] orients = StringUtil.parseStringArray(text);
|
||||||
|
|||||||
Reference in New Issue
Block a user