/SurfaceAcademy2009Toolkit/SurfaceCardsGameKit/Dispositions/FanDisposition.cs
C# | 399 lines | 297 code | 86 blank | 16 comment | 35 complexity | c63ad8aacd34b87cb32cdaa550c4d8fa MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using SurfaceCardsBoardLibrary.Interfaces;
- using System.Windows;
- using SurfaceCardsGameKit.Tools;
- using Microsoft.Surface.Presentation.Controls;
- using System.Windows.Media.Animation;
- using System.Windows.Media;
- using SurfaceCardsBoardLibrary;
-
- namespace SurfaceCardsGameKit.Dispositions
- {
- class FanDisposition : IDisposition
- {
- private List<DispositionOffset> _offsets;
-
- #region IDisposition Members
-
- public void Render(IDeck deck, Size cardSize, Rect destinationRect, Point center,
- double deckOrientation, bool useTransitions, bool sizeChanged, DeckOrientation deckupDownOrientation, double durationRatio)
- {
-
- if (!sizeChanged && _offsets != null)
- {
- int i = 0;
- foreach (var card in deck)
- {
- if (card.ScatterViewItem.Visibility == Visibility.Collapsed)
- continue;
-
- ActuallyMoveChilds(useTransitions, deck, card, _offsets[i], durationRatio);
- i++;
- }
- }
- else
- {
- // put in line
- if (cardSize.Width * deck.Count <= destinationRect.Width)
- {
- MoveChilds(deck, cardSize, destinationRect, 1, double.NaN, true, deckupDownOrientation, durationRatio);
- return;
- }
-
- var ratio = cardSize.Width / (destinationRect.Width * deck.Count);
-
- double angleDegree = ratio * 50;
- double radius = Math.Pow(destinationRect.Width, 3) * deck.Count / Math.Pow(cardSize.Width, 3);
-
- MoveChilds(deck, cardSize, destinationRect, angleDegree, radius, useTransitions, deckupDownOrientation, durationRatio);
- }
-
- }
-
- void MoveChilds(IDeck deck, Size cardSize, Rect destinationRect, double angleDegree, double circleRadius, bool useTransitions,
- DeckOrientation deckupDownOrientation, double durationRatio)
- {
- _offsets = new List<DispositionOffset>();
-
- bool isEven = deck.Count % 2 == 0;
- double i;
-
- if (isEven)
- i = (deck.Count - 1) / -2.0;
- else
- i = -Math.Floor(deck.Count / 2.0);
-
- DispositionOffset[] offsets = new DispositionOffset[deck.Count];
-
- // first pass : calculate positions
- var j = 0;
- foreach (var card in deck)
- {
- var svi = card.ScatterViewItem;
-
- Point offsetPoint = new Point(0, 0);
- if (card.IsSelected)
- {
- switch (deckupDownOrientation)
- {
- case DeckOrientation.Up:
- offsetPoint.Y = -20;
- break;
- case DeckOrientation.Down:
- offsetPoint.Y = 20;
- break;
- }
- }
-
- offsets[j] = CalcOffset(angleDegree * i, circleRadius, cardSize, destinationRect, offsetPoint, deckupDownOrientation);
- i++;
- j++;
- }
-
- double offsetX = offsets.Max(o => o.Max.X) - offsets.Min(o => o.Min.X);
- //offsetX = (offsets[offsets.Length - 1].Center.X + cardSize.Width) - (offsets[0].Center.X - cardSize.Width / 2);
- double offsetY = offsets.Max(o => o.Max.Y) - offsets.Min(o => o.Min.Y);
-
- // ratio can be equal to 0 when cards are in line
- double ratioX = offsetX == 0 ? 1 : (destinationRect.Width / offsetX);
- double ratioY = offsetY == 0 ? 1 : (destinationRect.Height / offsetY);
-
- var middle = new Point(destinationRect.X + destinationRect.Width / 2, destinationRect.Y + destinationRect.Height / 2);
-
- j = 0;
- foreach (var card in deck)
- {
- if (card.ScatterViewItem.Visibility == Visibility.Collapsed)
- continue;
-
- var svi = card.ScatterViewItem;
- var offset = offsets[j];
-
- offset.Center = new Point(
- middle.X + offset.Center.X * ratioX,
- middle.Y + offset.Center.Y * ratioY
- );
-
- _offsets.Add(offset);
-
- ActuallyMoveChilds(useTransitions, deck, card, offset, durationRatio);
-
- j++;
- }
- }
-
- private static void ActuallyMoveChilds(bool useTransitions, IDeck deck, ICard card, DispositionOffset offset, double durationRatio)
- {
-
- // translate Center to Deck position
- var center = deck.ScatterViewItem.TranslatePoint(offset.Center, deck.ScatterView);
-
- // calc real orientation
- var orientation = DispositionHelper.CalcOrientationForCards(
- card.ScatterViewItem.ActualOrientation, offset.Orientation + deck.ScatterViewItem.ActualOrientation);
-
- var svi = card.ScatterViewItem;
-
- bool centerChanged = svi.Center != offset.Center;
- bool orientationChanged = svi.Orientation != offset.Orientation;
-
- if (useTransitions)
- {
- var duration = DispositionHelper.ComputeAnimationDuration(svi.ActualCenter, center, svi.ActualOrientation, orientation, durationRatio);
-
- // center animation
- if (centerChanged)
- DispositionHelper.BeginCenterAnimation(svi, center, duration);
-
- // orientation animation
- if (orientationChanged)
- DispositionHelper.BeginOrientationAnimation(svi, orientation, duration);
- }
- else
- {
- if (centerChanged)
- card.Center = center;
- if (orientationChanged)
- card.Orientation = orientation;
- }
- }
-
- public bool CanApplyDisposition(Size cardSize, Rect destinationRect, int cardsCount)
- {
- return true;
- //return destinationRect.Width > cardsCount * (cardSize.Width / 4);
- }
-
- private DispositionOffset CalcOffset(double angleDegree, double circleRadius, Size cardSize, Rect destinationRect, Point offsetPoint, DeckOrientation deckupDownOrientation)
- {
- DispositionOffset off = new DispositionOffset();
-
- if (double.IsNaN(circleRadius))
- {
- // put in line
- off.Center =
- new Point(
- cardSize.Width * angleDegree,
- 0);
- }
- else
- {
- var middle = new Point(destinationRect.Width / 2.0, destinationRect.Height / 2.0);
-
- Matrix m = new Matrix()
- {
- OffsetX = offsetPoint.X,
- OffsetY = offsetPoint.Y,
- };
-
- var midCardWidth = cardSize.Width / 2.0;
- var midCardHeight = cardSize.Height / 2.0;
-
- Point[] points = new Point[4];
-
- Point p1, p2, p3, p4;
-
- TranslateRotateCopyMatrix(-midCardWidth, -midCardHeight, angleDegree, 0.0, circleRadius, out p1);
-
- // top right
- TranslateRotateCopyMatrix(midCardWidth, -midCardHeight, angleDegree, 0.0, circleRadius, out p2);
-
- // bottom right
- TranslateRotateCopyMatrix(midCardWidth, midCardHeight, angleDegree, 0.0, circleRadius, out p3);
-
- // bottom left
- TranslateRotateCopyMatrix(-midCardWidth, midCardHeight, angleDegree, 0.0, circleRadius, out p4);
-
- points[0] = p1;
- points[1] = p2;
- points[2] = p3;
- points[3] = p4;
-
- off.Min = new Point(points.Min(p => p.X), points.Min(p => p.Y));
- off.Max = new Point(points.Max(p => p.X), points.Max(p => p.Y));
-
- switch (deckupDownOrientation)
- {
- case DeckOrientation.Up:
- m.RotateAt(angleDegree, 0, circleRadius);
- break;
- case DeckOrientation.Down:
- m.RotateAt(-angleDegree, 0, -circleRadius);
- break;
- }
-
- off.Center = new Point(m.OffsetX, m.OffsetY);
-
- switch (deckupDownOrientation)
- {
- case DeckOrientation.Up:
- off.Orientation = angleDegree;
- break;
- case DeckOrientation.Down:
- off.Orientation = -angleDegree;
- break;
- }
- }
-
- return off;
- }
-
- private void TranslateRotateCopyMatrix(double x, double y, double angle, double rotationX, double rotationY, out Point p)
- {
- var m = new Matrix() { OffsetX = x, OffsetY = y };
- m.RotateAt(angle, rotationX, rotationY);
-
-
- p = new Point(m.OffsetX, m.OffsetY);
- }
-
- #endregion
-
- public void Cut(Card card)
- {
- var cardIndex = card.Deck.IndexOf(card);
- var cardsLeft = card.Deck.Where(c => card.Deck.IndexOf(c) < cardIndex).OfType<Card>();
- var cardsRight = card.Deck.Where(c => card.Deck.IndexOf(c) >= cardIndex).OfType<Card>();
-
- if (!cardsLeft.Any() || !cardsRight.Any())
- return;
-
- var leftoffset = CalcPositions(cardsLeft, true);
- var rightOffset = CalcPositions(cardsRight, false);
-
- // set the same animation duration for both
- var dispositionRect = card.Deck.GetCardsDestinationRect();
- var duration = DispositionHelper.ComputeAnimationDuration(dispositionRect.TopLeft, dispositionRect.TopRight, 0, 0, 1);
-
- leftoffset.Duration = rightOffset.Duration = duration;
-
- GatherCards(cardsLeft, true, leftoffset, rightOffset, null);
- GatherCards(cardsRight, false, rightOffset, leftoffset,
- (s, e) =>
- {
- using (card.Deck.DeferUpdateDisposition(true, true, 2))
- {
- var cards = cardsLeft.ToList();
- var deck = card.Deck;
- foreach (var c in cards)
- {
- deck.Remove(c);
- deck.Insert(deck.Count, c);
- }
- }
- }
- );
-
- }
-
- private DispositionOffset CalcPositions(IEnumerable<Card> allCards, bool left)
- {
- if (!allCards.Any())
- throw new Exception("Should have som cards");
-
- Card gatheredCard;
- if (left)
- gatheredCard = allCards.First();
- else
- gatheredCard = allCards.Last();
-
- Point dest = gatheredCard.ScatterViewItem.ActualCenter;
-
- DispositionOffset offset = new DispositionOffset
- {
- Center = dest,
- Orientation = gatheredCard.Deck.ScatterViewItem.ActualOrientation,
- };
-
- return offset;
- }
-
- private void GatherCards(IEnumerable<Card> allCards, bool isLeft, DispositionOffset beginOffset, DispositionOffset endOffset,
- EventHandler animsCompleted)
- {
-
- int i = 0;
- foreach (var card in allCards)
- {
- Point acutalDest = new Point(beginOffset.Center.X + i, beginOffset.Center.Y + i / 2);
- double actualOrientation = DispositionHelper.CalcOrientationForCards(card.ScatterViewItem.ActualOrientation, beginOffset.Orientation);
-
- var ca = DispositionHelper.BeginCenterAnimation(card.ScatterViewItem, acutalDest, beginOffset.Duration);
- DispositionHelper.BeginOrientationAnimation(card.ScatterViewItem, actualOrientation, beginOffset.Duration);
-
- if (card == allCards.Last())
- {
- ca.Completed += (s, e) =>
- {
- // when first anim completed, begin second one
- AnimateStacks(allCards, isLeft, beginOffset, endOffset, animsCompleted);
- };
- }
-
- i++;
- }
-
- }
-
- private void AnimateStacks(IEnumerable<Card> cards, bool isLeft, DispositionOffset beginOffset, DispositionOffset endOffset,
- EventHandler animsCompleted)
- {
-
- int i = 0;
- foreach (var card in cards)
- {
-
- // stop current animations if there is any
- DispositionHelper.StopCenterAnimation(card.ScatterViewItem);
- DispositionHelper.StopOrientationAnimation(card.ScatterViewItem);
-
- Point actualbeginCenter = card.ScatterViewItem.ActualCenter;
- Point actualDestCenter = new Point(endOffset.Center.X + i, endOffset.Center.Y + i / 2);
- Point actualMiddleCenter;
-
- if (isLeft)
- actualMiddleCenter = new Point(
- (card.ScatterViewItem.ActualCenter.X + actualDestCenter.X) / 2,
- card.ScatterViewItem.ActualCenter.Y + 200);
- else
-
- actualMiddleCenter = new Point(
- (card.ScatterViewItem.ActualCenter.X + actualDestCenter.X) / 2,
- card.ScatterViewItem.ActualCenter.Y - 200);
-
-
- BezierSegment bs = new BezierSegment(
- actualbeginCenter,
- actualMiddleCenter,
- actualDestCenter,
- true);
-
- PathGeometry path = new PathGeometry();
- PathFigure figure = new PathFigure();
- figure.StartPoint = actualbeginCenter;
- figure.Segments.Add(bs);
- figure.IsClosed = false;
- path.Figures.Add(figure);
-
- PointAnimationUsingPath anim =
- new PointAnimationUsingPath();
- anim.PathGeometry = path;
- anim.Duration = beginOffset.Duration + beginOffset.Duration;
-
- if (card == cards.Last())
- {
- if (animsCompleted != null)
- anim.Completed += animsCompleted;
- }
-
- card.ScatterViewItem.BeginAnimation(ScatterViewItem.CenterProperty, anim);
-
- i++;
- }
- }
-
- }
- }