Exemplo n.º 1
0
        /// <summary>
        /// Creates a new stage with start position and columns defined by the skin.
        /// </summary>
        /// <param name="skin">The skin to use.</param>
        /// <param name="posY">The vertical position of the stage.</param>
        /// <param name="height">The height of the stage.</param>
        /// <param name="minimal">Should we draw sprites?</param>
        /// <param name="columnOffset">The skin column offset for this stage (used for coop)</param>
        internal StageMania(SkinMania skin, bool minimal = false, float posY = 0f, float height = 480f, float posX = float.NaN, float widthScale = 1f, int stageIndex = 0, int columnOffset = 0)
        {
            Minimal           = minimal;
            Height            = height;
            Skin              = skin;
            this.stageIndex   = stageIndex;
            this.ColumnOffset = columnOffset;

            if (!minimal)
            {
                SpriteManager      = new SpriteManager(true);
                SpriteManagerBelow = new SpriteManager(true);
                SpriteManagerAbove = new SpriteManager(true);
                SpriteManagerNotes = new SpriteManager(true);

                stageHint              = new pSprite(Skin.Load(@"StageHint", @"mania-stage-hint", SkinSource), Fields.TopLeft, Origins.CentreLeft, Clocks.Audio, new Vector2(0, HitPosition), 0.62f, true, Color.White);
                stageHint.Alpha        = 0.9f;
                stageHint.VectorScale  = new Vector2(0, 0.9f);
                stageHint.Scale        = 1.6026f;
                stageHint.FlipVertical = UpsideDown;
                SpriteManager.Add(stageHint);

                pSprite p = new pSprite(Skin.Load(@"StageLeft", @"mania-stage-left", SkinSource), Fields.TopLeft, Origins.TopRight, Clocks.Audio, new Vector2(0.05f, Top), 0.8f, true, Color.White);
                p.VectorScale = new Vector2(HeightRatio, Height / (float)p.Height * 1.6f);
                SpriteManagerBelow.Add(p);

                stageRight             = new pSprite(Skin.Load(@"StageRight", @"mania-stage-right", SkinSource), Fields.TopLeft, Origins.TopLeft, Clocks.Audio, new Vector2(0.05f, Top), 0.8f, true, Color.White);
                stageRight.VectorScale = new Vector2(HeightRatio, Height / (float)stageRight.Height * 1.6f);
                SpriteManagerBelow.Add(stageRight);

                pTexture[] pt = Skin.LoadAll(@"StageBottom", @"mania-stage-bottom", SkinSource);
                if (pt != null && pt.Length > 0)
                {
                    stageBottom            = new pAnimation(pt, Fields.TopLeft, FlipOrigin(Origins.BottomCentre), Clocks.Audio, new Vector2(0, ActualBottom), 0.94f, true, Color.White);
                    stageBottom.FrameDelay = 1000 / 60f;
                    stageBottom.Scale      = 1.6f;
                    SpriteManagerAbove.Add(stageBottom);
                }

                if (Skin.JudgementLine)
                {
                    judgementLine             = new pSprite(GameBase.WhitePixel, Fields.TopLeft, FlipOrigin(Origins.TopLeft), Clocks.Audio, new Vector2(0, HitPosition), 0.62f, true, Skin.GetColour(@"JudgementLine"));
                    judgementLine.Alpha       = 0.9f;
                    judgementLine.VectorScale = new Vector2(0, 0.7f);
                    judgementLine.Scale       = 1.6026f;
                    SpriteManager.Add(judgementLine);
                }

                p             = new pSprite(TextureManager.Load("mania-stage-light", SkinSource.Osu), Fields.TopLeft, Origins.BottomRight, Clocks.Audio, new Vector2(0, Top), 0.5f, true, Color.TransparentWhite);
                p.Rotation    = -(float)(Math.PI / 2);
                p.VectorScale = new Vector2(Height / (float)p.Width, 0.27f) * 1.6f;
                SpriteManagerBelow.Add(p);

                waveRight             = new pSprite(TextureManager.Load("mania-stage-light", SkinSource.Osu), Fields.TopLeft, Origins.BottomLeft, Clocks.Audio, new Vector2(0, Top), 0.5f, true, Color.TransparentWhite);
                waveRight.Rotation    = (float)(Math.PI / 2);
                waveRight.VectorScale = new Vector2(Height / (float)waveRight.Width, 0.27f) * 1.6f;
                SpriteManagerBelow.Add(waveRight);

                hitScore            = new pAnimation(null, Fields.TopLeft, Origins.Centre, Clocks.Audio, new Vector2(0, ScaleFlipPosition(Skin.ScorePosition)), 0.998f, true, Color.White);
                hitScore.FrameDelay = 1000 / 20f;
                SpriteManagerAbove.Add(hitScore);

                foreach (string hitType in new[] { @"0", @"50", @"100", @"200", @"300", @"300g" })
                {
                    hitTextures.Add(hitType, Skin.LoadAll($@"Hit{hitType}", $@"mania-hit{hitType}", SkinSource));
                }

                if (hasHiddenSprites)
                {
                    bool fromKeyLayer = ModManager.CheckActive(Player.currentScore.EnabledMods, Mods.Hidden);

                    pTexture hiddenSprite = TextureManager.Load(@"mania-stage-hidden", SkinSource.Osu);

                    if (hiddenSprite == null)
                    {
                        GameBase.ChangeMode(OsuModes.Menu);
                    }

                    if (UpsideDown)
                    {
                        hiddenMask = new pSprite(GameBase.WhitePixel, Fields.TopLeft, fromKeyLayer ? Origins.TopLeft : Origins.BottomLeft, Clocks.Audio,
                                                 new Vector2(0, fromKeyLayer ? HitPosition : 480), 0.81f, true, Color.Black);
                        hiddenFade = new pSprite(hiddenSprite, Fields.TopLeft, fromKeyLayer ? Origins.TopLeft : Origins.BottomLeft, Clocks.Audio,
                                                 new Vector2(0, fromKeyLayer ? (HitPosition + 160 / 1.6f) : (320 / 1.6f)), 0.81f, true, Color.TransparentWhite);
                    }
                    else
                    {
                        hiddenMask = new pSprite(GameBase.WhitePixel, Fields.TopLeft, fromKeyLayer ? Origins.BottomLeft : Origins.TopLeft, Clocks.Audio,
                                                 new Vector2(0, fromKeyLayer ? HitPosition : 0), 0.81f, true, Color.Black);
                        hiddenFade = new pSprite(hiddenSprite, Fields.TopLeft, fromKeyLayer ? Origins.BottomLeft : Origins.TopLeft, Clocks.Audio,
                                                 new Vector2(0, fromKeyLayer ? (HitPosition - 160 / 1.6f) : (160 / 1.6f)), 0.81f, true, Color.TransparentWhite);
                    }

                    SpriteManagerAbove.Add(hiddenMask);
                    SpriteManagerAbove.Add(hiddenFade);
                }
            }

            //We must set these later as they position the spritemanagers
            Left = float.IsNaN(posX) ? Skin.ColumnStart : posX;
            Top  = posY;

            //Scale the width of columns, column spacing, and stage separation to fit everything on the screen
            //NOTE: This logic assumes there are a maximim of two stages
            if (!minimal && columnOffset == 0)
            {
                //Flip left and right offsets if they overlap
                float left  = Math.Min(Left, GameBase.WindowManager.WidthScaled - Skin.ColumnRight);
                float right = Math.Min(Skin.ColumnRight, GameBase.WindowManager.WidthScaled - Left);
                Left = left;

                //resizeWidth is the width of everything we're scaling that is to the right of "Left"
                float resizeWidth = 0;
                for (int i = 0; i < Skin.Columns; i++)
                {
                    resizeWidth += Skin.ColumnWidth[i] + (i > 0 ? Skin.ColumnSpacing[i - 1] : 0);
                }
                resizeWidth += Skin.SplitStages && SecondaryStageColumns != -1 ? Skin.StageSeparation : 0;

                float totalWidth     = Left + resizeWidth + right;
                float screenOverflow = Math.Max(0, totalWidth - GameBase.WindowManager.WidthScaled);

                widthScale = (resizeWidth - screenOverflow) / resizeWidth;
            }
            this.widthScale = widthScale;

            for (int i = columnOffset; i < columnOffset + PrimaryStageColumns; i++)
            {
                Columns.Add(new ColumnMania(this, i, widthScale));
            }

            if (!minimal)
            {
                //Set the visible area of the notes now that we know the width of the columns
                SpriteManagerNotes.SetVisibleArea(new RectangleF(Left, Top, Width, Height));
                SpriteManagerNotes.ForwardPlayOptimisations = true;
            }

            if (!minimal)
            {
                stageHint.VectorScale.X = Width / stageHint.Width;
                stageRight.Position.X  += Width;
                if (stageBottom != null)
                {
                    stageBottom.Position.X += Width / 2f;
                }
                if (judgementLine != null)
                {
                    judgementLine.VectorScale.X = Width;
                }
                waveRight.Position.X += Width;
                hitScore.Position.X  += Width / 2f;

                //Scale is used for sprite transformations, so we use vectorscale instead
                if (SkinManager.Current.Version >= 2.4 || HeightRatio < 1f)
                {
                    hitScore.VectorScale = Vector2.One * MinimumRatio;
                }

                //Hidden masks
                if (hasHiddenSprites)
                {
                    bool fromKeyLayer = ModManager.CheckActive(Player.currentScore.EnabledMods, Mods.Hidden);
                    hiddenMask.VectorScale = new Vector2(Width * 1.6f, 160);
                    hiddenMask.Alpha       = 0;
                    hiddenFade.VectorScale = new Vector2(Width * 1.6f, 180 / 250f);
                    if ((!fromKeyLayer && !UpsideDown) || (fromKeyLayer && UpsideDown))
                    {
                        hiddenFade.FlipVertical = true;
                    }
                    hiddenFade.Alpha = 0;
                }

                if (SecondaryStageColumns == -1)
                {
                    HPBar = new HpBarMania(this);
                }
            }

            if (SecondaryStageColumns != -1)
            {
                posX           = Left + Width + Skin.StageSeparation * widthScale;
                SecondaryStage = new StageMania(Skin, minimal, posY, height, posX, widthScale, stageIndex + 1, columnOffset + PrimaryStageColumns);
                Columns.AddRange(SecondaryStage.Columns);
                HPBar = SecondaryStage.HPBar;
            }

            bindColumnKeys();
        }
        internal void LoadKeys(bool setDefaultSplitStages = false)
        {
            currentBindingColumn = 0;

            spriteManager.SpriteList.FindAll(s => s.Tag == this).ForEach(s =>
            {
                s.FadeOut(50);
                s.AlwaysDraw = false;
                spriteManager.Remove(s);
            });

            disposeManiaStage();

            SkinMania skin = SkinManager.LoadManiaSkin(currentKeyConfig);

            cSplitLayout.Enabled = currentKeyConfig > 1 && skin.SplitStagesFromSkin == null;
            if (!setDefaultSplitStages)
            {
                skin.SplitStages = cSplitLayout.Checked;
            }
            cSplitLayout.SetStatusQuietly(skin.SplitStages);

            dKeyConfig.SpriteMainBox.Text = getKeyOptionText(currentKeyConfig, skin.SplitStages);

            stage = new StageMania(skin, true);

            //Validate the layout by recopying it to itself
            stage.CopyBindingToLayout(stage.LayoutList.Layout);

            dSpecialStyle.Enabled = stage.AllowSpecialStyle;

            switch (stage.SpecialStyle)
            {
            case ManiaSpecialStyle.Left:
                dSpecialStyle.SetSelected(1, true);
                break;

            case ManiaSpecialStyle.Right:
                dSpecialStyle.SetSelected(2, true);
                break;

            default:
                dSpecialStyle.SetSelected(0, true);
                break;
            }

            cBindAlternateKeys.Enabled = stage.SpecialStyle != ManiaSpecialStyle.None;
            if (stage.SpecialStyle == ManiaSpecialStyle.None)
            {
                cBindAlternateKeys.SetStatusQuietly(false);
            }

            cJudgementLine.SetStatusQuietly(skin.JudgementLine);
            cUpsideDown.SetStatusQuietly(skin.UpsideDown);

            float delta      = 40f;
            float separation = skin.SplitStages ? 1f : 0f;
            float totalWidth = (currentKeyConfig + separation) * delta;

            //Scale down if the keys are too wide to fit on the screen
            float scale = Math.Min(1f, GameBase.WindowManager.WidthScaled / totalWidth);

            totalWidth *= scale;
            delta      *= scale;
            float start = (GameBase.WindowManager.WidthScaled - totalWidth) / 2;

            arrow          = new pSprite(TextureManager.LoadFirstAvailable(new[] { @"arrow-generic", @"play-warningarrow" }, SkinSource.Osu), Fields.TopLeft, Origins.CentreLeft, Clocks.Game, new Vector2(0, 100), 0.92f, true, GameBase.NewGraphicsAvailable ? Color.SkyBlue : Color.White);
            arrow.Tag      = this;
            arrow.Rotation = OsuMathHelper.PiOver2;
            spriteManager.Add(arrow);

            keys = new pText[currentKeyConfig];
            int layoutIndex = 0;

            for (int i = 0; i < currentKeyConfig; i++)
            {
                bool skip = false;
                if (cBindAlternateKeys.Checked)
                {
                    skip = true;
                    foreach (StageMania s in stage)
                    {
                        if (i == s.Columns[s.SpecialColumn])
                        {
                            skip = false;
                        }
                    }
                }

                if (!skip)
                {
                    pSprite p = new pSprite(TextureManager.Load(@"mania-key1D", SkinSource.Osu), Fields.TopLeft, Origins.TopLeft, Clocks.Game, new Vector2(start, 192), 0.92f, true, stage.Columns[i].Colour);
                    p.VectorScale = 1.3f * new Vector2(scale, 1f);
                    p.Tag         = this;
                    spriteManager.Add(p);

                    keys[i]            = new pText(getKeyText(i), Math.Max(1, (int)Math.Round(14 * scale)), new Vector2(start + delta / 2f, 192 + 40), 0.93f, true, Color.White);
                    keys[i].TextBorder = true;
                    keys[i].Origin     = Origins.Centre;
                    keys[i].Tag        = this;
                    keys[i].TagNumeric = layoutIndex;
                    spriteManager.Add(keys[i]);

                    //Found the first non-skipped key
                    if (layoutIndex++ == 0)
                    {
                        currentBindingColumn = i;
                        arrow.Position.X     = start + delta / 2;
                    }
                }

                start += delta + delta * (i == stage.PrimaryStageColumns - 1 ? separation : 0);
            }
        }