/// <summary>Called once when time is EndTimeInMicroseconds.</summary> protected override sealed void SetFinalState(IModel model) { foreach (Stack stack in stacks) { IPiece piece = stack.Pieces[0]; ICounterSection counterSection = piece.CounterSection; if (model.CurrentSelection != null && model.CurrentSelection.Stack == stack) { if (piece is ICounter && ((int)counterSection.Type & (1 + (int)counterSection.CounterSheet.Side)) == 0 || piece is ICard && (counterSection.CounterSheet.Side == Side.Front) != counterSection.HasCardFaceOnFront) { model.CurrentSelection = null; } } ((CounterSheet)counterSection.CounterSheet).MoveStackToBack(stack); stack.AttachedToCounterSection = true; } }
/// <summary>Returns the top-most piece (but not terrain) at a given position on this board.</summary> /// <param name="position">Position in local coordinates.</param> /// <returns>A piece or null.</returns> public IPiece GetPieceAtPosition(PointF position) { // for each layer (bottom layer is for unpunched pieces, next layer is for punched cards, top layer is for punched counters) for (int layer = 2; layer >= 0; --layer) { for (int pass = 0; pass < 2; ++pass) { for (int i = Stacks.Count - 1; i >= 0; --i) { Stack stack = Stacks[i]; IPiece[] pieces = stack.Pieces; if (stack.Unfolded == (pass == 0) && !(pieces[0] is ITerrain) && ((layer == 0 && stack.AttachedToCounterSection) || (layer == 1 && !stack.AttachedToCounterSection && pieces[0] is ICard) || (layer == 2 && !stack.AttachedToCounterSection && pieces[0] is ICounter)) && stack.BoundingBox.Contains(position)) { // ignore attached pieces on the opposite side ICounterSection counterSection = pieces[0].CounterSection; CounterSectionType type = counterSection.Type; if (!stack.AttachedToCounterSection || (counterSection.ContainsCounters && ((int)type & ((int)((ICounterSheet)this).Side + 1)) != 0) || (!counterSection.ContainsCounters && counterSection.HasCardFaceOnFront == (((ICounterSheet)this).Side == Side.Front))) { for (int j = pieces.Length - 1; j >= 0; --j) { IPiece piece = pieces[j]; if (piece.BoundingBox.Contains(position)) { // we have to compute the model coordinates of the position // relative to the counter sheet // we have to handle rotations of the piece // apply the inverse rotation to the position PointF piecePosition = piece.Position; PointF transformedPosition = new PointF( position.X - piecePosition.X, position.Y - piecePosition.Y); if (piece.RotationAngle != 0.0f) { // rotation: // x <- x * cos - y * sin // y <- x * sin + y * cos float sin = (float)Math.Sin(piece.RotationAngle); float cos = (float)Math.Cos(piece.RotationAngle); transformedPosition = new PointF( transformedPosition.X * cos - transformedPosition.Y * sin, transformedPosition.X * sin + transformedPosition.Y * cos); } SizeF size = piece.Size; if (new RectangleF( -size.Width * 0.5f, -size.Height * 0.5f, size.Width, size.Height).Contains(transformedPosition)) { // is the piece completely transparent at that location? if (piece.Graphics != null) { uint color = piece.Graphics.GetColorAtPosition(transformedPosition); if ((color & 0xFF000000) != 0x00000000) { // no it is not if (!stack.Unfolded && piece is ICard) { return(pieces[pieces.Length - 1]); } else { return(piece); } } } } } } } } } } } return(null); }