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
This commit is contained in:
Walter Korman
2001-11-02 01:10:28 +00:00
parent 182306a5e4
commit 662b60e53e
8 changed files with 322 additions and 219 deletions
@@ -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());
}
@@ -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();
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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();
}
@@ -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;
}