diff --git a/src/java/com/threerings/cast/bundle/BundleUtil.java b/src/java/com/threerings/cast/bundle/BundleUtil.java index af4e09e88..e8308d740 100644 --- a/src/java/com/threerings/cast/bundle/BundleUtil.java +++ b/src/java/com/threerings/cast/bundle/BundleUtil.java @@ -1,5 +1,5 @@ // -// $Id: BundleUtil.java,v 1.1 2001/11/27 08:09:35 mdb Exp $ +// $Id: BundleUtil.java,v 1.2 2002/06/19 08:33:14 mdb Exp $ package com.threerings.cast.bundle; @@ -33,6 +33,9 @@ public class BundleUtil /** The file extension of our action tile images. */ public static final String IMAGE_EXTENSION = ".png"; + /** The serialized tileset extension for our action tilesets. */ + public static final String TILESET_EXTENSION = ".dat"; + /** * Attempts to load an object from the supplied resource bundle with * the specified path. diff --git a/src/java/com/threerings/cast/bundle/BundledComponentRepository.java b/src/java/com/threerings/cast/bundle/BundledComponentRepository.java index de0dae8ba..cf8aad89b 100644 --- a/src/java/com/threerings/cast/bundle/BundledComponentRepository.java +++ b/src/java/com/threerings/cast/bundle/BundledComponentRepository.java @@ -1,5 +1,5 @@ // -// $Id: BundledComponentRepository.java,v 1.12 2002/05/15 23:54:05 mdb Exp $ +// $Id: BundledComponentRepository.java,v 1.13 2002/06/19 08:33:14 mdb Exp $ package com.threerings.cast.bundle; @@ -258,30 +258,19 @@ public class BundledComponentRepository public ActionFrames getFrames ( CharacterComponent component, String action) { - // get the tileset for this action - TileSet aset = (TileSet)_actionSets.get(action); - if (aset == null) { - Log.warning("Can't provide animation frames for undefined " + - "action [action=" + action + - ", component=" + component + "]."); - return null; - } - - // construct the appropriate image path for the component + // load up the tileset for this action String path = component.componentClass.name + "/" + component.name + "/" + action + - BundleUtil.IMAGE_EXTENSION; - - // clone the tileset with this new image path + BundleUtil.TILESET_EXTENSION; try { - TileSet fset = aset.clone(path); - fset.setImageProvider(this); - return new TileSetFrameImage(fset); + TileSet aset = (TileSet)BundleUtil.loadObject(_bundle, path); + aset.setImageProvider(this); + return new TileSetFrameImage(aset); - } catch (CloneNotSupportedException cnse) { - Log.warning("Unable to clone tileset [action=" + action + - ", component=" + component + - ", set=" + aset + "]."); + } catch (Exception e) { + Log.warning("Error loading tileset for action " + + "[action=" + action + ", component=" + component + + ", error=" + e + "]."); return null; } } diff --git a/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java b/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java index b2adc412e..f453f5b51 100644 --- a/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java +++ b/src/java/com/threerings/cast/bundle/tools/ComponentBundlerTask.java @@ -1,8 +1,11 @@ // -// $Id: ComponentBundlerTask.java,v 1.8 2002/04/11 01:33:51 mdb Exp $ +// $Id: ComponentBundlerTask.java,v 1.9 2002/06/19 08:33:14 mdb Exp $ package com.threerings.cast.bundle.tools; +import java.awt.Image; +import javax.imageio.ImageIO; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; @@ -21,6 +24,9 @@ import java.util.Iterator; import java.util.jar.JarOutputStream; import java.util.jar.JarEntry; +import org.xml.sax.SAXException; +import org.apache.commons.digester.Digester; + import com.samskivert.io.PersistenceException; import com.samskivert.util.HashIntMap; import com.samskivert.util.StringUtil; @@ -33,8 +39,15 @@ import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Task; import org.apache.tools.ant.types.FileSet; +import com.threerings.media.tile.ImageProvider; +import com.threerings.media.tile.TileSet; +import com.threerings.media.tile.TrimmedTileSet; +import com.threerings.media.tile.tools.xml.SwissArmyTileSetRuleSet; +import com.threerings.media.tile.util.TileSetTrimmer; + import com.threerings.cast.ComponentIDBroker; import com.threerings.cast.bundle.BundleUtil; +import com.threerings.cast.tools.xml.ActionRuleSet; /** * Ant task for creating component bundles. This task must be configured @@ -70,6 +83,14 @@ public class ComponentBundlerTask extends Task _mapfile = mapfile; } + /** + * Sets the path to the action tilesets definition file. + */ + public void setActiondef (File actiondef) + { + _actionDef = actiondef; + } + /** * Sets the root path which will be stripped from the image paths * prior to parsing them to obtain the component class, type and @@ -98,6 +119,11 @@ public class ComponentBundlerTask extends Task "file via the 'target' attribute."); ensureSet(_mapfile, "Must specify the path to the component map " + "file via the 'mapfile' attribute."); + ensureSet(_actionDef, "Must specify the action sequence " + + "definitions via the 'actiondef' attribute."); + + // parse in the action tilesets + HashMap actsets = parseActionTileSets(); // load up our component ID broker ComponentIDBroker broker = loadBroker(_mapfile); @@ -107,9 +133,13 @@ public class ComponentBundlerTask extends Task FileOutputStream fout = new FileOutputStream(_target); JarOutputStream jout = new JarOutputStream(fout); - // we'll fill this with component id to tuple mappings as we go + // we'll fill this with component id to tuple mappings HashIntMap mapping = new HashIntMap(); + // herein we'll insert trimmed tileset objects that go along + // with each of the trimmed action images + HashIntMap actionSets = new HashIntMap(); + // deal with the filesets for (int i = 0; i < _filesets.size(); i++) { FileSet fs = (FileSet)_filesets.get(i); @@ -121,14 +151,49 @@ public class ComponentBundlerTask extends Task File cfile = new File(fromDir, srcFiles[f]); // determine the [class, name, action] triplet String[] info = decomposePath(cfile.getPath()); + + // make sure we have an action tileset definition + TileSet aset = (TileSet)actsets.get(info[2]); + if (aset == null) { + System.err.println( + "No tileset definition for component action " + + "[class=" + info[0] + ", name=" + info[1] + + ", action=" + info[2] + "]."); + continue; + } + // obtain the component id from our id broker int cid = broker.getComponentID(info[0], info[1]); // add a mapping for this component mapping.put(cid, new Tuple(info[0], info[1])); - // construct the path that'll go in the jar file and - // stuff the component into the jarfile - jout.putNextEntry(new JarEntry(composePath(info))); - StreamUtils.pipe(new FileInputStream(cfile), jout); + + // 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()); + aset.setImageProvider(new ImageProvider() { + public Image loadImage (String path) + throws IOException { + return ImageIO.read(new File(path)); + } + }); + TrimmedTileSet tset = + TileSetTrimmer.trimTileSet(aset, jout); + tset.setImagePath(ipath); + tset.setName(aset.getName()); + + // also write our trimmed tileset to the jar file + String tpath = composePath( + info, BundleUtil.TILESET_EXTENSION); + jout.putNextEntry(new JarEntry(tpath)); + ObjectOutputStream oout = new ObjectOutputStream(jout); + oout.writeObject(tset); + oout.flush(); } } @@ -208,10 +273,10 @@ public class ComponentBundlerTask extends Task * should be supplied to the JarEntry that contains the associated * image data. */ - protected String composePath (String[] info) + protected String composePath (String[] info, String extension) { - return (info[0] + File.separator + info[1] + File.separator + - info[2] + BundleUtil.IMAGE_EXTENSION); + return (info[0] + File.separator + info[1] + + File.separator + info[2] + extension); } protected void ensureSet (Object value, String errmsg) @@ -222,6 +287,55 @@ public class ComponentBundlerTask extends Task } } + /** + * Parses the action tileset definitions and puts them into a hash + * map, keyed on action name. + */ + protected HashMap parseActionTileSets () + { + Digester digester = new Digester(); + SwissArmyTileSetRuleSet srules = new SwissArmyTileSetRuleSet(); + String aprefix = "actions" + ActionRuleSet.ACTION_PATH; + srules.setPrefix(aprefix); + + digester.addRuleSet(srules); + digester.addSetProperties(aprefix); + digester.addSetNext(aprefix + SwissArmyTileSetRuleSet.TILESET_PATH, + "addTileSet", TileSet.class.getName()); + + HashMap actsets = new ActionMap(); + digester.push(actsets); + + try { + FileInputStream fin = new FileInputStream(_actionDef); + BufferedInputStream bin = new BufferedInputStream(fin); + digester.parse(bin); + + } catch (FileNotFoundException fnfe) { + String errmsg = "Unable to load action definition file " + + "[path=" + _actionDef.getPath() + "]."; + throw new BuildException(errmsg, fnfe); + + } catch (Exception e) { + throw new BuildException("Parsing error.", e); + } + + return actsets; + } + + /** Used when parsing action tilesets. */ + public static class ActionMap extends HashMap + { + public void setName (String name) { + _name = name; + } + public void addTileSet (TileSet set) { + set.setName(_name); + put(_name, set); + } + protected String _name; + } + /** * Loads the hashmap ID broker from its persistent representation in * the specified file. @@ -347,6 +461,9 @@ public class ComponentBundlerTask extends Task /** The path to our component map file. */ protected File _mapfile; + /** The path to our action tilesets definition file. */ + protected File _actionDef; + /** The component directory root. */ protected String _root;