/// <summary> /// Draws the entire game board for the provided state. /// </summary> /// <param name="sender"></param> /// <param name="session"></param> /// <param name="gameState"></param> public void Draw(ICanvasResourceCreator sender, double width, double height, CanvasDrawingSession session, GameTreeNode gameState) { // Calculations double clientWidth = width; double clientHeight = height; int boardWidth = this.SharedBoardControlState.BoardWidth; int widthWithBorder = boardWidth + (this.ShowCoordinates ? 2 : 0); int boardHeight = this.SharedBoardControlState.BoardHeight; Rect boardRectangle = RenderUtilities.Scale( new Rect(0, 0, clientWidth, clientHeight), boardWidth + (this.ShowCoordinates ? 2 : 0), boardHeight + (this.ShowCoordinates ? 2 : 0)); _cellSize = (int)(boardRectangle.Width / widthWithBorder); _halfSize = _cellSize / 2; if (this.ShowCoordinates) { _boardBorderThickness = _cellSize; } else { _boardBorderThickness = 0; } this.SharedBoardControlState.LeftPadding = (int)boardRectangle.X + _boardBorderThickness; this.SharedBoardControlState.TopPadding = (int)boardRectangle.Y + _boardBorderThickness; this.SharedBoardControlState.NewCellSize = _cellSize; // The above should only be probably called on demand, not always // Draw parts DrawBoard(session, clientWidth, clientHeight, boardRectangle); // Draw coordinates session.Transform = Matrix3x2.CreateTranslation( (float)boardRectangle.X, (float)boardRectangle.Y); DrawBoardCoordinates(sender, session, boardWidth, boardHeight); // Draw grid session.Transform = Matrix3x2.CreateTranslation( (float)boardRectangle.X + _boardBorderThickness, (float)boardRectangle.Y + _boardBorderThickness); CanvasCommandList lines = new CanvasCommandList(sender); using (CanvasDrawingSession linesSession = lines.CreateDrawingSession()) { linesSession.Antialiasing = CanvasAntialiasing.Aliased; DrawBoardLines(linesSession, boardWidth, boardHeight); } session.DrawImage(lines); DrawBoardStarPoints(session, boardWidth, boardHeight); lines.Dispose(); // Shining position special case if (_sharedBoardControlState.ShiningPosition.IsDefined) { int x = this.SharedBoardControlState.ShiningPosition.X; int y = ((this.SharedBoardControlState.BoardHeight - 1) - this.SharedBoardControlState.ShiningPosition.Y); float minusWhat = (float)_flickerPercentage * _cellSize * 0.07f; session.FillRoundedRectangle( _cellSize * x + minusWhat, _cellSize * y + minusWhat, _cellSize - 2 * minusWhat, _cellSize - 2 * minusWhat, 4, 4, Color.FromArgb(140, 100, 200, 100)); } // Draw all stones for given game state DrawStones(gameState, session); Position pointerPosition = _sharedBoardControlState.PointerOverPosition; // Mouse over position special case if (pointerPosition.IsDefined && _sharedBoardControlState.IsShadowDrawingEnabled) { if (SharedBoardControlState.IsAnalyzeModeEnabled) { // Set actual pointer position for the tools // This has to be done here and not in InputService because we might get caught in race condition // - pointerPosition.IsDefined returns true and in mean time user moves pointer outside of the board and IToolServices advertises Position.Undefined // - and finally in this step we ask ITool for its shadow. ITools should not worry about handling Position.Undefined for GetShadow SharedBoardControlState.AnalyzeToolServices.SetPointerPosition(pointerPosition); // Analyze mode is enabled, draw selected tool shadow item. DrawAnalyzeToolShadow(session, SharedBoardControlState.AnalyzeModeTool); } else { // TODO (future work) Petr : only if legal - use Ruleset IsLegalMove? // But it would be slow, you can implement caching to check for each intersection only once if (_sharedBoardControlState.PointerOverShadowColor != StoneColor.None && ( _sharedBoardControlState.TEMP_MoveLegality == null || _sharedBoardControlState.TEMP_MoveLegality[pointerPosition.X, pointerPosition.Y] == MoveResult.Legal)) { DrawStone(session, pointerPosition.X, pointerPosition.Y, _sharedBoardControlState.PointerOverShadowColor, 0.5); } } } // Draw markups if enabled if (SharedBoardControlState.IsAnalyzeModeEnabled) { session.Blend = CanvasBlend.SourceOver; DrawMarkups(session, gameState.Markups); } // Draw debug FPS session.Transform = Matrix3x2.Identity; if (!SimpleRenderService) { _fpsCounter.Draw(session, new Rect(clientWidth - 100, 10, 80, 30)); } }