From 662b60e53e59b13baa1e596c2fc7c82e45259700 Mon Sep 17 00:00:00 2001 From: Walter Korman Date: Fri, 2 Nov 2001 01:10:28 +0000 Subject: [PATCH] Update the character image immediately when a component is selected. General clean-up. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@583 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../com/threerings/cast/CharacterManager.java | 5 +- .../threerings/cast/builder/BuilderModel.java | 124 ++++++++++++++++++ .../cast/builder/BuilderModelListener.java | 22 ++++ .../threerings/cast/builder/BuilderPanel.java | 43 ++---- .../threerings/cast/builder/ClassEditor.java | 93 +++++++++++++ .../cast/builder/ComponentEditor.java | 82 ------------ .../cast/builder/ComponentPanel.java | 101 +++----------- .../threerings/cast/builder/SpritePanel.java | 71 +++++++--- 8 files changed, 322 insertions(+), 219 deletions(-) create mode 100644 src/java/com/threerings/cast/builder/BuilderModel.java create mode 100644 src/java/com/threerings/cast/builder/BuilderModelListener.java create mode 100644 src/java/com/threerings/cast/builder/ClassEditor.java delete mode 100644 src/java/com/threerings/cast/builder/ComponentEditor.java diff --git a/src/java/com/threerings/cast/CharacterManager.java b/src/java/com/threerings/cast/CharacterManager.java index 3cdc7ab7b..026fc5964 100644 --- a/src/java/com/threerings/cast/CharacterManager.java +++ b/src/java/com/threerings/cast/CharacterManager.java @@ -1,5 +1,5 @@ // -// $Id: CharacterManager.java,v 1.7 2001/11/01 01:40:42 shaper Exp $ +// $Id: CharacterManager.java,v 1.8 2001/11/02 01:10:28 shaper Exp $ package com.threerings.cast; @@ -43,7 +43,7 @@ public class CharacterManager // get the array of component ids of each class CharacterComponent components[] = getComponents(desc.getComponents()); - if (components.length == 0) { + if (components == null || components.length == 0) { Log.warning("No character components in descriptor."); return null; } @@ -146,7 +146,6 @@ public class CharacterManager // render all component frames one atop another for (int ii = 0; ii < _renderRank.length; ii++) { int clidx = _renderRank[ii].clid; - Log.info("Compositing component [c=" + components[clidx] + "]."); TileUtil.compositeFrames(frames, components[clidx].getFrames()); } diff --git a/src/java/com/threerings/cast/builder/BuilderModel.java b/src/java/com/threerings/cast/builder/BuilderModel.java new file mode 100644 index 000000000..c12b4a6db --- /dev/null +++ b/src/java/com/threerings/cast/builder/BuilderModel.java @@ -0,0 +1,124 @@ +// +// $Id: BuilderModel.java,v 1.1 2001/11/02 01:10:28 shaper Exp $ + +package com.threerings.cast.builder; + +import java.util.*; + +import com.samskivert.util.CollectionUtil; +import com.samskivert.util.HashIntMap; + +import com.threerings.cast.CharacterManager; +import com.threerings.cast.ComponentClass; + +/** + * The builder model represents the current state of the character + * the user is building. + */ +public class BuilderModel +{ + /** + * Constructs a builder model. + */ + public BuilderModel (CharacterManager charmgr) + { + gatherComponentInfo(charmgr); + _selected = new int[_classes.size()]; + } + + /** + * Adds a builder model listener. + * + * @param l the listener. + */ + public void addListener (BuilderModelListener l) + { + if (!_listeners.contains(l)) { + _listeners.add(l); + } + } + + /** + * Notifies all model listeners that the builder model has changed. + */ + protected void notifyListeners (int event) + { + int size = _listeners.size(); + for (int ii = 0; ii < size; ii++) { + ((BuilderModelListener)_listeners.get(ii)).modelChanged(event); + } + } + + /** + * Returns a list of the available component classes. + */ + public List getComponentClasses () + { + return _classes; + } + + /** + * Returns a hashtable of the components available for each + * component class, keyed on component class id. + */ + public HashIntMap getComponents () + { + return _components; + } + + /** + * Returns an array of the currently selected component ids. + */ + public int[] getSelectedComponents () + { + return _selected; + } + + /** + * Sets the selected component for the given component class id. + */ + public void setSelectedComponent (int clid, int cid) + { + _selected[clid] = cid; + notifyListeners(BuilderModelListener.COMPONENT_CHANGED); + } + + /** + * Gathers component class and component information from the + * character manager for later reference by others. + */ + 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 clid = ((ComponentClass)_classes.get(ii)).clid; + Iterator iter = charmgr.enumerateComponentsByClass(clid); + + while (iter.hasNext()) { + Integer cid = (Integer)iter.next(); + + ArrayList clist = (ArrayList)_components.get(clid); + if (clist == null) { + _components.put(clid, clist = new ArrayList()); + } + + clist.add(cid); + } + } + } + + /** The currently selected character components. */ + protected int _selected[]; + + /** The hashtable of available component ids for each class. */ + protected HashIntMap _components = new HashIntMap(); + + /** The list of all available component classes. */ + protected ArrayList _classes = new ArrayList(); + + /** The model listeners. */ + protected ArrayList _listeners = new ArrayList(); +} diff --git a/src/java/com/threerings/cast/builder/BuilderModelListener.java b/src/java/com/threerings/cast/builder/BuilderModelListener.java new file mode 100644 index 000000000..7d6fcfa68 --- /dev/null +++ b/src/java/com/threerings/cast/builder/BuilderModelListener.java @@ -0,0 +1,22 @@ +// +// $Id: BuilderModelListener.java,v 1.1 2001/11/02 01:10:28 shaper Exp $ + +package com.threerings.cast.builder; + +/** + * The builder model listener interface should be implemented by + * classes that would like to be notified when the builder model is + * changed. + * + * @see BuilderModel + */ +public interface BuilderModelListener +{ + /** + * Called by the {@link BuilderModel} when the model is changed. + */ + public void modelChanged (int event); + + /** Notification event constants. */ + public static final int COMPONENT_CHANGED = 0; +} diff --git a/src/java/com/threerings/cast/builder/BuilderPanel.java b/src/java/com/threerings/cast/builder/BuilderPanel.java index 727c26a3c..4ceb8ba82 100644 --- a/src/java/com/threerings/cast/builder/BuilderPanel.java +++ b/src/java/com/threerings/cast/builder/BuilderPanel.java @@ -1,5 +1,5 @@ // -// $Id: BuilderPanel.java,v 1.2 2001/11/01 01:40:42 shaper Exp $ +// $Id: BuilderPanel.java,v 1.3 2001/11/02 01:10:28 shaper Exp $ package com.threerings.cast.builder; @@ -10,6 +10,7 @@ import java.util.Iterator; import javax.swing.*; import com.samskivert.swing.*; +import com.samskivert.util.StringUtil; import com.threerings.cast.*; @@ -18,15 +19,13 @@ import com.threerings.cast.*; * composited character and facilities for altering the individual * components that comprise the character's display image. */ -public class BuilderPanel extends JPanel implements ActionListener +public class BuilderPanel extends JPanel { /** * Constructs the builder panel. */ public BuilderPanel (CharacterManager charmgr) { - _charmgr = charmgr; - setLayout(new VGroupLayout()); // give ourselves a wee bit of a border @@ -35,39 +34,13 @@ public class BuilderPanel extends JPanel implements ActionListener GroupLayout gl = new HGroupLayout(GroupLayout.STRETCH); gl.setOffAxisPolicy(GroupLayout.STRETCH); + // create the builder model + BuilderModel model = new BuilderModel(charmgr); + // create the component selection and sprite display panels JPanel sub = new JPanel(gl); - sub.add(_comppanel = new ComponentPanel(_charmgr)); - sub.add(_spritepanel = new SpritePanel()); - + sub.add(new ComponentPanel(model)); + sub.add(new SpritePanel(charmgr, model)); 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 + "]."); - } - } - - /** 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/ClassEditor.java b/src/java/com/threerings/cast/builder/ClassEditor.java new file mode 100644 index 000000000..fb6b9e1e0 --- /dev/null +++ b/src/java/com/threerings/cast/builder/ClassEditor.java @@ -0,0 +1,93 @@ +// +// $Id: ClassEditor.java,v 1.1 2001/11/02 01:10:28 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 class editor displays a label and a slider that allow the user + * to select the desired component for a given component class. + */ +public class ClassEditor extends JPanel implements ChangeListener +{ + /** + * Constructs a class editor. + */ + public ClassEditor (BuilderModel model, ComponentClass cclass, + List components) + { + _model = model; + _components = components; + _clid = cclass.clid; + + 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); + + // create the slider allowing selection of available components + int max = components.size() - 1; + JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, max, 0); + slider.setSnapToTicks(true); + slider.addChangeListener(this); + add(slider); + + // set the starting component for this class + setSelectedComponent(0); + } + + // documentation inherited + public void stateChanged (ChangeEvent e) + { + JSlider source = (JSlider)e.getSource(); + if (!source.getValueIsAdjusting()) { + int val = source.getValue(); + // update the model with the newly selected component + setSelectedComponent(val); + // update the label with the new value + _clabel.setText(Integer.toString(val)); + } + } + + /** + * Sets the selected component in the builder model for the + * component class associated with this editor to the component at + * the given index in this editor's list of available components. + */ + protected void setSelectedComponent (int idx) + { + int cid = ((Integer)_components.get(idx)).intValue(); + _model.setSelectedComponent(_clid, cid); + } + + /** The component class id associated with this editor. */ + protected int _clid; + + /** The components selectable via this editor. */ + protected List _components; + + /** The label denoting the currently selected component index. */ + protected JLabel _clabel; + + /** The builder model. */ + protected BuilderModel _model; +} diff --git a/src/java/com/threerings/cast/builder/ComponentEditor.java b/src/java/com/threerings/cast/builder/ComponentEditor.java deleted file mode 100644 index e470373e9..000000000 --- a/src/java/com/threerings/cast/builder/ComponentEditor.java +++ /dev/null @@ -1,82 +0,0 @@ -// -// $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 index 60d2c0c1f..e2283d67d 100644 --- a/src/java/com/threerings/cast/builder/ComponentPanel.java +++ b/src/java/com/threerings/cast/builder/ComponentPanel.java @@ -1,119 +1,52 @@ // -// $Id: ComponentPanel.java,v 1.2 2001/11/01 01:40:42 shaper Exp $ +// $Id: ComponentPanel.java,v 1.3 2001/11/02 01:10:28 shaper Exp $ package com.threerings.cast.builder; -import java.util.*; +import java.util.List; import javax.swing.*; import javax.swing.border.Border; import com.samskivert.swing.*; -import com.samskivert.util.*; +import com.samskivert.util.HashIntMap; 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. + * The component panel displays the available components for all + * component classes and allows the user to choose a set of components + * for compositing into a character image. */ public class ComponentPanel extends JPanel { /** * Constructs the component panel. */ - public ComponentPanel (CharacterManager charmgr) + public ComponentPanel (BuilderModel model) { - // retrieve component classes and relevant components - gatherComponentInfo(charmgr); - - GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH); - gl.setOffAxisPolicy(GroupLayout.STRETCH); - setLayout(gl); - + setLayout(new VGroupLayout(GroupLayout.STRETCH)); // 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(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 clid = ((ComponentClass)_classes.get(ii)).clid; - Iterator comps = charmgr.enumerateComponentsByClass(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); - } - } + addClassEditors(model); } /** * Adds editor user interface elements for each component class to * allow the user to select the desired component. */ - protected void addComponentEditors () + protected void addClassEditors (BuilderModel model) { - int size = _classes.size(); + List classes = model.getComponentClasses(); + HashIntMap components = model.getComponents(); + + 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); + ComponentClass cclass = (ComponentClass)classes.get(ii); + List ccomps = (List)components.get(cclass.clid); + add(new ClassEditor(model, cclass, ccomps)); } } - - /** 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 index 451e0bbd0..18bba8996 100644 --- a/src/java/com/threerings/cast/builder/SpritePanel.java +++ b/src/java/com/threerings/cast/builder/SpritePanel.java @@ -1,5 +1,5 @@ // -// $Id: SpritePanel.java,v 1.1 2001/10/30 16:16:01 shaper Exp $ +// $Id: SpritePanel.java,v 1.2 2001/11/02 01:10:28 shaper Exp $ package com.threerings.cast.builder; @@ -10,36 +10,35 @@ import javax.swing.border.BevelBorder; import com.threerings.media.sprite.*; import com.threerings.cast.Log; -import com.threerings.cast.CharacterSprite; +import com.threerings.cast.*; /** * The sprite panel displays a character sprite centered in the panel * suitable for user perusal. */ -public class SpritePanel extends AnimatedPanel +public class SpritePanel + extends AnimatedPanel + implements BuilderModelListener { /** * Constructs the sprite panel. */ - public SpritePanel () + public SpritePanel (CharacterManager charmgr, BuilderModel model) { - // create and save off references to our managers + // save off references + _charmgr = charmgr; + _model = model; + + // create 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(); + // listen to the builder model so that we can update the + // sprite when a new component is selected + _model.addListener(this); } // documentation inherited @@ -52,6 +51,11 @@ public class SpritePanel extends AnimatedPanel Dimension d = getSize(); gfx.fillRect(0, 0, d.width - 1, d.height - 1); + if (_sprite == null) { + // create the sprite if it's not yet extant + generateSprite(); + } + if (_sprite != null) { // render the sprite _sprite.paint((Graphics2D)g); @@ -65,6 +69,37 @@ public class SpritePanel extends AnimatedPanel centerSprite(); } + // documentation inherited + public void modelChanged (int event) + { + if (event == COMPONENT_CHANGED) { + generateSprite(); + } + } + + /** + * Generates a new character sprite for display to reflect the + * currently selected character components. + */ + protected void generateSprite () + { + int components[] = _model.getSelectedComponents(); + CharacterDescriptor desc = new CharacterDescriptor(components); + CharacterSprite sprite = _charmgr.getCharacter(desc); + setSprite(sprite); + } + + /** + * Sets the sprite to be displayed. + */ + protected void setSprite (CharacterSprite sprite) + { + _sprite = sprite; + _sprite.setOrientation(Sprite.DIR_SOUTHWEST); + centerSprite(); + repaint(); + } + /** * Sets the sprite's location to render it centered within the panel. */ @@ -86,4 +121,10 @@ public class SpritePanel extends AnimatedPanel /** The sprite manager. */ protected SpriteManager _spritemgr; + + /** The character manager. */ + protected CharacterManager _charmgr; + + /** The builder model. */ + protected BuilderModel _model; }