/// <summary>CounterSection constructor.</summary> public CounterSection(CounterSheet counterSheet, CounterSectionProperties properties, List <Piece> pieceList) { this.counterSheet = counterSheet; type = properties.Type; frontImageLocation = properties.FrontImageLocation; for (int i = (int)counterSheet.Properties.FrontImageResolution; i > 0; --i) { frontImageLocation = new RectangleF(frontImageLocation.X * 2, frontImageLocation.Y * 2, frontImageLocation.Width * 2, frontImageLocation.Height * 2); } backImageLocation = properties.BackImageLocation; for (int i = (int)counterSheet.Properties.BackImageResolution; i > 0; --i) { backImageLocation = new RectangleF(backImageLocation.X * 2, backImageLocation.Y * 2, backImageLocation.Width * 2, backImageLocation.Height * 2); } // create pieces for that section pieceFrontSize = new SizeF( frontImageLocation.Width / properties.Columns, frontImageLocation.Height / properties.Rows); pieceBackSize = new SizeF( backImageLocation.Width / properties.Columns, backImageLocation.Height / properties.Rows); pieceFrontDiagonal = (float)Math.Sqrt(pieceFrontSize.Width * pieceFrontSize.Width + pieceFrontSize.Height * pieceFrontSize.Height); pieceBackDiagonal = (float)Math.Sqrt(pieceBackSize.Width * pieceBackSize.Width + pieceBackSize.Height * pieceBackSize.Height); shadowLength = properties.ShadowLength; supply = properties.Supply; pieces = new Piece[properties.Rows * properties.Columns * properties.Supply]; for (int row = 0; row < properties.Rows; ++row) { for (int col = 0; col < properties.Columns; ++col) { for (int copy = 0; copy < properties.Supply; ++copy) { Piece piece = (counterSheet.Properties.Type == CounterSheetType.Terrain ? (Piece) new TerrainPrototype(pieceList.Count, this, row, col) : (Piece) new Counter(pieceList.Count, this, row, col)); pieces[(row * properties.Columns + col) * properties.Supply + copy] = piece; pieceList.Add(piece); } } } }
/// <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); }