We need to sort card sprites using a comparator if we want to sort them not

based on render order as we use render order. Also some widening.


git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@301 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
Michael Bayne
2007-05-15 18:03:54 +00:00
parent 84080ecb61
commit c4fbf34f44
2 changed files with 282 additions and 308 deletions
@@ -28,6 +28,7 @@ import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import javax.swing.event.MouseInputAdapter;
@@ -53,8 +54,8 @@ import com.threerings.parlor.card.data.Deck;
import com.threerings.parlor.card.data.Hand;
/**
* Extends VirtualMediaPanel to provide services specific to rendering
* and manipulating playing cards.
* Extends VirtualMediaPanel to provide services specific to rendering and manipulating playing
* cards.
*/
public abstract class CardPanel extends VirtualMediaPanel
implements CardCodes
@@ -120,8 +121,7 @@ public abstract class CardPanel extends VirtualMediaPanel
public abstract Mirage getMicroCardImage (Card card);
/**
* Sets the location of the hand (the location of the center of the hand's
* upper edge).
* Sets the location of the hand (the location of the center of the hand's upper edge).
*/
public void setHandLocation (int x, int y)
{
@@ -137,8 +137,7 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Sets the vertical distance to offset cards that are selectable or
* playable.
* Sets the vertical distance to offset cards that are selectable or playable.
*/
public void setSelectableCardOffset (int offset)
{
@@ -154,9 +153,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Sets the selection mode for the hand (NONE, PLAY_SINGLE, SINGLE,
* or MULTIPLE). Changing the selection mode does not change the
* current selection.
* Sets the selection mode for the hand (NONE, PLAY_SINGLE, SINGLE, or MULTIPLE). Changing the
* selection mode does not change the current selection.
*/
public void setHandSelectionMode (int mode)
{
@@ -167,9 +165,9 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Sets the selection predicate that determines which cards from the hand
* may be selected (if null, all cards may be selected). Changing the
* predicate does not change the current selection.
* Sets the selection predicate that determines which cards from the hand may be selected (if
* null, all cards may be selected). Changing the predicate does not change the current
* selection.
*/
public void setHandSelectionPredicate (Predicate<CardSprite> pred)
{
@@ -180,8 +178,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Returns the currently selected hand sprite (null if no sprites are
* selected, the first sprite if multiple sprites are selected).
* Returns the currently selected hand sprite (null if no sprites are selected, the first
* sprite if multiple sprites are selected).
*/
public CardSprite getSelectedHandSprite ()
{
@@ -190,8 +188,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Returns an array containing the currently selected hand sprites
* (returns an empty array if no sprites are selected).
* Returns an array containing the currently selected hand sprites (returns an empty array if
* no sprites are selected).
*/
public CardSprite[] getSelectedHandSprites ()
{
@@ -209,8 +207,7 @@ public abstract class CardPanel extends VirtualMediaPanel
return;
}
// if in single card mode and there's another card selected,
// deselect it
// if in single card mode and there's another card selected, deselect it
if (_handSelectionMode == SINGLE) {
CardSprite oldSprite = getSelectedHandSprite();
if (oldSprite != null) {
@@ -270,8 +267,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Adds an object to the list of observers to notify when cards in the
* hand are selected/deselected.
* Adds an object to the list of observers to notify when cards in the hand are
* selected/deselected.
*/
public void addHandSelectionObserver (CardSelectionObserver obs)
{
@@ -290,8 +287,7 @@ public abstract class CardPanel extends VirtualMediaPanel
* Fades a hand of cards in.
*
* @param hand the hand of cards
* @param fadeDuration the amount of time to spend fading in
* the entire hand
* @param fadeDuration the amount of time to spend fading in the entire hand
*/
public void setHand (Hand hand, long fadeDuration)
{
@@ -307,7 +303,7 @@ public abstract class CardPanel extends VirtualMediaPanel
// sort them
if (shouldSortHand()) {
QuickSort.sort(_handSprites);
QuickSort.sort(_handSprites, CARD_COMP);
}
// fade them in at proper locations and layers
@@ -329,8 +325,7 @@ public abstract class CardPanel extends VirtualMediaPanel
* Fades a hand of cards in face-down.
*
* @param size the size of the hand
* @param fadeDuration the amount of time to spend fading in
* each card
* @param fadeDuration the amount of time to spend fading in each card
*/
public void setHand (int size, long fadeDuration)
{
@@ -363,8 +358,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Returns the first sprite in the hand that corresponds to the
* specified card, or null if the card is not in the hand.
* Returns the first sprite in the hand that corresponds to the specified card, or null if the
* card is not in the hand.
*/
public CardSprite getHandSprite (Card card)
{
@@ -389,20 +384,18 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Flies a set of cards from the hand into the ether. Clears any selected
* cards.
* Flies a set of cards from the hand into the ether. Clears any selected cards.
*
* @param cards the card sprites to remove from the hand
* @param dest the point to fly the cards to
* @param flightDuration the duration of the cards' flight
* @param fadePortion the amount of time to spend fading out
* as a proportion of the flight duration
* @param fadePortion the amount of time to spend fading out as a proportion of the flight
* duration
*/
public void flyFromHand (CardSprite[] cards, Point dest,
long flightDuration, float fadePortion)
public void flyFromHand (CardSprite[] cards, Point dest, long flightDuration, float fadePortion)
{
// fly each sprite over, removing it from the hand immediately and
// from the board when it finishes its path
// fly each sprite over, removing it from the hand immediately and from the board when it
// finishes its path
for (int i = 0; i < cards.length; i++) {
removeFromHand(cards[i]);
LinePath flight = new LinePath(dest, flightDuration);
@@ -415,22 +408,20 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Flies a set of cards from the ether into the hand. Clears any selected
* cards. The cards will first fly to the selected card offset, pause for
* the specified duration, and then drop into the hand.
* Flies a set of cards from the ether into the hand. Clears any selected cards. The cards
* will first fly to the selected card offset, pause for the specified duration, and then drop
* into the hand.
*
* @param cards the cards to add to the hand
* @param src the point to fly the cards from
* @param flightDuration the duration of the cards' flight
* @param pauseDuration the duration of the pause before dropping into the
* hand
* @param dropDuration the duration of the cards' drop into the
* hand
* @param fadePortion the amount of time to spend fading in
* as a proportion of the flight duration
* @param pauseDuration the duration of the pause before dropping into the hand
* @param dropDuration the duration of the cards' drop into the hand
* @param fadePortion the amount of time to spend fading in as a proportion of the flight
* duration
*/
public void flyIntoHand (Card[] cards, Point src, long flightDuration,
long pauseDuration, long dropDuration, float fadePortion)
public void flyIntoHand (Card[] cards, Point src, long flightDuration, long pauseDuration,
long dropDuration, float fadePortion)
{
// first create the sprites and add them to the list
CardSprite[] sprites = new CardSprite[cards.length];
@@ -471,11 +462,11 @@ public abstract class CardPanel extends VirtualMediaPanel
* @param dest the point to fly the cards to
* @param flightDuration the duration of the cards' flight
* @param cardDelay the amount of time to wait between cards
* @param fadePortion the amount of time to spend fading in and out
* as a proportion of the flight duration
* @param fadePortion the amount of time to spend fading in and out as a proportion of the
* flight duration
*/
public void flyAcross (Card[] cards, Point src, Point dest,
long flightDuration, long cardDelay, float fadePortion)
public void flyAcross (Card[] cards, Point src, Point dest, long flightDuration,
long cardDelay, float fadePortion)
{
for (int i = 0; i < cards.length; i++) {
// add on top of all board sprites
@@ -511,11 +502,11 @@ public abstract class CardPanel extends VirtualMediaPanel
* @param dest the point to fly the cards to
* @param flightDuration the duration of the cards' flight
* @param cardDelay the amount of time to wait between cards
* @param fadePortion the amount of time to spend fading in and out
* as a proportion of the flight duration
* @param fadePortion the amount of time to spend fading in and out as a proportion of the
* flight duration
*/
public void flyAcross (int number, Point src, Point dest,
long flightDuration, long cardDelay, float fadePortion)
public void flyAcross (int number, Point src, Point dest, long flightDuration,
long cardDelay, float fadePortion)
{
// use null values to signify unknown cards
flyAcross(new Card[number], src, dest, flightDuration,
@@ -529,8 +520,7 @@ public abstract class CardPanel extends VirtualMediaPanel
* @param dest the point to fly the card to
* @param flightDuration the duration of the card's flight
*/
public void flyFromHandToBoard (CardSprite card, Point dest,
long flightDuration)
public void flyFromHandToBoard (CardSprite card, Point dest, long flightDuration)
{
// fly it over
LinePath flight = new LinePath(dest, flightDuration);
@@ -554,11 +544,11 @@ public abstract class CardPanel extends VirtualMediaPanel
* @param src the point to fly the card from
* @param dest the point to fly the card to
* @param flightDuration the duration of the card's flight
* @param fadePortion the amount of time to spend fading in as a
* proportion of the flight duration
* @param fadePortion the amount of time to spend fading in as a proportion of the flight
* duration
*/
public void flyToBoard (Card card, Point src, Point dest,
long flightDuration, float fadePortion)
public void flyToBoard (Card card, Point src, Point dest, long flightDuration,
float fadePortion)
{
// add it on top of the existing cards
CardSprite cs = new CardSprite(this, card);
@@ -593,11 +583,11 @@ public abstract class CardPanel extends VirtualMediaPanel
* @param cards the cards to remove from the board
* @param dest the point to fly the cards to
* @param flightDuration the duration of the cards' flight
* @param fadePortion the amount of time to spend fading out as a
* proportion of the flight duration
* @param fadePortion the amount of time to spend fading out as a proportion of the flight
* duration
*/
public void flyFromBoard (CardSprite[] cards, Point dest,
long flightDuration, float fadePortion)
public void flyFromBoard (CardSprite[] cards, Point dest, long flightDuration,
float fadePortion)
{
for (int i = 0; i < cards.length; i++) {
LinePath flight = new LinePath(dest, flightDuration);
@@ -607,27 +597,18 @@ public abstract class CardPanel extends VirtualMediaPanel
}
}
// documentation inherited
protected void paintBehind (Graphics2D gfx, Rectangle dirtyRect)
{
gfx.setColor(DEFAULT_BACKGROUND);
gfx.fill(dirtyRect);
super.paintBehind(gfx, dirtyRect);
}
/**
* Flies a set of cards from the board into the ether through an
* intermediate point.
* Flies a set of cards from the board into the ether through an intermediate point.
*
* @param cards the cards to remove from the board
* @param dest1 the first point to fly the cards to
* @param dest2 the final destination of the cards
* @param flightDuration the duration of the cards' flight
* @param fadePortion the amount of time to spend fading out as a
* proportion of the flight duration
* @param fadePortion the amount of time to spend fading out as a proportion of the flight
* duration
*/
public void flyFromBoard (CardSprite[] cards, Point dest1, Point dest2,
long flightDuration, float fadePortion)
public void flyFromBoard (CardSprite[] cards, Point dest1, Point dest2, long flightDuration,
float fadePortion)
{
for (int i = 0; i < cards.length; i++) {
PathSequence flight = new PathSequence(
@@ -640,8 +621,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Returns the first card sprite in the specified list that represents
* the specified card, or null if there is no such sprite in the list.
* Returns the first card sprite in the specified list that represents the specified card, or
* null if there is no such sprite in the list.
*/
protected CardSprite getCardSprite (ArrayList list, Card card)
{
@@ -655,8 +636,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Returns whether the user's hand should be sorted when displayed. By
* default, hands are sorted.
* Returns whether the user's hand should be sorted when displayed. By default, hands are
* sorted.
*/
protected boolean shouldSortHand ()
{
@@ -664,12 +645,11 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Expands or collapses the hand to accommodate new cards or cover the
* space left by removed cards. Skips unmanaged sprites. Clears out
* any selected cards.
* Expands or collapses the hand to accommodate new cards or cover the space left by removed
* cards. Skips unmanaged sprites. Clears out any selected cards.
*
* @param adjustDuration the amount of time to spend settling the cards
* into their new locations
* @param adjustDuration the amount of time to spend settling the cards into their new
* locations
* @param updateLayers whether or not to update the layers of the cards
*/
protected void adjustHand (long adjustDuration, boolean updateLayers)
@@ -679,7 +659,7 @@ public abstract class CardPanel extends VirtualMediaPanel
// Sort the hand
if (shouldSortHand()) {
QuickSort.sort(_handSprites);
QuickSort.sort(_handSprites, CARD_COMP);
}
// Move each card to its proper position (and, optionally, layer)
@@ -692,8 +672,8 @@ public abstract class CardPanel extends VirtualMediaPanel
if (updateLayers) {
cs.setRenderOrder(i);
}
LinePath adjust = new LinePath(new Point(getHandX(size, i),
_handLocation.y), adjustDuration);
LinePath adjust = new LinePath(
new Point(getHandX(size, i), _handLocation.y), adjustDuration);
cs.move(adjust);
}
}
@@ -708,8 +688,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Updates the offsets of all the cards in the hand. If there is only
* one selectable card, that card will always be raised slightly.
* Updates the offsets of all the cards in the hand. If there is only one selectable card,
* that card will always be raised slightly.
*/
protected void updateHandOffsets ()
{
@@ -726,8 +706,8 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Given the location and spacing of the hand, returns the x location of
* the card at the specified index within a hand of the specified size.
* Given the location and spacing of the hand, returns the x location of the card at the
* specified index within a hand of the specified size.
*/
protected int getHandX (int size, int idx)
{
@@ -735,15 +715,14 @@ public abstract class CardPanel extends VirtualMediaPanel
if (_cardWidth == 0) {
_cardWidth = getCardBackImage().getWidth();
}
// first compute the width of the entire hand, then use that to
// determine the centered location
// first compute the width of the entire hand, then use that to determine the centered
// location
int width = (size - 1) * _handSpacing + _cardWidth;
return (_handLocation.x - width/2) + idx * _handSpacing;
}
/**
* Determines the y location of the specified card sprite, given its
* selection state.
* Determines the y location of the specified card sprite, given its selection state.
*/
protected int getHandY (CardSprite sprite)
{
@@ -760,19 +739,18 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Given the current selection mode and predicate, determines if the
* specified sprite is selectable.
* Given the current selection mode and predicate, determines if the specified sprite is
* selectable.
*/
protected boolean isSelectable (CardSprite sprite)
{
return _handSelectionMode != NONE &&
(_handSelectionPredicate == null ||
_handSelectionPredicate.isMatch(sprite));
(_handSelectionPredicate == null || _handSelectionPredicate.isMatch(sprite));
}
/**
* Determines whether the specified sprite is the only selectable sprite
* in the hand according to the selection predicate.
* Determines whether the specified sprite is the only selectable sprite in the hand according
* to the selection predicate.
*/
protected boolean isOnlySelectable (CardSprite sprite)
{
@@ -781,8 +759,7 @@ public abstract class CardPanel extends VirtualMediaPanel
return _handSprites.size() == 1 && _handSprites.contains(sprite);
}
// otherwise, look for a sprite that fits the predicate and isn't the
// parameter
// otherwise, look for a sprite that fits the predicate and isn't the parameter
for (CardSprite cs : _handSprites) {
if (cs != sprite && _handSelectionPredicate.isMatch(cs)) {
return false;
@@ -792,8 +769,7 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Lowers all board sprites so that they are rendered at or below the
* specified layer.
* Lowers all board sprites so that they are rendered at or below the specified layer.
*/
protected void lowerBoardSprites (int layer)
{
@@ -816,8 +792,8 @@ public abstract class CardPanel extends VirtualMediaPanel
*/
protected int getHighestBoardLayer ()
{
// must be at least zero, because that's the lowest number we can push
// the sprites down to (the layer of the first card in the hand)
// must be at least zero, because that's the lowest number we can push the sprites down to
// (the layer of the first card in the hand)
int size = _boardSprites.size(), highest = 0;
for (int i = 0; i < size; i++) {
highest = Math.max(highest, _boardSprites.get(i).getRenderOrder());
@@ -837,8 +813,7 @@ public abstract class CardPanel extends VirtualMediaPanel
}
/**
* Updates the active card sprite based on the location of the mouse
* pointer.
* Updates the active card sprite based on the location of the mouse pointer.
*/
protected void updateActiveCardSprite ()
{
@@ -851,80 +826,28 @@ public abstract class CardPanel extends VirtualMediaPanel
_mouseEvent.getX(), _mouseEvent.getY());
CardSprite newActiveCardSprite =
(newHighestHit instanceof CardSprite ?
(CardSprite)newHighestHit : null);
(newHighestHit instanceof CardSprite ? (CardSprite)newHighestHit : null);
if (_activeCardSprite != newActiveCardSprite) {
if (_activeCardSprite != null &&
isManaged(_activeCardSprite)) {
if (_activeCardSprite != null && isManaged(_activeCardSprite)) {
_activeCardSprite.queueNotification(
new CardSpriteExitedOp(_activeCardSprite,
_mouseEvent)
);
new CardSpriteExitedOp(_activeCardSprite, _mouseEvent));
}
_activeCardSprite = newActiveCardSprite;
if (_activeCardSprite != null) {
_activeCardSprite.queueNotification(
new CardSpriteEnteredOp(_activeCardSprite,
_mouseEvent)
);
new CardSpriteEnteredOp(_activeCardSprite, _mouseEvent));
}
}
}
/** The width of the playing cards. */
protected int _cardWidth;
/** The last motion/entrance/exit event received from the mouse. */
protected MouseEvent _mouseEvent;
/** The currently active card sprite (the one that the mouse is over). */
protected CardSprite _activeCardSprite;
/** The sprites for cards within the hand. */
protected ArrayList<CardSprite> _handSprites = new ArrayList<CardSprite>();
/** The sprites for cards within the hand that have been selected. */
protected ArrayList<CardSprite> _selectedHandSprites =
new ArrayList<CardSprite>();
/** The current selection mode for the hand. */
protected int _handSelectionMode;
/** The predicate that determines which cards are selectable (if null, all
* cards are selectable). */
protected Predicate<CardSprite> _handSelectionPredicate;
/** Observers of hand card selection/deselection. */
protected ObserverList<CardSelectionObserver> _handSelectionObservers =
new ObserverList<CardSelectionObserver>(
ObserverList.FAST_UNSAFE_NOTIFY);
/** The location of the center of the hand's upper edge. */
protected Point _handLocation = new Point();
/** The horizontal distance between cards in the hand. */
protected int _handSpacing;
/** The vertical distance to offset cards that are selectable. */
protected int _selectableCardOffset;
/** The vertical distance to offset cards that are selected. */
protected int _selectedCardOffset;
/** The sprites for cards on the board. */
protected ArrayList<CardSprite> _boardSprites = new ArrayList<CardSprite>();
/** The hand sprite observer instance. */
protected HandSpriteObserver _handSpriteObserver =
new HandSpriteObserver();
/** A path observer that removes the sprite at the end of its path. */
protected PathAdapter _pathEndRemover = new PathAdapter() {
public void pathCompleted (Sprite sprite, Path path, long when) {
removeSprite(sprite);
// documentation inherited
protected void paintBehind (Graphics2D gfx, Rectangle dirtyRect)
{
gfx.setColor(DEFAULT_BACKGROUND);
gfx.fill(dirtyRect);
super.paintBehind(gfx, dirtyRect);
}
};
/** Listens for interactions with cards in hand. */
protected class HandSpriteObserver extends PathAdapter
@@ -1134,6 +1057,70 @@ public abstract class CardPanel extends VirtualMediaPanel
protected MouseEvent _me;
}
/** A nice default green card table background color. */
protected static Color DEFAULT_BACKGROUND = new Color(0x326D36);
/** The width of the playing cards. */
protected int _cardWidth;
/** The last motion/entrance/exit event received from the mouse. */
protected MouseEvent _mouseEvent;
/** The currently active card sprite (the one that the mouse is over). */
protected CardSprite _activeCardSprite;
/** The sprites for cards within the hand. */
protected ArrayList<CardSprite> _handSprites = new ArrayList<CardSprite>();
/** The sprites for cards within the hand that have been selected. */
protected ArrayList<CardSprite> _selectedHandSprites =
new ArrayList<CardSprite>();
/** The current selection mode for the hand. */
protected int _handSelectionMode;
/** The predicate that determines which cards are selectable (if null, all
* cards are selectable). */
protected Predicate<CardSprite> _handSelectionPredicate;
/** Observers of hand card selection/deselection. */
protected ObserverList<CardSelectionObserver> _handSelectionObservers =
new ObserverList<CardSelectionObserver>(
ObserverList.FAST_UNSAFE_NOTIFY);
/** The location of the center of the hand's upper edge. */
protected Point _handLocation = new Point();
/** The horizontal distance between cards in the hand. */
protected int _handSpacing;
/** The vertical distance to offset cards that are selectable. */
protected int _selectableCardOffset;
/** The vertical distance to offset cards that are selected. */
protected int _selectedCardOffset;
/** The sprites for cards on the board. */
protected ArrayList<CardSprite> _boardSprites = new ArrayList<CardSprite>();
/** The hand sprite observer instance. */
protected HandSpriteObserver _handSpriteObserver = new HandSpriteObserver();
/** A path observer that removes the sprite at the end of its path. */
protected PathAdapter _pathEndRemover = new PathAdapter() {
public void pathCompleted (Sprite sprite, Path path, long when) {
removeSprite(sprite);
}
};
/** Compares two card sprites based on their underlying card. */
protected static final Comparator<CardSprite> CARD_COMP = new Comparator<CardSprite>() {
public int compare (CardSprite cs1, CardSprite cs2) {
if (cs1._card == null || cs2._card == null) {
return 0;
} else {
return cs1._card.compareTo(cs2._card);
}
}
};
/** A nice default green card table background color. */
protected static final Color DEFAULT_BACKGROUND = new Color(0x326D36);
}
@@ -203,19 +203,6 @@ public class CardSprite extends FadableImageSprite
gfx.setTransform(otrans);
}
/**
* Compares this to another card sprite based on their cards.
*/
protected int naturalCompareTo (AbstractMedia other)
{
CardSprite cs = (CardSprite)other;
if (_card == null || cs._card == null) {
return 0;
} else {
return _card.compareTo(cs._card);
}
}
/**
* Updates the mirage according to the current state.
*/