public static SKRect ResizingBehaviorApply(ResizingBehavior behavior, SKRect rect, SKRect target)
        {
            if (rect.Equals(target) || target == null)
            {
                return(rect);
            }

            if (behavior == ResizingBehavior.Stretch)
            {
                return(target);
            }

            float xRatio = Math.Abs(target.Width / rect.Width);
            float yRatio = Math.Abs(target.Height / rect.Height);
            float scale  = 0f;

            switch (behavior)
            {
            case ResizingBehavior.AspectFit:
            {
                scale = Math.Min(xRatio, yRatio);
                break;
            }

            case ResizingBehavior.AspectFill:
            {
                scale = Math.Max(xRatio, yRatio);
                break;
            }

            case ResizingBehavior.Center:
            {
                scale = 1f;
                break;
            }
            }

            float newWidth  = Math.Abs(rect.Width * scale);
            float newHeight = Math.Abs(rect.Height * scale);

            return(new SKRect(target.MidX - newWidth / 2,
                              target.MidY - newHeight / 2,
                              target.MidX + newWidth / 2,
                              target.MidY + newHeight / 2));
        }
Exemple #2
0
        public override void RenderStats(IStateOwner pOwner, SKCanvas pRenderTarget, GameplayGameState Source, GameStateSkiaDrawParameters Element)
        {
            var Bounds = Element.Bounds;
            var g      = pRenderTarget;

            bool RedrawsNeeded = !LastDrawStat.Equals(Bounds);

            try
            {
                if (StatisticsBackground == null || RedrawsNeeded || Source.f_RedrawStatusBitmap || LastStatisticsTheme != Source.PlayField.Theme)
                {
                    GenerateStatisticsBackground(Source);
                }

                g.DrawImage(StatisticsBackground, Bounds);
                //g.Clear(Color.Black);
                if (!Source.HasTetrominoSKBitmaps() || RedrawsNeeded)
                {
                    RedrawStatusbarTetrominoBitmaps(pOwner, Source, Bounds);
                }

                lock (Source.LockTetImageRedraw)
                {
                    var        useStats = Source.GameStats;
                    double     Factor   = Bounds.Height / 644d;
                    var        DesiredFontPixelHeight = 22d; //  PixelsToPoints((int)(Bounds.Height * (30d / 644d)));
                    float      DesiredFontSize        = (float)(DesiredFontPixelHeight * pOwner.ScaleFactor);
                    SKTypeface standardFont           = TetrisGame.RetroFontSK;
                    //Font standardFont = new Font(TetrisGame.RetroFont, DesiredFontPixelHeight, FontStyle.Bold, GraphicsUnit.Pixel);

                    var TopScore       = Source.GetLocalScores() == null?0:Source.GetLocalScores().GetScores().First().Score;
                    int MaxScoreLength = Math.Max(TopScore.ToString().Length, useStats.Score.ToString().Length);

                    String CurrentScoreStr = useStats.Score.ToString().PadLeft(MaxScoreLength + 2);
                    String TopScoreStr     = TopScore.ToString().PadLeft(MaxScoreLength + 2);
                    //TODO: redo this segment separately, so we can have the labels left-aligned and the values right-aligned.
                    // String BuildStatString = "Time:  " + FormatGameTime(pOwner).ToString().PadLeft(MaxScoreLength + 2) + "\n" +
                    //                          "Score: " + CurrentScoreStr + "\n" +
                    //                          "Top:   " + TopScoreStr + " \n" +
                    //                          "Lines: " + GameStats.LineCount.ToString().PadLeft(MaxScoreLength+2);
                    //SKPaint skp = new SKPaint(){Style = SKPaintStyle.Fill,Color=;
                    //g.DrawRect();
                    g.DrawRect(Bounds.Left, Bounds.Top + 5, Bounds.Width - 10, (int)(450 * Factor), LightenBrush);
                    //String[] StatLabels = new string[] { "Time:", "Score:", "Top:", "Lines:" };
                    //int LineCount = Source.GameStats is TetrisStatistics ? (Source.GameStats as TetrisStatistics).LineCount : 0;
                    //String[] StatValues = new string[] { FormatGameTime(pOwner), useStats.Score.ToString(), TopScore.ToString(), LineCount.ToString() };

                    WhiteBrush.TextSize = BlackBrush.TextSize = DesiredFontSize;
                    WhiteBrush.Typeface = BlackBrush.Typeface = TetrisGame.RetroFontSK;
                    SKRect MeasureLabel = new SKRect(), MeasureValue = new SKRect();
                    BlackBrush.MeasureText("#", ref MeasureLabel);
                    BlackBrush.MeasureText("#", ref MeasureValue);
                    SKPoint StatPosition     = new SKPoint(Bounds.Left + (int)(7 * Factor), Bounds.Top + MeasureLabel.Height + (int)(14 * Factor));
                    float   CurrentYPosition = StatPosition.Y + MeasureLabel.Height;
                    var     StatData         = useStats.GetDisplayStatistics(pOwner, Source);

                    int MaxLabelLength = 0;
                    int MaxValueLength = 0;
                    foreach (var statkvp in StatData)
                    {
                        if (MaxLabelLength < statkvp.Key.Length)
                        {
                            MaxLabelLength = statkvp.Key.Length;
                        }
                        if (MaxValueLength < statkvp.Value.Length)
                        {
                            MaxValueLength = statkvp.Value.Length;
                        }
                    }

                    foreach (var statkvp in StatData)
                    //for (int statindex = 0; statindex < StatLabels.Length; statindex++)
                    {
                        String Label      = statkvp.Key;
                        String Value      = statkvp.Value.PadLeft(MaxValueLength, ' ');
                        float  LabelWidth = BlackBrush.MeasureText(Label.Replace(" ", "_") + "###", ref MeasureLabel);
                        float  ValueWidth = BlackBrush.MeasureText(Value.Replace(" ", "_") + "###", ref MeasureValue);

                        //var MeasureLabel = g.MeasureString(StatLabels[statindex], standardFont);
                        //var MeasureValue = g.MeasureString(StatValues[statindex], standardFont);
                        float LargerHeight = Math.Max(MeasureLabel.Height, MeasureValue.Height);

                        //we want to draw the current stat label at position StatPosition.X,CurrentYPosition...

                        // TetrisGame.DrawTextSK(g, StatLabels[statindex], new SKPoint(StatPosition.X, CurrentYPosition),
                        //     TetrisGame.RetroFontSK, SKColors.Black, DesiredFontSize, (float)pOwner.ScaleFactor);


                        //draw labels...
                        g.DrawText(Label, new SKPoint(StatPosition.X + 5, CurrentYPosition + 5), WhiteBrush);
                        g.DrawText(Label, new SKPoint(StatPosition.X, CurrentYPosition), BlackBrush);


                        SKPoint ValuePosition = new SKPoint((float)(Bounds.Right - ((MeasureValue.Width) + (7 * Factor))), CurrentYPosition);

                        g.DrawText(Value, new SKPoint(ValuePosition.X + 5, ValuePosition.Y + 5), WhiteBrush);
                        g.DrawText(Value, new SKPoint(ValuePosition.X, ValuePosition.Y), BlackBrush);
                        //TetrisGame.DrawTextSK(g, PaintInfo);


                        //TetrisGame.DrawTextSK(g, PaintInfo);

                        //we want to draw the current stat value at Bounds.Width-ValueWidth.
                        //TetrisGame.DrawTextSK(g, StatValues[statindex], new SKPoint((float)(Bounds.Right - ((MeasureValue.Width) + (5 * Factor))), CurrentYPosition), TetrisGame.RetroFontSK, SKColors.Black, DesiredFontSize, (float)pOwner.ScaleFactor);

                        //add the larger of the two heights to the current Y Position.
                        CurrentYPosition += (int)LargerHeight;
                        CurrentYPosition += 10;
                    }


                    var findRenderer = Source.GameHandler.GetStatAreaRenderer <SKCanvas, GameStateSkiaDrawParameters>();
                    if (findRenderer != null)
                    {
                        //bounds of stat area.
                        var    LeftBound = Bounds.Left + (int)(30 * Factor);
                        var    TopBound  = Bounds.Top + (int)(140 * Factor);
                        SKRect useBounds = new SKRect(LeftBound, TopBound, Bounds.Right, (float)(420 * Factor));
                        GameStateSkiaDrawParameters parameters = new GameStateSkiaDrawParameters(useBounds);
                        findRenderer.Render(pOwner, pRenderTarget, Source, parameters);
                    }
                    else
                    {
                    }
                    SKPoint NextDrawPosition = new SKPoint(Bounds.Left + (int)(40f * Factor), Bounds.Top + (int)(420 * Factor));
                    Size    NextSize         = new Size((int)(200f * Factor), (int)(200f * Factor));
                    SKPoint CenterPoint      = new SKPoint(NextDrawPosition.X + NextSize.Width / 2, NextDrawPosition.Y + NextSize.Height / 2);

                    if (Source.NextBlocks.Count > 0)
                    {
                        var        QueueList       = Source.NextBlocks.ToArray();
                        SKBitmap[] NextTetrominoes = (from t in QueueList select Source.GetTetrominoSKBitmap(pOwner, t)).ToArray();
                        SKBitmap   DisplayBox      = TetrisGame.Imageman.GetSKBitmap("display_box");
                        //draw it at 40,420. (Scaled).
                        float ScaleDiff = 0;
                        iActiveSoundObject PlayingMusic;
                        if ((PlayingMusic = TetrisGame.Soundman.GetPlayingMusic_Active()) != null)
                        {
                            Source.StoredLevels.Enqueue(PlayingMusic.Level);
                        }

                        if (Source.StoredLevels.Count >= 4)
                        {
                            ScaleDiff = Math.Min(30, 10 * Source.StoredLevels.Dequeue());
                        }

                        if (!TetrisGame.DJMode)
                        {
                            ScaleDiff = 0;
                        }


                        SKRect useRectangle = new SKRect(NextDrawPosition.X - ScaleDiff, NextDrawPosition.Y - ScaleDiff,
                                                         NextDrawPosition.X - ScaleDiff + NextSize.Width + ScaleDiff * 2,
                                                         NextDrawPosition.Y - ScaleDiff + NextSize.Height + ScaleDiff * 2);



                        g.DrawBitmap(DisplayBox, useRectangle);

                        g.DrawCircle(CenterPoint.X - 5, CenterPoint.Y - 5, 5, BlackBrush);

                        //new "wiggling" mode. add Sin(timer*(5*index))*30 to the angle.

                        for (int i = NextTetrominoes.Length - 1; i > -1; i--)
                        {
                            var baseval = ((double)(DateTime.Now.Ticks + (250000 * i)) / 5000000);
                            //var AngleAdd = Math.Sin(baseval) * 10; //old approach.
                            var AngleAdd = (Math.Sin(baseval) * Math.Cos(baseval * 2)) * 7; //new approach, tries to be a little bit different...

                            //var AngleAdd = Math.Sin(((double)DateTime.Now.Millisecond / 166)) * 15;


                            double StartAngle         = Math.PI;
                            double AngleIncrementSize = (Math.PI * 1.8) / (double)NextTetrominoes.Length;
                            //we draw starting at StartAngle, in increments of AngleIncrementSize.
                            //i is the index- we want to increase the angle by that amount (well, obviously, I suppose...

                            double UseAngleCurrent = StartAngle + AngleIncrementSize * (float)i + Source.NextAngleOffset;

                            double UseXPosition = CenterPoint.X + ((float)((NextSize.Width) / 2.2) * Math.Cos(UseAngleCurrent));
                            double UseYPosition = CenterPoint.Y + ((float)((NextSize.Height) / 2.2) * Math.Sin(UseAngleCurrent));


                            var NextTetromino = NextTetrominoes[i];
                            if (NextTetromino == null)
                            {
                                continue;
                            }
                            float Deviation = (i - NextTetrominoes.Length / 2);
                            Point Deviate   = new Point((int)(Deviation * 20 * Factor), (int)(Deviation * 20 * Factor));

                            var AngleRotateLocation = DateTime.Now.Ticks / 5000000;

                            Point DrawTetLocation = new Point((int)UseXPosition - (NextTetromino.Width / 2), (int)UseYPosition - NextTetromino.Height / 2);
                            //Point DrawTetLocation = new Point(Deviate.X + (int)(NextDrawPosition.X + ((float)NextSize.Width / 2) - ((float)NextTetromino.Width / 2)),
                            //    Deviate.Y + (int)(NextDrawPosition.Y + ((float)NextSize.Height / 2) - ((float)NextTetromino.Height / 2)));
                            double AngleMovePercent = Source.NextAngleOffset / AngleIncrementSize;
                            double NumAffect        = Source.NextAngleOffset == 0 ? 0 : AngleIncrementSize / Source.NextAngleOffset;
                            Size   DrawTetSize      = new Size
                                                      (
                                (int)((float)(NextTetromino.Width * 1.5f) * (0.3 + (1 - ((float)(i) * 0.15f) - .15f * AngleMovePercent))),
                                (int)((float)(NextTetromino.Height * 1.5f) * (0.3 + (1 - ((float)(i) * 0.15f) - .15f * AngleMovePercent))));


                            //g.TranslateTransform(CenterPoint.X,CenterPoint.Y);
                            double DrawTetAngle = UseAngleCurrent;
                            DrawTetAngle += (Math.PI * AngleMovePercent);
                            float useDegrees = 180 + (float)(DrawTetAngle * (180 / Math.PI));
                            useDegrees = (float)(useDegrees + AngleAdd);
                            g.RotateDegrees(useDegrees, DrawTetLocation.X + DrawTetSize.Width / 2, DrawTetLocation.Y + DrawTetSize.Width / 2);

                            var DrawAdjustmentAngle = MathHelper.mod((int)(((double)DateTime.Now.Ticks / 400) * (5f * i)), 360);



                            if (DrawTetSize.Width > 0 && DrawTetSize.Height > 0)
                            {
                                //ImageAttributes Shade = GetShadowAttributes(1.0f - ((float)i * 0.3f));
                                //ImageAttributes Shade = new ImageAttributes();
                                //Shade.SetColorMatrix(ColorMatrices.GetFader(1.0f - ((float)i * 0.1f)));

                                SKRect DrawBound = new SKRect(DrawTetLocation.X, DrawTetLocation.Y, DrawTetLocation.X + DrawTetSize.Width, DrawTetLocation.Y + DrawTetSize.Height);

                                //for the shade we would need to deal with SKPaint, I feel. Want to get it working somewhat first though.
                                g.DrawBitmap(NextTetromino, DrawBound, null);
                            }

                            g.ResetMatrix();
                        }
                    }

                    if (Source.HoldBlock != null)
                    {
                        SKBitmap HoldTetromino = Source.GetTetrominoSKBitmap(Source.HoldBlock.GetType());
                        if (HoldTetromino != null)
                        {
                            g.DrawBitmap(HoldTetromino, CenterPoint.X - HoldTetromino.Width / 2, CenterPoint.Y - HoldTetromino.Height / 2);
                        }
                    }
                }
            }
            finally
            {
                LastDrawStat = Bounds;
            }
        }