private void updateBackgroundAlignment(pSprite s, AlignmentMode alignmentMode, BackgroundAdjustmentDelegate backgroundAdjustment)
        {
            if (s == null || BackgroundTexture == null)
            {
                return;
            }

            if ((alignmentMode & AlignmentMode.Storyboard) != 0)
            {
                s.ScaleToScreen((alignmentMode & AlignmentMode.Widescreen) != 0);
            }
            else
            {
                //first align based on height
                s.Scale = (float)GameBase.WindowManager.SpriteRes / BackgroundTexture.DisplayHeight;

                //if it isn't wide enough, let's make it so.
                if (s.Width * s.Scale * GameBase.WindowManager.RatioInverse < GameBase.WindowManager.Width)
                {
                    s.Scale = GameBase.WindowManager.Width / ((float)s.Width * GameBase.WindowManager.RatioInverse);
                }
            }

            if (backgroundAdjustment != null)
            {
                backgroundAdjustment(BackgroundSprite);
            }

            currentAlignmentMode        = alignmentMode;
            currentBackgroundAdjustment = backgroundAdjustment;
        }
        private void updateBackground(AlignmentMode alignmentMode, BackgroundAdjustmentDelegate backgroundAdjustment, pTexture loadedTexture = null)
        {
            if (!showBackground)
            {
                return;
            }

            if (BackgroundSprite != null && GameBase.Time >= Menu.IntroLength)
            {
                BackgroundSprite.FadeTo(1, 100);
            }

            if (loadedTexture == null || loadedTexture.IsDisposed)
            {
                //we need to load a new texture.
                int updateCountAtStart = backgroundUpdateCount;

                GameBase.RunBackgroundThread(delegate
                {
                    if (updateCountAtStart != backgroundUpdateCount)
                    {
                        return;
                    }

                    pTexture loaded = null;

                    //load from beatmap
                    if (BeatmapManager.Current != null && !string.IsNullOrEmpty(BeatmapManager.Current.BackgroundImage))
                    {
                        switch (GameBase.Mode)
                        {
                        case OsuModes.Edit:
                        case OsuModes.SelectEdit:
                        case OsuModes.SelectMulti:
                        case OsuModes.SelectPlay:
                        case OsuModes.Play:
                        case OsuModes.Rank:
                        case OsuModes.RankingTagCoop:
                        case OsuModes.RankingTeam:
                        case OsuModes.RankingVs:
                            loaded = TextureManager.Load(BeatmapManager.Current.BackgroundImage, SkinSource.Beatmap);
                            if (loaded != null)
                            {
                                loaded.Disposable = true;
                            }
                            break;
                        }
                    }

#if CHRISTMAS
                    if (loaded == null)
                    {
                        const int available_xmas_backgrounds = 13;
                        if (loadedBackgroundIndex < 0)
                        {
                            loadedBackgroundIndex = RNG.Next(1, available_xmas_backgrounds + 1);
                        }
                        else if (GameBase.Mode == OsuModes.Menu)
                        {
                            loadedBackgroundIndex = Math.Max(1, (loadedBackgroundIndex + 1) % (available_xmas_backgrounds + 1));
                        }

                        loaded = TextureManager.Load(@"menu-background-xmas-" + loadedBackgroundIndex, SkinSource.Osu);
                    }
#endif

                    //if we are a supporter, we can also check the skin for a custom menu-background.
                    if (loaded == null && (BanchoClient.Permission & Permissions.Supporter) > 0 && !SkinManager.IsDefault)
                    {
                        loaded = TextureManager.Load(@"menu-background.jpg", SkinSource.Skin);
                    }

                    //if we still haven't found a texture, we can fall back to the default.
                    if (loaded == null)
                    {
                        loaded = TextureManager.Load(@"menu-background", SkinSource.Osu);
                    }

                    //perform the final load.
                    if (loaded != null)
                    {
                        GameBase.Scheduler.Add(delegate
                        {
                            if (updateCountAtStart != backgroundUpdateCount)
                            {
                                return;
                            }

                            updateBackground(alignmentMode, backgroundAdjustment, loaded);
                        });
                    }
                });
            }
            else
            {
                //we have finished loading a texture.
                BackgroundTexture = loadedTexture;

                loadedBackgroundMode = BanchoClient.Permission;

                bool isSameTexture = BackgroundSprite != null && BackgroundTexture == BackgroundSprite.Texture;

                if (isSameTexture && currentBackgroundAdjustment == null && backgroundAdjustment == null && currentAlignmentMode == alignmentMode)
                {
                    return;
                }

                bool firstChange = BackgroundSprite == null;

                ClearBackground(false);
                BackgroundSprite = createBackgroundSprite(alignmentMode);
                if (GameBase.Time >= Menu.IntroLength)
                {
                    BackgroundSprite.FadeInFromZero(50);
                }
                else
                {
                    BackgroundSprite.Alpha = 0;
                }

                updateBackgroundAlignment(BackgroundSprite, alignmentMode, backgroundAdjustment);

                SpriteManager backgroundSpriteManager = (alignmentMode & AlignmentMode.Widescreen) != 0 ? spriteManagerBackWide : spriteManagerBack;
                backgroundSpriteManager.Add(BackgroundSprite);

                if (TrianglesBack != null)
                {
                    if (SkinManager.Current.TriangleColours.Count != 0)
                    {
                        GameBase.Scheduler.Add(delegate { TrianglesBack.SetColours(SkinManager.Current.TriangleColours); });
                    }
                    else
                    {
                        switch (BackgroundTexture.Source)
                        {
                        case SkinSource.Beatmap:
                            TrianglesBack.SetColours(BeatmapManager.Current.GetFileStream(BeatmapManager.Current.BackgroundImage), finishedReadingColours);
                            break;

                        case SkinSource.Skin:
                            Stream stream = new FileStream(BackgroundTexture.Filename, FileMode.Open, FileAccess.Read, FileShare.Read);
                            TrianglesBack.SetColours(stream, finishedReadingColours);
                            break;

                        default:
                            TrianglesBack.SetColours(null, finishedReadingColours);
                            break;
                        }
                    }
                }

                if (OnBackgroundChanged != null)
                {
                    OnBackgroundChanged();
                }
                TrianglesBack.VelocityCurrent = firstChange ? 150 : 50;
            }
        }
        internal void UpdateBackground(AlignmentMode alignmentMode = AlignmentMode.Default, BackgroundAdjustmentDelegate backgroundAdjustment = null)
        {
            BackgroundTexture = null;
            showBackground    = true;
            backgroundUpdateCount++;

            updateBackground(alignmentMode, backgroundAdjustment);
        }