diff --git a/src/java/com/threerings/cast/CharacterComponent.java b/src/java/com/threerings/cast/CharacterComponent.java
index 8195d4264..7cebb5627 100644
--- a/src/java/com/threerings/cast/CharacterComponent.java
+++ b/src/java/com/threerings/cast/CharacterComponent.java
@@ -1,9 +1,10 @@
//
-// $Id: CharacterComponent.java,v 1.1 2001/10/26 01:17:21 shaper Exp $
+// $Id: CharacterComponent.java,v 1.2 2001/10/30 16:16:01 shaper Exp $
package com.threerings.cast;
import com.threerings.media.sprite.MultiFrameImage;
+import com.threerings.media.sprite.Sprite;
/**
* The character component represents a single component that can be
@@ -17,14 +18,16 @@ public class CharacterComponent
/**
* Constructs a character component.
*/
- public CharacterComponent (ComponentType type, int cid,
- ComponentFrames frames)
+ public CharacterComponent (
+ ComponentType type, ComponentClass cclass, int cid,
+ ComponentFrames frames)
{
_type = type;
+ _cclass = cclass;
_cid = cid;
_frames = frames;
}
-
+
/**
* Returns the unique component identifier.
*/
@@ -42,20 +45,28 @@ public class CharacterComponent
}
/**
- * Returns the {@link ComponentType} object describing the base
- * component type information associated with this component.
+ * Returns the component type associated with this component.
*/
public ComponentType getType ()
{
return _type;
}
+ /**
+ * Returns the component class associated with this component.
+ */
+ public ComponentClass getComponentClass ()
+ {
+ return _cclass;
+ }
+
/**
* Returns a string representation of this character component.
*/
public String toString ()
{
- return "[cid=" + _cid + ", type=" + _type + "]";
+ return "[cid=" + _cid + ", clid=" + _cclass.clid +
+ ", type=" + _type + "]";
}
/**
@@ -70,6 +81,15 @@ public class CharacterComponent
/** The walking animations in each orientation. */
public MultiFrameImage walk[];
+
+ /**
+ * Constructs a component frames object.
+ */
+ public ComponentFrames ()
+ {
+ stand = new MultiFrameImage[Sprite.NUM_DIRECTIONS];
+ walk = new MultiFrameImage[Sprite.NUM_DIRECTIONS];
+ }
}
/** The unique character component identifier. */
@@ -78,6 +98,9 @@ public class CharacterComponent
/** The animation frames. */
protected ComponentFrames _frames;
+ /** The component class. */
+ protected ComponentClass _cclass;
+
/** The character component type. */
protected ComponentType _type;
}
diff --git a/src/java/com/threerings/cast/CharacterDescriptor.java b/src/java/com/threerings/cast/CharacterDescriptor.java
index 63b932e1c..f326c06c1 100644
--- a/src/java/com/threerings/cast/CharacterDescriptor.java
+++ b/src/java/com/threerings/cast/CharacterDescriptor.java
@@ -1,22 +1,22 @@
//
-// $Id: CharacterDescriptor.java,v 1.1 2001/10/26 01:17:21 shaper Exp $
+// $Id: CharacterDescriptor.java,v 1.2 2001/10/30 16:16:01 shaper Exp $
package com.threerings.cast;
import com.samskivert.util.StringUtil;
/**
- * The character descriptor object contains all necessary information
- * on the character components that are composited together to create
- * a character image.
+ * The character descriptor object details the components that are
+ * pieced together to create a single character image.
*/
public class CharacterDescriptor
{
/**
* Constructs the character descriptor.
*/
- public CharacterDescriptor (int components[])
+ public CharacterDescriptor (ComponentType type, int components[])
{
+ _type = type;
_components = components;
}
@@ -29,16 +29,28 @@ public class CharacterDescriptor
return _components;
}
+ /**
+ * Returns the {@link ComponentType} of the character's components.
+ */
+ public ComponentType getType ()
+ {
+ return _type;
+ }
+
/**
* Returns a string representation of this character descriptor.
*/
public String toString ()
{
StringBuffer buf = new StringBuffer();
- buf.append("[").append(StringUtil.toString(_components));
+ buf.append("[type=").append(_type);
+ buf.append(StringUtil.toString(_components));
return buf.append("]").toString();
}
/** The array of component identifiers. */
protected int _components[];
+
+ /** The component type of the character's components. */
+ protected ComponentType _type;
}
diff --git a/src/java/com/threerings/cast/CharacterManager.java b/src/java/com/threerings/cast/CharacterManager.java
index 4c189dc93..64f8de3dd 100644
--- a/src/java/com/threerings/cast/CharacterManager.java
+++ b/src/java/com/threerings/cast/CharacterManager.java
@@ -1,15 +1,14 @@
//
-// $Id: CharacterManager.java,v 1.5 2001/10/26 01:17:21 shaper Exp $
+// $Id: CharacterManager.java,v 1.6 2001/10/30 16:16:01 shaper Exp $
package com.threerings.cast;
-import java.awt.Point;
-import java.io.IOException;
+import java.util.*;
-import com.threerings.media.tile.TileManager;
+import com.samskivert.util.CollectionUtil;
import com.threerings.cast.Log;
-import com.threerings.cast.TileUtil;
+import com.threerings.cast.CharacterComponent.ComponentFrames;
/**
* The character manager provides facilities for constructing sprites
@@ -20,11 +19,13 @@ public class CharacterManager
/**
* Constructs the character manager.
*/
- public CharacterManager (TileManager tilemgr, ComponentRepository repo)
+ public CharacterManager (ComponentRepository repo)
{
- // save off our objects
- _tilemgr = tilemgr;
+ // keep this around
_repo = repo;
+
+ // determine component class render order
+ _renderRank = getRenderRank();
}
/**
@@ -36,51 +37,81 @@ public class CharacterManager
*/
public CharacterSprite getCharacter (CharacterDescriptor desc)
{
- // get the list of component ids
+ long start = System.currentTimeMillis();
+
+ // get the array of component ids of each class
int components[] = desc.getComponents();
- // TODO: here is where we'd iterate through all components
- // building up the full composite image of the sprite in each
- // orientation, standing and walking. we punt for now, but
- // we'll revisit this soon enough.
- if (components.length == 0 || components.length > 1) {
+ if (components.length == 0) {
Log.warning("Invalid number of components " +
- " [size=" + components.length + "].");
+ "[size=" + components.length + "].");
return null;
}
- CharacterComponent comp;
- try {
- // as noted above, no compositing for now. note that when
- // we do composite, we probably will want to make sure all
- // components share a compatible component type.
- comp = _repo.getComponent(components[0]);
- } catch (Exception e) {
- Log.warning("Exception retrieving character component " +
- "[e=" + e + "].");
+ // create the composite character image
+ ComponentFrames frames = createCompositeFrames(desc);
+ if (frames == null) {
return null;
}
// instantiate the character sprite
- CharacterSprite sprite;
- try {
- sprite = (CharacterSprite)_charClass.newInstance();
- } catch (Exception e) {
- Log.warning("Failed to instantiate character sprite " +
- "[e=" + e + "].");
- Log.logStackTrace(e);
+ CharacterSprite sprite = createSprite();
+ if (sprite == null) {
return null;
}
// populate the character sprite with its attributes
- ComponentType ctype = comp.getType();
- sprite.setFrames(comp.getFrames());
+ ComponentType ctype = desc.getType();
+ sprite.setFrames(frames);
sprite.setFrameRate(ctype.fps);
sprite.setOrigin(ctype.origin.x, ctype.origin.y);
+ long end = System.currentTimeMillis();
+ Log.info("Generated character sprite [ms=" + (end - start) + "].");
+
return sprite;
}
+ /**
+ * Returns an iterator over the {@link ComponentType} objects
+ * representing all available character component type
+ * identifiers.
+ */
+ public Iterator enumerateComponentTypes ()
+ {
+ return _repo.enumerateComponentTypes();
+ }
+
+ /**
+ * Returns an iterator over the Integer objects
+ * representing all available character component identifiers for
+ * the given character component type identifier.
+ */
+ public Iterator enumerateComponentsByType (int ctid)
+ {
+ return _repo.enumerateComponentsByType(ctid);
+ }
+
+ /**
+ * Returns an iterator over the {@link ComponentClass} objects
+ * representing all available character component class
+ * identifiers.
+ */
+ public Iterator enumerateComponentClasses ()
+ {
+ return _repo.enumerateComponentClasses();
+ }
+
+ /**
+ * Returns an iterator over the Integer objects
+ * representing all available character component identifiers for
+ * the given character component type and class identifiers.
+ */
+ public Iterator enumerateComponentsByClass (int ctid, int clid)
+ {
+ return _repo.enumerateComponentsByClass(ctid, clid);
+ }
+
/**
* Instructs the character manager to construct instances of this
* derived class of CharacterSprite.
@@ -99,8 +130,77 @@ public class CharacterManager
_charClass = charClass;
}
- /** The tile manager. */
- protected TileManager _tilemgr;
+ /**
+ * Returns a {@link CharacterComponent.ComponentFrames} object
+ * containing the fully composited images detailed in the given
+ * character descriptor.
+ */
+ protected ComponentFrames createCompositeFrames (CharacterDescriptor desc)
+ {
+ int components[] = desc.getComponents();
+ ComponentFrames frames = null;
+
+ for (int ii = 0; ii < _renderRank.length; ii++) {
+ try {
+ int clidx = _renderRank[ii].clid;
+
+ // get the component to render
+ CharacterComponent c = _repo.getComponent(components[clidx]);
+
+ // TODO: fix this to deal with frames of varying dimensions
+ if (frames == null) {
+ int fcount = desc.getType().frameCount;
+ frames = TileUtil.createBlankFrames(c.getFrames(), fcount);
+ }
+
+ // render the frames onto the composite frames
+ TileUtil.compositeFrames(frames, c.getFrames());
+
+ } catch (NoSuchComponentException nsce) {
+ Log.warning("Exception compositing character components " +
+ "[nsce=" + nsce + "].");
+ return null;
+ }
+ }
+
+ return frames;
+ }
+
+ /**
+ * Returns a new {@link CharacterSprite} of the character class
+ * specified for use by this character manager.
+ */
+ protected CharacterSprite createSprite ()
+ {
+ try {
+ return (CharacterSprite)_charClass.newInstance();
+ } catch (Exception e) {
+ Log.warning("Failed to instantiate character sprite " +
+ "[e=" + e + "].");
+ Log.logStackTrace(e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns an array of {@link ComponentClass} objects sorted into
+ * the appropriate rendering order as specified by each component
+ * class object.
+ */
+ protected ComponentClass[] getRenderRank ()
+ {
+ ArrayList classes = new ArrayList();
+ CollectionUtil.addAll(classes, _repo.enumerateComponentClasses());
+
+ ComponentClass rank[] = new ComponentClass[classes.size()];
+ classes.toArray(rank);
+ Arrays.sort(rank, ComponentClass.RENDER_COMP);
+
+ return rank;
+ }
+
+ /** The order in which to render component classes. */
+ protected ComponentClass _renderRank[];
/** The component repository. */
protected ComponentRepository _repo;
diff --git a/src/java/com/threerings/cast/ComponentClass.java b/src/java/com/threerings/cast/ComponentClass.java
new file mode 100644
index 000000000..72117b56a
--- /dev/null
+++ b/src/java/com/threerings/cast/ComponentClass.java
@@ -0,0 +1,70 @@
+//
+// $Id: ComponentClass.java,v 1.1 2001/10/30 16:16:01 shaper Exp $
+
+package com.threerings.cast;
+
+import java.util.Comparator;
+
+/**
+ * The component class object denotes the particular class of
+ * components that a {@link CharacterComponent} object belongs to.
+ * Examples of feasible component classes might include "Hat", "Head",
+ * or "Feet".
+ */
+public class ComponentClass
+{
+ /** The comparator used to sort component class objects in render
+ * priority order. */
+ public static final Comparator RENDER_COMP = new RenderComparator();
+
+ /** The unique component class identifier. */
+ public int clid;
+
+ /** The component class name. */
+ public String name;
+
+ /** The render priority. */
+ public int render;
+
+ /**
+ * Returns a string representation of this component class.
+ */
+ public String toString ()
+ {
+ return "[clid=" + clid + ", name=" + name + "]";
+ }
+
+ /**
+ * The comparator used to sort component class objects in render
+ * priority order so that compositing components into a single
+ * character image can be done in the proper order.
+ */
+ protected static class RenderComparator implements Comparator
+ {
+ // documentation inherited
+ public int compare (Object a, Object b)
+ {
+ if (!(a instanceof ComponentClass) ||
+ !(b instanceof ComponentClass)) {
+ return -1;
+ }
+
+ ComponentClass ca = (ComponentClass)a;
+ ComponentClass cb = (ComponentClass)b;
+
+ if (ca.render < cb.render) {
+ return -1;
+ } else if (ca.render == cb.render) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ // documentation inherited
+ public boolean equals (Object obj)
+ {
+ return (obj == this);
+ }
+ }
+}
diff --git a/src/java/com/threerings/cast/ComponentRepository.java b/src/java/com/threerings/cast/ComponentRepository.java
index 2e9ccd0ce..f0be4736f 100644
--- a/src/java/com/threerings/cast/ComponentRepository.java
+++ b/src/java/com/threerings/cast/ComponentRepository.java
@@ -1,5 +1,5 @@
//
-// $Id: ComponentRepository.java,v 1.1 2001/10/26 01:17:21 shaper Exp $
+// $Id: ComponentRepository.java,v 1.2 2001/10/30 16:16:01 shaper Exp $
package com.threerings.cast;
@@ -17,20 +17,31 @@ public interface ComponentRepository
* unique component identifier.
*/
public CharacterComponent getComponent (int cid)
- throws NoSuchComponentException, NoSuchComponentTypeException;
+ throws NoSuchComponentException;
+
+ /**
+ * Returns an iterator over the {@link ComponentType} objects
+ * representing all available character component types.
+ */
+ public Iterator enumerateComponentTypes ();
/**
* Returns an iterator over the Integer objects
* representing all available character component identifiers for
* the given character component type identifier.
*/
- public Iterator enumerateComponents (int ctid)
- throws NoSuchComponentTypeException;
+ public Iterator enumerateComponentsByType (int ctid);
+
+ /**
+ * Returns an iterator over the {@link ComponentClass} objects
+ * representing all available character component classes.
+ */
+ public Iterator enumerateComponentClasses ();
/**
* Returns an iterator over the Integer objects
- * representing all available character component type
- * identifiers.
+ * representing all available character component identifiers for
+ * the given character component type and class identifiers.
*/
- public Iterator enumerateComponentTypes ();
+ public Iterator enumerateComponentsByClass (int ctid, int clid);
}
diff --git a/src/java/com/threerings/cast/NoSuchComponentTypeException.java b/src/java/com/threerings/cast/NoSuchComponentTypeException.java
deleted file mode 100644
index 1b44a6523..000000000
--- a/src/java/com/threerings/cast/NoSuchComponentTypeException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// $Id: NoSuchComponentTypeException.java,v 1.1 2001/10/26 01:17:21 shaper Exp $
-
-package com.threerings.cast;
-
-/**
- * Thrown when an attempt is made to reference a non-existent
- * component type in the component repository.
- */
-public class NoSuchComponentTypeException extends Exception
-{
- public NoSuchComponentTypeException (int ctid)
- {
- super("No such component type [ctid=" + ctid + "]");
- _ctid = ctid;
- }
-
- public int getTypeId ()
- {
- return _ctid;
- }
-
- protected int _ctid;
-}
diff --git a/src/java/com/threerings/cast/TileUtil.java b/src/java/com/threerings/cast/TileUtil.java
index 0200ceeaa..c51a25b0d 100644
--- a/src/java/com/threerings/cast/TileUtil.java
+++ b/src/java/com/threerings/cast/TileUtil.java
@@ -1,9 +1,10 @@
//
-// $Id: TileUtil.java,v 1.2 2001/10/26 01:40:22 mdb Exp $
+// $Id: TileUtil.java,v 1.3 2001/10/30 16:16:01 shaper Exp $
package com.threerings.cast;
import java.awt.Image;
+import java.awt.image.BufferedImage;
import com.threerings.media.sprite.*;
import com.threerings.media.tile.*;
@@ -16,6 +17,46 @@ import com.threerings.cast.CharacterComponent.ComponentFrames;
*/
public class TileUtil
{
+ /**
+ * Renders each of the given src component frames
+ * into the corresponding frames of dest.
+ */
+ public static void compositeFrames (
+ ComponentFrames dest, ComponentFrames src)
+ {
+ for (int ii = 0; ii < Sprite.NUM_DIRECTIONS; ii++) {
+ // composite the standing frames
+ compositeFrames(dest.stand[ii], src.stand[ii]);
+
+ // composite the walking frames
+ compositeFrames(dest.walk[ii], src.walk[ii]);
+ }
+ }
+
+ /**
+ * Constructs and returns a new {@link
+ * CharacterComponent.ComponentFrames} object with empty images
+ * for all of its frames.
+ */
+ public static ComponentFrames createBlankFrames (
+ ComponentFrames src, int frameCount)
+ {
+ ComponentFrames frames = new ComponentFrames();
+
+ // for now, just use the first frame from the source image to
+ // get the width and height for all of the blank frames
+ Image img = src.walk[0].getFrame(0);
+ int wid = img.getWidth(null), hei = img.getHeight(null);
+
+ // allocate the blank frame images
+ for (int ii = 0; ii < Sprite.NUM_DIRECTIONS; ii++) {
+ frames.stand[ii] = new BlankFrameImage(wid, hei, 1);
+ frames.walk[ii] = new BlankFrameImage(wid, hei, frameCount);
+ }
+
+ return frames;
+ }
+
/**
* Returns a {@link CharacterComponent.ComponentFrames} object
* containing the frames of animation used to render the sprite while
@@ -33,8 +74,6 @@ public class TileUtil
TileManager tilemgr, int tsid, int frameCount)
{
ComponentFrames frames = new ComponentFrames();
- frames.walk = new MultiFrameImage[Sprite.NUM_DIRECTIONS];
- frames.stand = new MultiFrameImage[Sprite.NUM_DIRECTIONS];
try {
for (int ii = 0; ii < Sprite.NUM_DIRECTIONS; ii++) {
@@ -63,4 +102,61 @@ public class TileUtil
return frames;
}
+
+ /**
+ * Renders each of the given src frames into the
+ * corresponding frames of dest.
+ */
+ protected static void compositeFrames (
+ MultiFrameImage dest, MultiFrameImage src)
+ {
+ int dsize = dest.getFrameCount(), ssize = src.getFrameCount();
+ if (dsize != ssize) {
+ Log.warning("Can't composite multi frame images " +
+ "with differing frame counts " +
+ "[dest=" + dsize + ", src=" + ssize + "].");
+ return;
+ }
+
+ for (int ii = 0; ii < dsize; ii++) {
+ Image dimg = dest.getFrame(ii);
+ Image simg = src.getFrame(ii);
+ dimg.getGraphics().drawImage(simg, 0, 0, null);
+ }
+ }
+
+ /**
+ * An implementation of the {@link MultiFrameImage} interface that
+ * initializes itself to contain a specified number of blank
+ * frames of the requested dimensions.
+ */
+ protected static class BlankFrameImage implements MultiFrameImage
+ {
+ /**
+ * Constructs a blank frame image.
+ */
+ public BlankFrameImage (int width, int height, int frameCount)
+ {
+ _imgs = new Image[frameCount];
+ for (int ii = 0; ii < frameCount; ii++) {
+ _imgs[ii] = new BufferedImage(
+ width, height, BufferedImage.TYPE_INT_ARGB);
+ }
+ }
+
+ // documentation inherited
+ public int getFrameCount ()
+ {
+ return _imgs.length;
+ }
+
+ // documentation inherited
+ public Image getFrame (int index)
+ {
+ return _imgs[index];
+ }
+
+ /** The frame images. */
+ protected Image _imgs[];
+ }
}
diff --git a/src/java/com/threerings/cast/builder/BuilderPanel.java b/src/java/com/threerings/cast/builder/BuilderPanel.java
new file mode 100644
index 000000000..d9f48b342
--- /dev/null
+++ b/src/java/com/threerings/cast/builder/BuilderPanel.java
@@ -0,0 +1,83 @@
+//
+// $Id: BuilderPanel.java,v 1.1 2001/10/30 16:16:01 shaper Exp $
+
+package com.threerings.cast.builder;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Iterator;
+
+import javax.swing.*;
+
+import com.samskivert.swing.*;
+
+import com.threerings.cast.*;
+
+/**
+ * The builder panel presents the user with an overview of a
+ * composited character and facilities for altering the individual
+ * components that comprise the character's display image.
+ */
+public class BuilderPanel extends JPanel implements ActionListener
+{
+ /**
+ * Constructs the builder panel.
+ */
+ public BuilderPanel (CharacterManager charmgr)
+ {
+ _charmgr = charmgr;
+
+ setLayout(new VGroupLayout());
+
+ // give ourselves a wee bit of a border
+ setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+ GroupLayout gl = new HGroupLayout(GroupLayout.STRETCH);
+ gl.setOffAxisPolicy(GroupLayout.STRETCH);
+
+ // create the component selection and sprite display panels
+ JPanel sub = new JPanel(gl);
+ ComponentType ctype = getComponentType();
+ sub.add(_comppanel = new ComponentPanel(_charmgr, ctype));
+ sub.add(_spritepanel = new SpritePanel());
+
+ add(sub);
+
+ // create the "OK" button
+ JButton ok = new JButton("OK");
+ ok.addActionListener(this);
+ ok.setActionCommand("ok");
+ add(ok);
+ }
+
+ public void actionPerformed (ActionEvent e)
+ {
+ String cmd = e.getActionCommand();
+ if (cmd.equals("ok")) {
+ CharacterDescriptor desc = _comppanel.getDescriptor();
+ CharacterSprite sprite = _charmgr.getCharacter(desc);
+ _spritepanel.setSprite(sprite);
+ } else {
+ Log.warning("Unknown action command [cmd=" + cmd + "].");
+ }
+ }
+
+ protected ComponentType getComponentType ()
+ {
+ ComponentType ctype = null;
+ Iterator types = _charmgr.enumerateComponentTypes();
+ // for now, fixedly choose the first component type
+ // TODO: fix this hack
+ return (ComponentType)types.next();
+ }
+
+ /** The component panel that displays components available for
+ * selection. */
+ protected ComponentPanel _comppanel;
+
+ /** The sprite panel that displays the composited character sprite. */
+ protected SpritePanel _spritepanel;
+
+ /** The character manager. */
+ protected CharacterManager _charmgr;
+}
diff --git a/src/java/com/threerings/cast/builder/ComponentEditor.java b/src/java/com/threerings/cast/builder/ComponentEditor.java
new file mode 100644
index 000000000..e470373e9
--- /dev/null
+++ b/src/java/com/threerings/cast/builder/ComponentEditor.java
@@ -0,0 +1,82 @@
+//
+// $Id: ComponentEditor.java,v 1.1 2001/10/30 16:16:01 shaper Exp $
+
+package com.threerings.cast.builder;
+
+import java.util.List;
+
+import javax.swing.*;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import com.samskivert.swing.*;
+import com.samskivert.util.StringUtil;
+
+import com.threerings.cast.Log;
+import com.threerings.cast.ComponentClass;
+
+/**
+ * The component editor displays a label and a slider that allow the
+ * user to select the desired component from a list of components of
+ * the same class.
+ */
+public class ComponentEditor extends JPanel implements ChangeListener
+{
+ /**
+ * Constructs a component editor.
+ */
+ public ComponentEditor (ComponentClass cclass, List components)
+ {
+ _components = components;
+
+ // Log.info("Creating editor [class=" + cclass +
+ // ", components=" + StringUtil.toString(components) + "].");
+
+ GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
+ gl.setOffAxisPolicy(GroupLayout.STRETCH);
+ setLayout(gl);
+
+ gl = new HGroupLayout();
+ gl.setJustification(GroupLayout.LEFT);
+ JPanel sub = new JPanel(gl);
+
+ sub.add(new JLabel(cclass.name + ": "));
+ sub.add(_clabel = new JLabel("0"));
+
+ add(sub);
+
+ int max = components.size() - 1;
+ _slider = new JSlider(JSlider.HORIZONTAL, 0, max, 0);
+ _slider.setSnapToTicks(true);
+ _slider.addChangeListener(this);
+ add(_slider);
+ }
+
+ /**
+ * Returns the selected component id.
+ */
+ public int getSelectedComponent ()
+ {
+ int idx = _slider.getModel().getValue();
+ return ((Integer)_components.get(idx)).intValue();
+ }
+
+ // documentation inherited
+ public void stateChanged (ChangeEvent e)
+ {
+ JSlider source = (JSlider)e.getSource();
+ if (!source.getValueIsAdjusting()) {
+ _clabel.setText(Integer.toString(source.getValue()));
+ }
+ }
+
+ /** The components selectable via this editor. */
+ protected List _components;
+
+ /** The slider allowing the user to select a component. */
+ protected JSlider _slider;
+
+ /** The label denoting the currently selected component index. */
+ protected JLabel _clabel;
+}
diff --git a/src/java/com/threerings/cast/builder/ComponentPanel.java b/src/java/com/threerings/cast/builder/ComponentPanel.java
new file mode 100644
index 000000000..4eabacd41
--- /dev/null
+++ b/src/java/com/threerings/cast/builder/ComponentPanel.java
@@ -0,0 +1,126 @@
+//
+// $Id: ComponentPanel.java,v 1.1 2001/10/30 16:16:01 shaper Exp $
+
+package com.threerings.cast.builder;
+
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+
+import com.samskivert.swing.*;
+import com.samskivert.util.*;
+
+import com.threerings.cast.Log;
+import com.threerings.cast.*;
+
+/**
+ * The component panel displays the available components for a
+ * particular component type, allows the user to choose a set of
+ * components for compositing, and makes available a {@link
+ * CharacterDescriptor} suitable for passing to {@link
+ * CharacterManager#getCharacter} to create a character built from the
+ * chosen components.
+ */
+public class ComponentPanel extends JPanel
+{
+ /**
+ * Constructs the component panel.
+ */
+ public ComponentPanel (CharacterManager charmgr, ComponentType type)
+ {
+ // save off references
+ _type = type;
+
+ // retrieve component classes and relevant components
+ gatherComponentInfo(charmgr);
+
+ GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH);
+ gl.setOffAxisPolicy(GroupLayout.STRETCH);
+ setLayout(gl);
+
+ // set up a border
+ setBorder(BorderFactory.createEtchedBorder());
+
+ // add the component editors to the panel
+ addComponentEditors();
+ }
+
+ /**
+ * Returns a {@link CharacterDescriptor} detailing the selected
+ * character components.
+ */
+ public CharacterDescriptor getDescriptor ()
+ {
+ int size = _classes.size();
+ int comps[] = new int[size];
+ for (int ii = 0; ii < size; ii++) {
+ ComponentClass cclass = (ComponentClass)_classes.get(ii);
+ ComponentEditor ce = (ComponentEditor)_editors.get(ii);
+ comps[cclass.clid] = ce.getSelectedComponent();
+ }
+
+ return new CharacterDescriptor(_type, comps);
+ }
+
+ /**
+ * Gathers component information from the character manager for
+ * later use when creating the editor components and the resulting
+ * character descriptor.
+ */
+ protected void gatherComponentInfo (CharacterManager charmgr)
+ {
+ // get the list of all component classes
+ CollectionUtil.addAll(_classes, charmgr.enumerateComponentClasses());
+
+ for (int ii = 0; ii < _classes.size(); ii++) {
+ // get the list of components available for this class
+ int ctid = _type.ctid;
+ int clid = ((ComponentClass)_classes.get(ii)).clid;
+ Iterator comps = charmgr.enumerateComponentsByClass(ctid, clid);
+
+ while (comps.hasNext()) {
+ Integer cid = (Integer)comps.next();
+
+ ArrayList clist = (ArrayList)_classinfo.get(clid);
+ if (clist == null) {
+ _classinfo.put(clid, clist = new ArrayList());
+ }
+
+ clist.add(cid);
+ }
+ }
+ }
+
+ /**
+ * Adds editor user interface elements for each component class to
+ * allow the user to select the desired component.
+ */
+ protected void addComponentEditors ()
+ {
+ int size = _classes.size();
+ for (int ii = 0; ii < size; ii++) {
+ ComponentClass cclass = (ComponentClass)_classes.get(ii);
+ List components = (List)_classinfo.get(cclass.clid);
+
+ // create the component editor
+ ComponentEditor e = new ComponentEditor(cclass, components);
+ _editors.add(e);
+
+ // add it to the panel
+ add(e);
+ }
+ }
+
+ /** The component type associated with the character components. */
+ protected ComponentType _type;
+
+ /** The list of all available component classes. */
+ protected ArrayList _classes = new ArrayList();
+
+ /** The list of component editors for each component class. */
+ protected ArrayList _editors = new ArrayList();
+
+ /** The hashtable of available component ids for each class. */
+ protected HashIntMap _classinfo = new HashIntMap();
+}
diff --git a/src/java/com/threerings/cast/builder/SpritePanel.java b/src/java/com/threerings/cast/builder/SpritePanel.java
new file mode 100644
index 000000000..451e0bbd0
--- /dev/null
+++ b/src/java/com/threerings/cast/builder/SpritePanel.java
@@ -0,0 +1,89 @@
+//
+// $Id: SpritePanel.java,v 1.1 2001/10/30 16:16:01 shaper Exp $
+
+package com.threerings.cast.builder;
+
+import java.awt.*;
+import javax.swing.BorderFactory;
+import javax.swing.border.BevelBorder;
+
+import com.threerings.media.sprite.*;
+
+import com.threerings.cast.Log;
+import com.threerings.cast.CharacterSprite;
+
+/**
+ * The sprite panel displays a character sprite centered in the panel
+ * suitable for user perusal.
+ */
+public class SpritePanel extends AnimatedPanel
+{
+ /**
+ * Constructs the sprite panel.
+ */
+ public SpritePanel ()
+ {
+ // create and save off references to our managers
+ _spritemgr = new SpriteManager();
+ _animmgr = new AnimationManager(_spritemgr, this);
+
+ // create a visually pleasing border
+ setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
+ }
+
+ /**
+ * Sets the sprite to be displayed.
+ */
+ public void setSprite (CharacterSprite sprite)
+ {
+ _sprite = sprite;
+ _sprite.setOrientation(Sprite.DIR_SOUTHWEST);
+ centerSprite();
+ repaint();
+ }
+
+ // documentation inherited
+ protected void render (Graphics g)
+ {
+ Graphics2D gfx = (Graphics2D)g;
+
+ // clear the background
+ gfx.setColor(Color.lightGray);
+ Dimension d = getSize();
+ gfx.fillRect(0, 0, d.width - 1, d.height - 1);
+
+ if (_sprite != null) {
+ // render the sprite
+ _sprite.paint((Graphics2D)g);
+ }
+ }
+
+ // documentation inherited
+ public void setBounds (Rectangle r)
+ {
+ super.setBounds(r);
+ centerSprite();
+ }
+
+ /**
+ * Sets the sprite's location to render it centered within the panel.
+ */
+ protected void centerSprite ()
+ {
+ if (_sprite != null) {
+ Dimension d = getSize();
+ int swid = _sprite.getWidth(), shei = _sprite.getHeight();
+ int x = d.width / 2, y = (d.height + shei) / 2;
+ _sprite.setLocation(x, y);
+ }
+ }
+
+ /** The sprite displayed by the panel. */
+ protected Sprite _sprite;
+
+ /** The animation manager. */
+ protected AnimationManager _animmgr;
+
+ /** The sprite manager. */
+ protected SpriteManager _spritemgr;
+}
diff --git a/src/java/com/threerings/cast/tools/xml/XMLComponentParser.java b/src/java/com/threerings/cast/tools/xml/XMLComponentParser.java
index 7b0d87b56..a405bae47 100644
--- a/src/java/com/threerings/cast/tools/xml/XMLComponentParser.java
+++ b/src/java/com/threerings/cast/tools/xml/XMLComponentParser.java
@@ -1,5 +1,5 @@
//
-// $Id: XMLComponentParser.java,v 1.1 2001/10/26 01:17:21 shaper Exp $
+// $Id: XMLComponentParser.java,v 1.2 2001/10/30 16:16:01 shaper Exp $
package com.threerings.cast;
@@ -10,8 +10,16 @@ import org.xml.sax.*;
import com.samskivert.util.HashIntMap;
import com.samskivert.util.StringUtil;
+import com.samskivert.util.Tuple;
import com.samskivert.xml.SimpleParser;
+/**
+ * Parses an XML character component description file and populates
+ * hashtables with component type, component class, and specific
+ * component information. Does not currently perform validation on
+ * the input XML stream, though the parsing code assumes the XML
+ * document is well-formed.
+ */
public class XMLComponentParser extends SimpleParser
{
// documentation inherited
@@ -28,31 +36,52 @@ public class XMLComponentParser extends SimpleParser
ct.fps = parseInt(attributes.getValue("fps"));
parsePoint(attributes.getValue("origin"), ct.origin);
- Log.info("Parsed component type [ct=" + ct + "].");
-
// save the component type
_types.put(ct.ctid, ct);
+ } else if (qName.equals("class")) {
+ // save off the component class info
+ ComponentClass cclass = new ComponentClass();
+ cclass.clid = parseInt(attributes.getValue("clid"));
+ cclass.name = attributes.getValue("name");
+ cclass.render = parseInt(attributes.getValue("render"));
+ _classes.put(cclass.clid, cclass);
+
} else if (qName.equals("component")) {
- // save off the component info
+ // retrieve the component attributes
int cid = parseInt(attributes.getValue("cid"));
int ctid = parseInt(attributes.getValue("ctid"));
- _components.put(cid, new Integer(ctid));
+ int clid = parseInt(attributes.getValue("clid"));
+
+ // output a warning if the component references valid
+ // attributes
+ if (_types.get(ctid) == null) {
+ Log.warning("Component references non-existent type " +
+ "[cid=" + cid + ", ctid=" + ctid + "].");
+ }
+ if (_classes.get(clid) == null) {
+ Log.warning("Component references non-existent class " +
+ "[cid=" + cid + ", clid=" + clid + "].");
+ }
+
+ // save off the component information
+ _components.put(cid, new Tuple(
+ new Integer(ctid), new Integer(clid)));
}
}
/**
- * Loads the component descriptions in the given file into {@link
- * ComponentType} and {@link CharacterComponent} objects in the
- * given hashtables, respectively, keyed on the type and component
- * unique id, also respectively.
+ * Loads the component descriptions in the given file into the
+ * given component data hashtables.
*/
public void loadComponents (
- String file, HashIntMap types, HashIntMap components)
+ String file, HashIntMap types, HashIntMap classes,
+ HashIntMap components)
throws IOException
{
// save off hashtables for reference while parsing
_types = types;
+ _classes = classes;
_components = components;
parseFile(file);
@@ -77,4 +106,7 @@ public class XMLComponentParser extends SimpleParser
/** The hashtable of character components gathered while parsing. */
protected HashIntMap _components;
+
+ /** The hashtable of component classes gathered while parsing. */
+ protected HashIntMap _classes;
}
diff --git a/src/java/com/threerings/cast/tools/xml/XMLComponentRepository.java b/src/java/com/threerings/cast/tools/xml/XMLComponentRepository.java
index f2e181e18..b0735451b 100644
--- a/src/java/com/threerings/cast/tools/xml/XMLComponentRepository.java
+++ b/src/java/com/threerings/cast/tools/xml/XMLComponentRepository.java
@@ -1,13 +1,15 @@
//
-// $Id: XMLComponentRepository.java,v 1.1 2001/10/26 01:17:22 shaper Exp $
+// $Id: XMLComponentRepository.java,v 1.2 2001/10/30 16:16:01 shaper Exp $
package com.threerings.miso.scene.xml;
import java.io.IOException;
+import java.util.Collections;
import java.util.Iterator;
import com.samskivert.util.Config;
import com.samskivert.util.HashIntMap;
+import com.samskivert.util.Tuple;
import com.threerings.cast.*;
import com.threerings.cast.CharacterComponent.ComponentFrames;
@@ -35,8 +37,8 @@ public class XMLFileComponentRepository implements ComponentRepository
// load component types and components
String file = config.getValue(COMPFILE_KEY, DEFAULT_COMPFILE);
try {
- new XMLComponentParser().loadComponents(
- file, _types, _components);
+ XMLComponentParser p = new XMLComponentParser();
+ p.loadComponents(file, _types, _classes, _components);
} catch (IOException ioe) {
Log.warning("Exception loading component descriptions " +
"[ioe=" + ioe + "].");
@@ -45,59 +47,77 @@ public class XMLFileComponentRepository implements ComponentRepository
// documentation inherited
public CharacterComponent getComponent (int cid)
- throws NoSuchComponentException, NoSuchComponentTypeException
+ throws NoSuchComponentException
{
- // get the component type id
- Integer ctid = (Integer)_components.get(cid);
- if (ctid == null) {
+ // get the component information
+ Tuple cinfo = (Tuple)_components.get(cid);
+ if (cinfo == null) {
throw new NoSuchComponentException(cid);
}
// get the component type
- ComponentType type = (ComponentType)_types.get(ctid.intValue());
- if (type == null) {
- throw new NoSuchComponentTypeException(ctid.intValue());
- }
+ int ctid = ((Integer)cinfo.left).intValue();
+ ComponentType type = (ComponentType)_types.get(ctid);
+
+ // get the component class
+ int clid = ((Integer)cinfo.right).intValue();
+ ComponentClass cclass = (ComponentClass)_classes.get(clid);
// get the character animation images
ComponentFrames frames = TileUtil.getComponentFrames(
_tilemgr, cid, type.frameCount);
// create the component
- return new CharacterComponent(type, cid, frames);
- }
-
- // documentation inherited
- public Iterator enumerateComponents (int ctid)
- throws NoSuchComponentTypeException
- {
- return new ComponentTypeIterator(ctid);
+ return new CharacterComponent(type, cclass, cid, frames);
}
// documentation inherited
public Iterator enumerateComponentTypes ()
{
- return _types.keys();
+ return Collections.unmodifiableMap(_types).values().iterator();
+ }
+
+ // documentation inherited
+ public Iterator enumerateComponentsByType (int ctid)
+ {
+ return new ComponentIterator(ctid);
+ }
+
+ // documentation inherited
+ public Iterator enumerateComponentClasses ()
+ {
+ return Collections.unmodifiableMap(_classes).values().iterator();
+ }
+
+ // documentation inherited
+ public Iterator enumerateComponentsByClass (int ctid, int clid)
+ {
+ return new ComponentIterator(ctid, clid);
}
/**
- * Iterates over all components of a specified component type in
- * the component hashtable.
+ * Iterates over all components of a specified component type, and
+ * optionally a specified component class, in the component
+ * hashtable.
*/
- protected class ComponentTypeIterator implements Iterator
+ protected class ComponentIterator implements Iterator
{
- public ComponentTypeIterator (int ctid)
- throws NoSuchComponentTypeException
+ /**
+ * Constructs an iterator that iterates over all components of
+ * the specified component type.
+ */
+ public ComponentIterator (int ctid)
{
- _ctid = ctid;
- _iter = _components.keys();
- advance();
+ init(ctid, -1);
+ }
- // make sure we have at least one component of the
- // specified type
- if (_next == null) {
- throw new NoSuchComponentTypeException(ctid);
- }
+ /**
+ * Constructs an iterator that iterates over all components of
+ * the specified component type and class.
+ */
+ public ComponentIterator (int ctid, int clid)
+ {
+ init(ctid, clid);
}
public boolean hasNext ()
@@ -117,12 +137,25 @@ public class XMLFileComponentRepository implements ComponentRepository
throw new UnsupportedOperationException();
}
+ protected void init (int ctid, int clid)
+ {
+ _ctid = ctid;
+ _clid = clid;
+ _iter = _components.keys();
+ advance();
+ }
+
protected void advance ()
{
while (_iter.hasNext()) {
- CharacterComponent c = (CharacterComponent)_iter.next();
- if (c.getType().ctid == _ctid) {
- _next = c;
+ Integer cid = (Integer)_iter.next();
+
+ Tuple c = (Tuple)_components.get(cid);
+ int ctid = ((Integer)c.left).intValue();
+ int clid = ((Integer)c.right).intValue();
+ if (ctid == _ctid &&
+ (_clid == -1 || (clid == _clid))) {
+ _next = cid;
return;
}
}
@@ -132,11 +165,15 @@ public class XMLFileComponentRepository implements ComponentRepository
/** The component type id we're enumerating over. */
protected int _ctid;
+ /** The component class id required for inclusion in the
+ * iterator, or -1 for all classes. */
+ protected int _clid;
+
/** The next character component of the component type id
* associated with this iterator, or null if no more exist. */
protected Object _next;
- /** Iterator over the components in the repository. */
+ /** The iterator over all components in the repository. */
protected Iterator _iter;
}
@@ -151,6 +188,9 @@ public class XMLFileComponentRepository implements ComponentRepository
/** The hashtable of component types. */
protected HashIntMap _types = new HashIntMap();
+ /** The hashtable of component classes. */
+ protected HashIntMap _classes = new HashIntMap();
+
/** The hashtable of character components. */
protected HashIntMap _components = new HashIntMap();
diff --git a/src/java/com/threerings/miso/client/DirtyItemList.java b/src/java/com/threerings/miso/client/DirtyItemList.java
index f11768671..d6a8f72d1 100644
--- a/src/java/com/threerings/miso/client/DirtyItemList.java
+++ b/src/java/com/threerings/miso/client/DirtyItemList.java
@@ -1,5 +1,5 @@
//
-// $Id: DirtyItemList.java,v 1.4 2001/10/26 01:17:21 shaper Exp $
+// $Id: DirtyItemList.java,v 1.5 2001/10/30 16:16:01 shaper Exp $
package com.threerings.miso.scene;
@@ -142,7 +142,9 @@ public class DirtyItemList extends ArrayList
public String toString ()
{
- return "[obj=" + obj + ", ox=" + ox + ", oy=" + oy + "]";
+ return "[obj=" + obj + ", ox=" + ox + ", oy=" + oy +
+ ", lx=" + lx + ", ly=" + ly + ", rx=" + rx +
+ ", ry=" + ry + "]";
}
}
@@ -163,28 +165,36 @@ public class DirtyItemList extends ArrayList
DirtyItem db = (DirtyItem)b;
if (da.ox == db.ox &&
- da.oy == db.oy &&
- (da.obj instanceof MisoCharacterSprite) &&
- (db.obj instanceof MisoCharacterSprite)) {
- // we're comparing two sprites co-existing on the same
- // tile, so study their fine coordinates to determine
- // rendering order
- MisoCharacterSprite as = (MisoCharacterSprite)da.obj;
- MisoCharacterSprite bs = (MisoCharacterSprite)db.obj;
+ da.oy == db.oy) {
- int ahei = as.getFineX() + as.getFineY();
- int bhei = bs.getFineX() + bs.getFineY();
+ if (da.equals(db)) {
+ // render level is equal if we're the same sprite
+ // or an object at the same location
+ return 0;
+ }
- if (ahei < bhei) {
- // item b is in front of item a
- return -1;
- } else if (ahei > bhei) {
- // item a is in front of item b
- return 1;
- } else {
- // if they're at the same vertical row of
- // intra-tile tiles, just use something consistent
- return as.hashCode() - bs.hashCode();
+ if ((da.obj instanceof MisoCharacterSprite) &&
+ (db.obj instanceof MisoCharacterSprite)) {
+ // we're comparing two sprites co-existing on the same
+ // tile, so study their fine coordinates to determine
+ // rendering order
+ MisoCharacterSprite as = (MisoCharacterSprite)da.obj;
+ MisoCharacterSprite bs = (MisoCharacterSprite)db.obj;
+
+ int ahei = as.getFineX() + as.getFineY();
+ int bhei = bs.getFineX() + bs.getFineY();
+
+ if (ahei < bhei) {
+ // item b is in front of item a
+ return -1;
+ } else if (ahei > bhei) {
+ // item a is in front of item b
+ return 1;
+ } else {
+ // if they're at the same vertical row of
+ // intra-tile tiles, just use something consistent
+ return as.hashCode() - bs.hashCode();
+ }
}
}
@@ -192,10 +202,10 @@ public class DirtyItemList extends ArrayList
da.ry > db.oy) {
// item a is in front of item b
return 1;
- } else {
- // item b is in front of item a
- return -1;
}
+
+ // item b is in front of item a
+ return -1;
}
public boolean equals (Object obj)
diff --git a/src/java/com/threerings/miso/util/MisoUtil.java b/src/java/com/threerings/miso/util/MisoUtil.java
index 3a7b6ac07..20210e364 100644
--- a/src/java/com/threerings/miso/util/MisoUtil.java
+++ b/src/java/com/threerings/miso/util/MisoUtil.java
@@ -1,5 +1,5 @@
//
-// $Id: MisoUtil.java,v 1.10 2001/10/26 01:17:22 shaper Exp $
+// $Id: MisoUtil.java,v 1.11 2001/10/30 16:16:01 shaper Exp $
package com.threerings.miso.util;
@@ -43,6 +43,41 @@ public class MisoUtil
config.bindProperties(CONFIG_KEY, "rsrc/config/miso/miso");
}
+ /**
+ * Creates a Config object that contains
+ * configuration parameters for miso.
+ */
+ public static Config createConfig ()
+ {
+ return createConfig(null, null);
+ }
+
+ /**
+ * Creates a Config object that contains
+ * configuration parameters for miso. If key and
+ * path are non-null, the properties in
+ * the given file will additionally be bound to the specified
+ * config key namespace.
+ */
+ public static Config createConfig (String key, String path)
+ {
+ Config config = new Config();
+ try {
+ // load the miso config info
+ bindProperties(config);
+
+ if (key != null && path != null) {
+ // load the application-specific config info
+ config.bindProperties(key, path);
+ }
+
+ } catch (IOException ioe) {
+ Log.warning("Error loading config information [e=" + ioe + "].");
+ }
+
+ return config;
+ }
+
/**
* Creates a CharacterManager object.
*
@@ -57,7 +92,7 @@ public class MisoUtil
{
XMLFileComponentRepository crepo =
new XMLFileComponentRepository(config, tilemgr);
- CharacterManager charmgr = new CharacterManager(tilemgr, crepo);
+ CharacterManager charmgr = new CharacterManager(crepo);
charmgr.setCharacterClass(MisoCharacterSprite.class);
return charmgr;
}
diff --git a/tests/src/java/com/threerings/cast/builder/TestApp.java b/tests/src/java/com/threerings/cast/builder/TestApp.java
new file mode 100644
index 000000000..c3670906b
--- /dev/null
+++ b/tests/src/java/com/threerings/cast/builder/TestApp.java
@@ -0,0 +1,77 @@
+//
+// $Id: TestApp.java,v 1.1 2001/10/30 16:16:01 shaper Exp $
+
+package com.threerings.cast.builder.test;
+
+import java.io.IOException;
+import javax.swing.JFrame;
+
+import com.samskivert.util.Config;
+import com.samskivert.swing.util.SwingUtil;
+
+import com.threerings.cast.Log;
+import com.threerings.cast.CharacterManager;
+import com.threerings.media.tile.TileManager;
+
+import com.threerings.miso.util.MisoContext;
+import com.threerings.miso.util.MisoUtil;
+
+public class TestApp
+{
+ public TestApp (String[] args)
+ {
+ _frame = new TestFrame();
+ _frame.setSize(800, 600);
+ SwingUtil.centerWindow(_frame);
+
+ // create the handles on our various services
+ _config = MisoUtil.createConfig();
+ _tilemgr = MisoUtil.createTileManager(_config, _frame);
+
+ CharacterManager charmgr =
+ MisoUtil.createCharacterManager(_config, _tilemgr);
+
+ // create the context object
+ _ctx = new TestContextImpl();
+
+ // initialize the frame
+ ((TestFrame)_frame).init(charmgr);
+ }
+
+ public void run ()
+ {
+ _frame.pack();
+ _frame.show();
+ }
+
+ public static void main (String[] args)
+ {
+ TestApp app = new TestApp(args);
+ app.run();
+ }
+
+ protected class TestContextImpl implements MisoContext
+ {
+ public Config getConfig ()
+ {
+ return _config;
+ }
+
+ public TileManager getTileManager ()
+ {
+ return _tilemgr;
+ }
+ }
+
+ /** The test frame. */
+ protected JFrame _frame;
+
+ /** The test context. */
+ protected MisoContext _ctx;
+
+ /** The config object. */
+ protected Config _config;
+
+ /** The tile manager object. */
+ protected TileManager _tilemgr;
+}
diff --git a/tests/src/java/com/threerings/cast/builder/TestFrame.java b/tests/src/java/com/threerings/cast/builder/TestFrame.java
new file mode 100644
index 000000000..8b4c484d4
--- /dev/null
+++ b/tests/src/java/com/threerings/cast/builder/TestFrame.java
@@ -0,0 +1,25 @@
+//
+// $Id: TestFrame.java,v 1.1 2001/10/30 16:16:01 shaper Exp $
+
+package com.threerings.cast.builder.test;
+
+import javax.swing.JFrame;
+
+import com.threerings.cast.CharacterManager;
+import com.threerings.cast.builder.BuilderPanel;
+
+public class TestFrame extends JFrame
+{
+ public TestFrame ()
+ {
+ super("Character Builder");
+
+ setResizable(false);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+ }
+
+ public void init (CharacterManager charmgr)
+ {
+ getContentPane().add(new BuilderPanel(charmgr));
+ }
+}
diff --git a/tests/src/java/com/threerings/miso/viewer/ViewerApp.java b/tests/src/java/com/threerings/miso/viewer/ViewerApp.java
index 4c150346a..25da6e54b 100644
--- a/tests/src/java/com/threerings/miso/viewer/ViewerApp.java
+++ b/tests/src/java/com/threerings/miso/viewer/ViewerApp.java
@@ -1,5 +1,5 @@
//
-// $Id: ViewerApp.java,v 1.9 2001/10/17 22:16:04 shaper Exp $
+// $Id: ViewerApp.java,v 1.10 2001/10/30 16:16:01 shaper Exp $
package com.threerings.miso.viewer;
@@ -32,7 +32,8 @@ public class ViewerApp
SwingUtil.centerWindow(_frame);
// create the handles on our various services
- _config = createConfig();
+ _config = MisoUtil.createConfig(
+ ViewerModel.CONFIG_KEY, "rsrc/config/miso/viewer");
_model = createModel(_config, args);
_tilemgr = MisoUtil.createTileManager(_config, _frame);
_screpo = MisoUtil.createSceneRepository(_config, _tilemgr);
@@ -44,28 +45,6 @@ public class ViewerApp
((ViewerFrame)_frame).init(_ctx);
}
- /**
- * Create the config object that contains configuration parameters
- * for the application and other utilized packages.
- */
- protected Config createConfig ()
- {
- Config config = new Config();
- try {
- // load the miso config info
- MisoUtil.bindProperties(config);
-
- // load the viewer-specific config info
- config.bindProperties(
- ViewerModel.CONFIG_KEY, "rsrc/config/miso/viewer");
-
- } catch (IOException ioe) {
- Log.warning("Error loading config information [e=" + ioe + "].");
- }
-
- return config;
- }
-
protected ViewerModel createModel (Config config, String args[])
{
ViewerModel model = new ViewerModel(config);
diff --git a/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java b/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java
index 04c148020..a53f0d977 100644
--- a/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java
+++ b/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java
@@ -1,13 +1,16 @@
//
-// $Id: ViewerSceneViewPanel.java,v 1.24 2001/10/27 01:35:21 shaper Exp $
+// $Id: ViewerSceneViewPanel.java,v 1.25 2001/10/30 16:16:01 shaper Exp $
package com.threerings.miso.viewer;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
import javax.swing.JPanel;
+import com.samskivert.util.CollectionUtil;
import com.samskivert.util.Config;
import com.threerings.cast.*;
@@ -47,8 +50,12 @@ public class ViewerSceneViewPanel extends SceneViewPanel
CharacterManager charmgr = MisoUtil.createCharacterManager(
ctx.getConfig(), ctx.getTileManager());
+ // create the character descriptors
+ _descUser = createCharacterDescriptor(charmgr);
+ _descDecoy = createCharacterDescriptor(charmgr);
+
// create the manipulable sprite
- _sprite = createSprite(spritemgr, charmgr, TSID_CHAR_USER);
+ _sprite = createSprite(spritemgr, charmgr, _descUser);
// create the decoy sprites
createDecoys(spritemgr, charmgr);
@@ -67,10 +74,9 @@ public class ViewerSceneViewPanel extends SceneViewPanel
* Creates a new sprite.
*/
protected MisoCharacterSprite createSprite (
- SpriteManager spritemgr, CharacterManager charmgr, int tsid)
+ SpriteManager spritemgr, CharacterManager charmgr,
+ CharacterDescriptor desc)
{
- int dummy[] = { tsid };
- CharacterDescriptor desc = new CharacterDescriptor(dummy);
MisoCharacterSprite s =
(MisoCharacterSprite)charmgr.getCharacter(desc);
if (s != null) {
@@ -91,7 +97,7 @@ public class ViewerSceneViewPanel extends SceneViewPanel
{
_decoys = new MisoCharacterSprite[NUM_DECOYS];
for (int ii = 0; ii < NUM_DECOYS; ii++) {
- _decoys[ii] = createSprite(spritemgr, charmgr, TSID_CHAR);
+ _decoys[ii] = createSprite(spritemgr, charmgr, _descDecoy);
if (_decoys[ii] != null) {
createRandomPath(_decoys[ii]);
}
@@ -179,6 +185,42 @@ public class ViewerSceneViewPanel extends SceneViewPanel
} while (!createPath(s, x, y));
}
+ /**
+ * Returns a new {@link CharacterDescriptor} suitable for use in
+ * creating character sprites via {@link
+ * CharacterManager#getCharacter}.
+ */
+ protected CharacterDescriptor
+ createCharacterDescriptor (CharacterManager charmgr)
+ {
+ // get the base component type (always the first type for now).
+ // TODO: change this to retrieve component type by name
+ Iterator iter = charmgr.enumerateComponentTypes();
+ ComponentType ctype = (ComponentType)iter.next();
+
+ // get all available classes
+ ArrayList classes = new ArrayList();
+ CollectionUtil.addAll(classes, charmgr.enumerateComponentClasses());
+
+ // select the components
+ int size = classes.size();
+ int components[] = new int[size];
+ for (int ii = 0; ii < size; ii++) {
+ ComponentClass cclass = (ComponentClass)classes.get(ii);
+
+ // get the components available for this class
+ ArrayList choices = new ArrayList();
+ iter = charmgr.enumerateComponentsByClass(ctype.ctid, cclass.clid);
+ CollectionUtil.addAll(choices, iter);
+
+ // choose a random component
+ int idx = RandomUtil.getInt(choices.size());
+ components[cclass.clid] = ((Integer)choices.get(idx)).intValue();
+ }
+
+ return new CharacterDescriptor(ctype, components);
+ }
+
// documentation inherited
public void handleEvent (SpriteEvent event)
{
@@ -193,13 +235,13 @@ public class ViewerSceneViewPanel extends SceneViewPanel
}
/** The number of decoy characters milling about. */
- protected static final int NUM_DECOYS = 2;
+ protected static final int NUM_DECOYS = 10;
- /** The tileset id for the decoy character tiles. */
- protected static final int TSID_CHAR = 1011;
+ /** The character descriptor for the user character. */
+ protected CharacterDescriptor _descUser;
- /** The tileset id for the user character tiles. */
- protected static final int TSID_CHAR_USER = 1012;
+ /** The character descriptor for the decoy characters. */
+ protected CharacterDescriptor _descDecoy;
/** The animation manager. */
protected AnimationManager _animmgr;