Esempio n. 1
0
        private void load(UserProfileOverlay profileOverlay)
        {
            LeftFlowContainer.Add(new BeatmapMetadataContainer(beatmap));
            LeftFlowContainer.Add(new FillFlowContainer
            {
                RelativeSizeAxes = Axes.X,
                AutoSizeAxes     = Axes.Y,
                Direction        = FillDirection.Horizontal,
                Children         = new Drawable[]
                {
                    new OsuSpriteText
                    {
                        Text = @"mapped by ",
                        Font = OsuFont.GetFont(size: 12)
                    },
                    mapperContainer = new OsuHoverContainer
                    {
                        AutoSizeAxes = Axes.Both,
                        Children     = new Drawable[]
                        {
                            new OsuSpriteText
                            {
                                Text = beatmap.Metadata.AuthorString,
                                Font = OsuFont.GetFont(size: 12, weight: FontWeight.Medium, italics: true)
                            }
                        }
                    },
                }
            });

            RightFlowContainer.Add(new FillFlowContainer
            {
                Anchor       = Anchor.TopRight,
                Origin       = Anchor.TopRight,
                AutoSizeAxes = Axes.Both,
                Direction    = FillDirection.Horizontal,
                Children     = new[]
                {
                    new OsuSpriteText
                    {
                        Anchor = Anchor.BottomRight,
                        Origin = Anchor.BottomRight,
                        Text   = playCount.ToString(),
                        Font   = OsuFont.GetFont(size: 18, weight: FontWeight.SemiBold, italics: true)
                    },
                    new OsuSpriteText
                    {
                        Anchor = Anchor.BottomRight,
                        Origin = Anchor.BottomRight,
                        Text   = @"times played ",
                        Font   = OsuFont.GetFont(size: 12, weight: FontWeight.Regular, italics: true)
                    },
                }
            });

            if (profileOverlay != null)
            {
                mapperContainer.Action = () => profileOverlay.ShowUser(beatmap.BeatmapSet.Metadata.Author);
            }
        }
Esempio n. 2
0
        public TestCaseUserProfile()
        {
            var profile = new UserProfileOverlay();

            Add(profile);

            AddStep("Show offline dummy", () => profile.ShowUser(new User
            {
                Username = @"Somebody",
                Id       = 1,
                Country  = new Country {
                    FullName = @"Alien"
                },
                CoverUrl     = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg",
                JoinDate     = DateTimeOffset.Now.AddDays(-1),
                LastVisit    = DateTimeOffset.Now,
                Age          = 1,
                ProfileOrder = new[] { "me" },
                CountryRank  = 1,
                Statistics   = new UserStatistics
                {
                    Rank = 2148,
                    PP   = 4567.89m
                },
                AllRankHistories = new User.RankHistories
                {
                    Osu = new User.RankHistory
                    {
                        Mode = @"osu",
                        Data = Enumerable.Range(2345, 45).Concat(Enumerable.Range(2109, 40)).ToArray()
                    }
                }
            }, false));
            AddStep("Show ppy", () => profile.ShowUser(new User
            {
                Username = @"peppy",
                Id       = 2,
                Country  = new Country {
                    FullName = @"Australia", FlagName = @"AU"
                },
                CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg"
            }));
            AddStep("Show flyte", () => profile.ShowUser(new User
            {
                Username = @"flyte",
                Id       = 3103765,
                Country  = new Country {
                    FullName = @"Japan", FlagName = @"JP"
                },
                CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
            }));
            AddStep("Hide", profile.Hide);
            AddStep("Show without reload", profile.Show);
        }
Esempio n. 3
0
        private void load(OsuColour colours, UserProfileOverlay profile)
        {
            Status.ValueChanged += displayStatus;
            Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint);

            base.Action = () =>
            {
                Action?.Invoke();
                profile?.ShowUser(user);
            };
        }
Esempio n. 4
0
        private void load(UserProfileOverlay profile)
        {
            clickableArea.Action = () =>
            {
                if (avatar.User != null)
                {
                    profile?.ShowUser(avatar.User);
                }
            };

            updateDisplay();
        }
Esempio n. 5
0
        private void load(OsuColour colours, UserProfileOverlay profile)
        {
            if (colours == null)
            {
                throw new ArgumentNullException(nameof(colours));
            }

            Status.ValueChanged += displayStatus;
            Status.ValueChanged += status => statusBg.FadeColour(status?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint);

            base.Action = ViewProfile = () =>
            {
                Action?.Invoke();
                profile?.ShowUser(user);
            };
        }
Esempio n. 6
0
 private void load(UserProfileOverlay profile)
 {
     Action = () => profile?.ShowUser(sender);
 }
Esempio n. 7
0
        protected override void LoadComplete()
        {
            base.LoadComplete();

            // hook up notifications to components.
            BeatmapManager.PostNotification = n => notificationOverlay?.Post(n);
            BeatmapManager.GetStableStorage = GetStorageForStableInstall;

            AddRange(new Drawable[] {
                new VolumeControlReceptor
                {
                    RelativeSizeAxes = Axes.Both,
                    ActionRequested  = action => volume.Adjust(action)
                },
                mainContent = new Container
                {
                    RelativeSizeAxes = Axes.Both,
                },
                volume         = new VolumeControl(),
                overlayContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                new OnScreenDisplay(),
            });

            LoadComponentAsync(screenStack = new Loader(), d =>
            {
                screenStack.ModePushed += screenAdded;
                screenStack.Exited     += screenRemoved;
                mainContent.Add(screenStack);
            });

            //overlay elements
            LoadComponentAsync(direct = new DirectOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(social = new SocialOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(chat = new ChatOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(settings = new MainSettings
            {
                GetToolbarHeight = () => ToolbarOffset,
                Depth            = -1
            }, overlayContent.Add);
            LoadComponentAsync(userProfile = new UserProfileOverlay {
                Depth = -2
            }, mainContent.Add);
            LoadComponentAsync(beatmapSetOverlay = new BeatmapSetOverlay {
                Depth = -3
            }, mainContent.Add);
            LoadComponentAsync(musicController = new MusicController
            {
                Depth    = -4,
                Position = new Vector2(0, Toolbar.HEIGHT),
                Anchor   = Anchor.TopRight,
                Origin   = Anchor.TopRight,
            }, overlayContent.Add);

            LoadComponentAsync(notificationOverlay = new NotificationOverlay
            {
                Depth  = -4,
                Anchor = Anchor.TopRight,
                Origin = Anchor.TopRight,
            }, overlayContent.Add);

            LoadComponentAsync(dialogOverlay = new DialogOverlay
            {
                Depth = -5,
            }, overlayContent.Add);

            Logger.NewEntry += entry =>
            {
                if (entry.Level < LogLevel.Important)
                {
                    return;
                }

                notificationOverlay.Post(new SimpleNotification
                {
                    Text = $@"{entry.Level}: {entry.Message}"
                });
            };

            dependencies.Cache(settings);
            dependencies.Cache(social);
            dependencies.Cache(direct);
            dependencies.Cache(chat);
            dependencies.Cache(userProfile);
            dependencies.Cache(musicController);
            dependencies.Cache(beatmapSetOverlay);
            dependencies.Cache(notificationOverlay);
            dependencies.Cache(dialogOverlay);

            // ensure only one of these overlays are open at once.
            var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct };

            foreach (var overlay in singleDisplayOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }

                    foreach (var c in singleDisplayOverlays)
                    {
                        if (c == overlay)
                        {
                            continue;
                        }
                        c.State = Visibility.Hidden;
                    }
                };
            }

            LoadComponentAsync(Toolbar = new Toolbar
            {
                Depth  = -4,
                OnHome = delegate
                {
                    hideAllOverlays();
                    intro?.ChildScreen?.MakeCurrent();
                },
            }, overlayContent.Add);

            settings.StateChanged += delegate
            {
                switch (settings.State)
                {
                case Visibility.Hidden:
                    intro.MoveToX(0, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint);
                    break;

                case Visibility.Visible:
                    intro.MoveToX(SettingsOverlay.SIDEBAR_WIDTH / 2, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint);
                    break;
                }
            };

            Cursor.State = Visibility.Hidden;
        }
Esempio n. 8
0
File: OsuGame.cs Progetto: mist9/osu
        protected override void LoadComplete()
        {
            base.LoadComplete();

            AddRange(new Drawable[] {
                new VolumeControlReceptor
                {
                    RelativeSizeAxes = Axes.Both,
                    ActionRequested  = delegate(InputState state) { volume.Adjust(state); }
                },
                mainContent = new Container
                {
                    RelativeSizeAxes = Axes.Both,
                },
                volume         = new VolumeControl(),
                overlayContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                new OnScreenDisplay(),
                new GlobalHotkeys //exists because UserInputManager is at a level below us.
                {
                    Handler = globalHotkeyPressed
                }
            });

            LoadComponentAsync(screenStack = new Loader(), d =>
            {
                screenStack.ModePushed += screenAdded;
                screenStack.Exited     += screenRemoved;
                mainContent.Add(screenStack);
            });

            //overlay elements
            LoadComponentAsync(direct = new DirectOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(social = new SocialOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(chat = new ChatOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(userProfile = new UserProfileOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(settings = new SettingsOverlay {
                Depth = -1
            }, overlayContent.Add);
            LoadComponentAsync(musicController = new MusicController
            {
                Depth    = -2,
                Position = new Vector2(0, Toolbar.HEIGHT),
                Anchor   = Anchor.TopRight,
                Origin   = Anchor.TopRight,
            }, overlayContent.Add);

            LoadComponentAsync(notificationManager = new NotificationManager
            {
                Depth  = -2,
                Anchor = Anchor.TopRight,
                Origin = Anchor.TopRight,
            }, overlayContent.Add);

            LoadComponentAsync(dialogOverlay = new DialogOverlay
            {
                Depth = -4,
            }, overlayContent.Add);

            Logger.NewEntry += entry =>
            {
                if (entry.Level < LogLevel.Important)
                {
                    return;
                }

                notificationManager.Post(new SimpleNotification
                {
                    Text = $@"{entry.Level}: {entry.Message}"
                });
            };

            Dependencies.Cache(settings);
            Dependencies.Cache(social);
            Dependencies.Cache(chat);
            Dependencies.Cache(userProfile);
            Dependencies.Cache(musicController);
            Dependencies.Cache(notificationManager);
            Dependencies.Cache(dialogOverlay);

            // ensure both overlays aren't presented at the same time
            chat.StateChanged   += (container, state) => social.State = state == Visibility.Visible ? Visibility.Hidden : social.State;
            social.StateChanged += (container, state) => chat.State = state == Visibility.Visible ? Visibility.Hidden : chat.State;

            LoadComponentAsync(Toolbar = new Toolbar
            {
                Depth  = -3,
                OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); },
            }, overlayContent.Add);

            settings.StateChanged += delegate
            {
                switch (settings.State)
                {
                case Visibility.Hidden:
                    intro.MoveToX(0, SettingsOverlay.TRANSITION_LENGTH, EasingTypes.OutQuint);
                    break;

                case Visibility.Visible:
                    intro.MoveToX(SettingsOverlay.SIDEBAR_WIDTH / 2, SettingsOverlay.TRANSITION_LENGTH, EasingTypes.OutQuint);
                    break;
                }
            };

            Cursor.State = Visibility.Hidden;
        }
Esempio n. 9
0
        protected override void LoadComplete()
        {
            base.LoadComplete();

            // The next time this is updated is in UpdateAfterChildren, which occurs too late and results
            // in the cursor being shown for a few frames during the intro.
            // This prevents the cursor from showing until we have a screen with CursorVisible = true
            MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;

            // todo: all archive managers should be able to be looped here.
            SkinManager.PostNotification = n => notifications?.Post(n);
            SkinManager.GetStableStorage = GetStorageForStableInstall;

            BeatmapManager.PostNotification = n => notifications?.Post(n);
            BeatmapManager.GetStableStorage = GetStorageForStableInstall;

            BeatmapManager.PresentBeatmap = PresentBeatmap;

            AddRange(new Drawable[]
            {
                new VolumeControlReceptor
                {
                    RelativeSizeAxes      = Axes.Both,
                    ActionRequested       = action => volume.Adjust(action),
                    ScrollActionRequested = (action, amount, isPrecise) => volume.Adjust(action, amount, isPrecise),
                },
                screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays)
                {
                    RelativeSizeAxes = Axes.Both,
                },
                mainContent = new Container
                {
                    RelativeSizeAxes = Axes.Both,
                },
                overlayContent = new Container {
                    RelativeSizeAxes = Axes.Both, Depth = float.MinValue
                },
                idleTracker = new IdleTracker(6000)
            });

            loadComponentSingleFile(screenStack = new Loader(), d =>
            {
                screenStack.ModePushed += screenAdded;
                screenStack.Exited     += screenRemoved;
                screenContainer.Add(screenStack);
            });

            loadComponentSingleFile(Toolbar = new Toolbar
            {
                Depth  = -5,
                OnHome = delegate
                {
                    CloseAllOverlays(false);
                    intro?.ChildScreen?.MakeCurrent();
                },
            }, overlayContent.Add);

            loadComponentSingleFile(volume          = new VolumeOverlay(), overlayContent.Add);
            loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add);

            loadComponentSingleFile(screenshotManager, Add);

            //overlay elements
            loadComponentSingleFile(direct = new DirectOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(social = new SocialOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal);
            loadComponentSingleFile(chatOverlay    = new ChatOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(settings = new MainSettings
            {
                GetToolbarHeight = () => ToolbarOffset,
                Depth            = -1
            }, overlayContent.Add);
            loadComponentSingleFile(userProfile = new UserProfileOverlay {
                Depth = -2
            }, mainContent.Add);
            loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay {
                Depth = -3
            }, mainContent.Add);
            loadComponentSingleFile(musicController = new MusicController
            {
                Depth    = -5,
                Position = new Vector2(0, Toolbar.HEIGHT),
                Anchor   = Anchor.TopRight,
                Origin   = Anchor.TopRight,
            }, overlayContent.Add);

            loadComponentSingleFile(notifications = new NotificationOverlay
            {
                GetToolbarHeight = () => ToolbarOffset,
                Depth            = -4,
                Anchor           = Anchor.TopRight,
                Origin           = Anchor.TopRight,
            }, overlayContent.Add);

            loadComponentSingleFile(accountCreation = new AccountCreationOverlay
            {
                Depth = -6,
            }, overlayContent.Add);

            loadComponentSingleFile(dialogOverlay = new DialogOverlay
            {
                Depth = -7,
            }, overlayContent.Add);

            loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener
            {
                Depth = -8,
            }, overlayContent.Add);

            dependencies.Cache(idleTracker);
            dependencies.Cache(settings);
            dependencies.Cache(onscreenDisplay);
            dependencies.Cache(social);
            dependencies.Cache(direct);
            dependencies.Cache(chatOverlay);
            dependencies.Cache(channelManager);
            dependencies.Cache(userProfile);
            dependencies.Cache(musicController);
            dependencies.Cache(beatmapSetOverlay);
            dependencies.Cache(notifications);
            dependencies.Cache(dialogOverlay);
            dependencies.Cache(accountCreation);

            chatOverlay.StateChanged += state => channelManager.HighPollRate.Value = state == Visibility.Visible;

            Add(externalLinkOpener = new ExternalLinkOpener());

            var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications };

            overlays.AddRange(singleDisplaySideOverlays);

            foreach (var overlay in singleDisplaySideOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }
                    singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
                };
            }

            // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time.
            var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile };

            overlays.AddRange(informationalOverlays);

            foreach (var overlay in informationalOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }
                    informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
                };
            }

            // ensure only one of these overlays are open at once.
            var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct };

            overlays.AddRange(singleDisplayOverlays);

            foreach (var overlay in singleDisplayOverlays)
            {
                overlay.StateChanged += state =>
                {
                    // informational overlays should be dismissed on a show or hide of a full overlay.
                    informationalOverlays.ForEach(o => o.Hide());

                    if (state == Visibility.Hidden)
                    {
                        return;
                    }

                    singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
                };
            }

            OverlayActivationMode.ValueChanged += v =>
            {
                if (v != OverlayActivation.All)
                {
                    CloseAllOverlays();
                }
            };

            void updateScreenOffset()
            {
                float offset = 0;

                if (settings.State == Visibility.Visible)
                {
                    offset += ToolbarButton.WIDTH / 2;
                }
                if (notifications.State == Visibility.Visible)
                {
                    offset -= ToolbarButton.WIDTH / 2;
                }

                screenContainer.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint);
            }

            settings.StateChanged      += _ => updateScreenOffset();
            notifications.StateChanged += _ => updateScreenOffset();
        }
Esempio n. 10
0
        protected override void LoadComplete()
        {
            base.LoadComplete();

            // The next time this is updated is in UpdateAfterChildren, which occurs too late and results
            // in the cursor being shown for a few frames during the intro.
            // This prevents the cursor from showing until we have a screen with CursorVisible = true
            MenuCursorContainer.CanShowCursor = menuScreen?.CursorVisible ?? false;

            // todo: all archive managers should be able to be looped here.
            SkinManager.PostNotification = n => notifications?.Post(n);
            SkinManager.GetStableStorage = GetStorageForStableInstall;

            BeatmapManager.PostNotification = n => notifications?.Post(n);
            BeatmapManager.GetStableStorage = GetStorageForStableInstall;
            BeatmapManager.PresentImport    = items => PresentBeatmap(items.First());

            ScoreManager.PostNotification = n => notifications?.Post(n);
            ScoreManager.GetStableStorage = GetStorageForStableInstall;
            ScoreManager.PresentImport    = items => PresentScore(items.First());

            Container logoContainer;

            BackButton.Receptor receptor;

            dependencies.CacheAs(idleTracker = new GameIdleTracker(6000));

            AddRange(new Drawable[]
            {
                new VolumeControlReceptor
                {
                    RelativeSizeAxes      = Axes.Both,
                    ActionRequested       = action => volume.Adjust(action),
                    ScrollActionRequested = (action, amount, isPrecise) => volume.Adjust(action, amount, isPrecise),
                },
                screenContainer = new ScalingContainer(ScalingMode.ExcludeOverlays)
                {
                    RelativeSizeAxes = Axes.Both,
                    Children         = new Drawable[]
                    {
                        receptor    = new BackButton.Receptor(),
                        ScreenStack = new OsuScreenStack {
                            RelativeSizeAxes = Axes.Both
                        },
                        BackButton = new BackButton(receptor)
                        {
                            Anchor = Anchor.BottomLeft,
                            Origin = Anchor.BottomLeft,
                            Action = () =>
                            {
                                if ((ScreenStack.CurrentScreen as IOsuScreen)?.AllowBackButton == true)
                                {
                                    ScreenStack.Exit();
                                }
                            }
                        },
                        logoContainer = new Container {
                            RelativeSizeAxes = Axes.Both
                        },
                    }
                },
                overlayContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                rightFloatingOverlayContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                leftFloatingOverlayContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                topMostOverlayContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                idleTracker
            });

            ScreenStack.ScreenPushed += screenPushed;
            ScreenStack.ScreenExited += screenExited;

            loadComponentSingleFile(osuLogo, logo =>
            {
                logoContainer.Add(logo);

                // Loader has to be created after the logo has finished loading as Loader performs logo transformations on entering.
                ScreenStack.Push(CreateLoader().With(l => l.RelativeSizeAxes = Axes.Both));
            });

            loadComponentSingleFile(Toolbar = new Toolbar
            {
                OnHome = delegate
                {
                    CloseAllOverlays(false);
                    menuScreen?.MakeCurrent();
                },
            }, d =>
            {
                topMostOverlayContent.Add(d);
                toolbarElements.Add(d);
            });

            loadComponentSingleFile(volume = new VolumeOverlay(), leftFloatingOverlayContent.Add, true);

            loadComponentSingleFile(new OnScreenDisplay(), Add, true);

            loadComponentSingleFile(musicController = new MusicController(), Add, true);

            loadComponentSingleFile(notifications = new NotificationOverlay
            {
                GetToolbarHeight = () => ToolbarOffset,
                Anchor           = Anchor.TopRight,
                Origin           = Anchor.TopRight,
            }, rightFloatingOverlayContent.Add, true);

            loadComponentSingleFile(screenshotManager, Add);

            //overlay elements
            loadComponentSingleFile(direct         = new DirectOverlay(), overlayContent.Add, true);
            loadComponentSingleFile(social         = new SocialOverlay(), overlayContent.Add, true);
            loadComponentSingleFile(channelManager = new ChannelManager(), AddInternal, true);
            loadComponentSingleFile(chatOverlay    = new ChatOverlay(), overlayContent.Add, true);
            loadComponentSingleFile(Settings       = new SettingsOverlay {
                GetToolbarHeight = () => ToolbarOffset
            }, leftFloatingOverlayContent.Add, true);
            var changelogOverlay = loadComponentSingleFile(new ChangelogOverlay(), overlayContent.Add, true);

            loadComponentSingleFile(userProfile       = new UserProfileOverlay(), overlayContent.Add, true);
            loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay(), overlayContent.Add, true);

            loadComponentSingleFile(new LoginOverlay
            {
                GetToolbarHeight = () => ToolbarOffset,
                Anchor           = Anchor.TopRight,
                Origin           = Anchor.TopRight,
            }, rightFloatingOverlayContent.Add, true);

            loadComponentSingleFile(new NowPlayingOverlay
            {
                GetToolbarHeight = () => ToolbarOffset,
                Anchor           = Anchor.TopRight,
                Origin           = Anchor.TopRight,
            }, d =>
            {
                rightFloatingOverlayContent.Add(d);
                toolbarElements.Add(d);
            }, true);

            loadComponentSingleFile(new AccountCreationOverlay(), topMostOverlayContent.Add, true);
            loadComponentSingleFile(new DialogOverlay(), topMostOverlayContent.Add, true);
            loadComponentSingleFile(externalLinkOpener = new ExternalLinkOpener(), topMostOverlayContent.Add);

            chatOverlay.State.ValueChanged += state => channelManager.HighPollRate.Value = state.NewValue == Visibility.Visible;

            Add(externalLinkOpener = new ExternalLinkOpener());

            var singleDisplaySideOverlays = new OverlayContainer[] { Settings, notifications };

            overlays.AddRange(singleDisplaySideOverlays);

            foreach (var overlay in singleDisplaySideOverlays)
            {
                overlay.State.ValueChanged += state =>
                {
                    if (state.NewValue == Visibility.Hidden)
                    {
                        return;
                    }

                    singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
                };
            }

            // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time.
            var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile };

            overlays.AddRange(informationalOverlays);

            foreach (var overlay in informationalOverlays)
            {
                overlay.State.ValueChanged += state =>
                {
                    if (state.NewValue == Visibility.Hidden)
                    {
                        return;
                    }

                    informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
                };
            }

            // ensure only one of these overlays are open at once.
            var singleDisplayOverlays = new OverlayContainer[] { chatOverlay, social, direct, changelogOverlay };

            overlays.AddRange(singleDisplayOverlays);

            foreach (var overlay in singleDisplayOverlays)
            {
                overlay.State.ValueChanged += state =>
                {
                    // informational overlays should be dismissed on a show or hide of a full overlay.
                    informationalOverlays.ForEach(o => o.Hide());

                    if (state.NewValue == Visibility.Hidden)
                    {
                        return;
                    }

                    singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
                };
            }

            OverlayActivationMode.ValueChanged += mode =>
            {
                if (mode.NewValue != OverlayActivation.All)
                {
                    CloseAllOverlays();
                }
            };

            void updateScreenOffset()
            {
                float offset = 0;

                if (Settings.State.Value == Visibility.Visible)
                {
                    offset += ToolbarButton.WIDTH / 2;
                }
                if (notifications.State.Value == Visibility.Visible)
                {
                    offset -= ToolbarButton.WIDTH / 2;
                }

                screenContainer.MoveToX(offset, SettingsPanel.TRANSITION_LENGTH, Easing.OutQuint);
            }

            Settings.State.ValueChanged      += _ => updateScreenOffset();
            notifications.State.ValueChanged += _ => updateScreenOffset();
        }
Esempio n. 11
0
        protected override void LoadComplete()
        {
            base.LoadComplete();

            // hook up notifications to components.
            BeatmapManager.PostNotification = n => notificationOverlay?.Post(n);
            BeatmapManager.GetStableStorage = GetStorageForStableInstall;

            AddRange(new Drawable[] {
                new VolumeControlReceptor
                {
                    RelativeSizeAxes = Axes.Both,
                    ActionRequested  = delegate(InputState state) { volume.Adjust(state); }
                },
                mainContent = new Container
                {
                    RelativeSizeAxes = Axes.Both,
                },
                volume         = new VolumeControl(),
                overlayContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                new OnScreenDisplay(),
            });

            LoadComponentAsync(screenStack = new Loader(), d =>
            {
                screenStack.ModePushed += screenAdded;
                screenStack.Exited     += screenRemoved;
                mainContent.Add(screenStack);
            });

            //overlay elements
            LoadComponentAsync(direct = new DirectOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(social = new SocialOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(chat = new ChatOverlay {
                Depth = -1
            }, mainContent.Add);
            LoadComponentAsync(settings = new SettingsOverlay {
                Depth = -1
            }, overlayContent.Add);
            LoadComponentAsync(userProfile = new UserProfileOverlay {
                Depth = -2
            }, mainContent.Add);
            LoadComponentAsync(musicController = new MusicController
            {
                Depth    = -3,
                Position = new Vector2(0, Toolbar.HEIGHT),
                Anchor   = Anchor.TopRight,
                Origin   = Anchor.TopRight,
            }, overlayContent.Add);

            LoadComponentAsync(notificationOverlay = new NotificationOverlay
            {
                Depth  = -3,
                Anchor = Anchor.TopRight,
                Origin = Anchor.TopRight,
            }, overlayContent.Add);

            LoadComponentAsync(dialogOverlay = new DialogOverlay
            {
                Depth = -5,
            }, overlayContent.Add);

            Logger.NewEntry += entry =>
            {
                if (entry.Level < LogLevel.Important)
                {
                    return;
                }

                notificationOverlay.Post(new SimpleNotification
                {
                    Text = $@"{entry.Level}: {entry.Message}"
                });
            };

            dependencies.Cache(settings);
            dependencies.Cache(social);
            dependencies.Cache(chat);
            dependencies.Cache(userProfile);
            dependencies.Cache(musicController);
            dependencies.Cache(notificationOverlay);
            dependencies.Cache(dialogOverlay);

            // ensure both overlays aren't presented at the same time
            chat.StateChanged   += (container, state) => social.State = state == Visibility.Visible ? Visibility.Hidden : social.State;
            social.StateChanged += (container, state) => chat.State = state == Visibility.Visible ? Visibility.Hidden : chat.State;

            LoadComponentAsync(Toolbar = new Toolbar
            {
                Depth  = -4,
                OnHome = delegate
                {
                    //Create variable double step home exit
                    //If overlay was visible, home button will only close it
                    //Pressing home twice will go to main menu. This behavior should match Key.Escape
                    var overlayWasVisible = false;
                    foreach (var container in overlayContainers())
                    {
                        if (container.State == Visibility.Visible)
                        {
                            container.State   = Visibility.Hidden;
                            overlayWasVisible = true;
                        }
                    }
                    //Execute double exit if overlay was active
                    if (!overlayWasVisible)
                    {
                        intro?.ChildScreen?.MakeCurrent();
                    }
                },
            }, overlayContent.Add);

            settings.StateChanged += delegate
            {
                switch (settings.State)
                {
                case Visibility.Hidden:
                    intro.MoveToX(0, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint);
                    break;

                case Visibility.Visible:
                    intro.MoveToX(SettingsOverlay.SIDEBAR_WIDTH / 2, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint);
                    break;
                }
            };

            Cursor.State = Visibility.Hidden;
        }
Esempio n. 12
0
        private void load(OsuColour colours, UserProfileOverlay profile)
        {
            if (colours == null)
            {
                throw new ArgumentNullException(nameof(colours));
            }

            FillFlowContainer infoContainer;

            UserCoverBackground coverBackground;

            AddInternal(content = new Container
            {
                RelativeSizeAxes = Axes.Both,
                Masking          = true,
                CornerRadius     = 5,
                EdgeEffect       = new EdgeEffectParameters
                {
                    Type   = EdgeEffectType.Shadow,
                    Colour = Color4.Black.Opacity(0.25f),
                    Radius = 4,
                },

                Children = new Drawable[]
                {
                    new DelayedLoadWrapper(coverBackground = new UserCoverBackground(user)
                    {
                        RelativeSizeAxes = Axes.Both,
                        Anchor           = Anchor.Centre,
                        Origin           = Anchor.Centre,
                        FillMode         = FillMode.Fill,
                    }, 300)
                    {
                        RelativeSizeAxes = Axes.Both
                    },
                    new Box
                    {
                        RelativeSizeAxes = Axes.Both,
                        Colour           = Color4.Black.Opacity(0.7f),
                    },
                    new Container
                    {
                        RelativeSizeAxes = Axes.X,
                        AutoSizeAxes     = Axes.Y,
                        Padding          = new MarginPadding {
                            Top = content_padding, Horizontal = content_padding
                        },
                        Children = new Drawable[]
                        {
                            new UpdateableAvatar
                            {
                                Size         = new Vector2(height - status_height - content_padding * 2),
                                User         = user,
                                Masking      = true,
                                CornerRadius = 5,
                                OpenOnClick  = { Value = false },
                                EdgeEffect   = new EdgeEffectParameters
                                {
                                    Type   = EdgeEffectType.Shadow,
                                    Colour = Color4.Black.Opacity(0.25f),
                                    Radius = 4,
                                },
                            },
                            new Container
                            {
                                RelativeSizeAxes = Axes.Both,
                                Padding          = new MarginPadding {
                                    Left = height - status_height - content_padding
                                },
                                Children = new Drawable[]
                                {
                                    new OsuSpriteText
                                    {
                                        Text = user.Username,
                                        Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 18, italics: true),
                                    },
                                    infoContainer = new FillFlowContainer
                                    {
                                        Anchor       = Anchor.BottomLeft,
                                        Origin       = Anchor.BottomLeft,
                                        AutoSizeAxes = Axes.X,
                                        Height       = 20f,
                                        Direction    = FillDirection.Horizontal,
                                        Spacing      = new Vector2(5f, 0f),
                                        Children     = new Drawable[]
                                        {
                                            new DrawableFlag(user.Country)
                                            {
                                                Width            = 30f,
                                                RelativeSizeAxes = Axes.Y,
                                            },
                                        },
                                    },
                                },
                            },
                        },
                    },
                    statusBar = new Container
                    {
                        Anchor           = Anchor.BottomLeft,
                        Origin           = Anchor.BottomLeft,
                        RelativeSizeAxes = Axes.X,
                        Alpha            = 0f,
                        Children         = new Drawable[]
                        {
                            statusBg = new Box
                            {
                                RelativeSizeAxes = Axes.Both,
                                Alpha            = 0.5f,
                            },
                            new FillFlowContainer
                            {
                                Anchor       = Anchor.Centre,
                                Origin       = Anchor.Centre,
                                AutoSizeAxes = Axes.Both,
                                Spacing      = new Vector2(5f, 0f),
                                Children     = new Drawable[]
                                {
                                    new SpriteIcon
                                    {
                                        Anchor = Anchor.CentreLeft,
                                        Origin = Anchor.CentreLeft,
                                        Icon   = FontAwesome.Regular.Circle,
                                        Shadow = true,
                                        Size   = new Vector2(14),
                                    },
                                    statusMessage = new OsuSpriteText
                                    {
                                        Anchor = Anchor.CentreLeft,
                                        Origin = Anchor.CentreLeft,
                                        Font   = OsuFont.GetFont(weight: FontWeight.SemiBold),
                                    },
                                },
                            },
                        },
                    },
                }
            });

            coverBackground.OnLoadComplete += d => d.FadeInFromZero(400, Easing.Out);

            if (user.IsSupporter)
            {
                infoContainer.Add(new SupporterIcon
                {
                    RelativeSizeAxes = Axes.Y,
                    Width            = 20f,
                });
            }

            Status.ValueChanged += status => displayStatus(status.NewValue);
            Status.ValueChanged += status => statusBg.FadeColour(status.NewValue?.GetAppropriateColour(colours) ?? colours.Gray5, 500, Easing.OutQuint);

            base.Action = ViewProfile = () =>
            {
                Action?.Invoke();
                profile?.ShowUser(user);
            };
        }
Esempio n. 13
0
 private void load(OsuColour colours, UserProfileOverlay profile)
 {
     customUsernameColour = colours.ChatBlue;
     loadProfile          = u => profile?.ShowUser(u);
 }
Esempio n. 14
0
 private void load(UserProfileOverlay profile)
 {
     this.profile         = profile;
     clickableArea.Action = () => profile?.ShowUser(avatar.User);
 }
Esempio n. 15
0
        private void load(UserProfileOverlay profile)
        {
            if (colours == null)
            {
                throw new InvalidOperationException($"{nameof(colours)} not initialized!");
            }

            FillFlowContainer infoContainer;

            AddInternal(content = new Container
            {
                RelativeSizeAxes = Axes.Both,
                Masking          = true,
                CornerRadius     = 5,
                EdgeEffect       = new EdgeEffectParameters
                {
                    Type   = EdgeEffectType.Shadow,
                    Colour = Color4.Black.Opacity(0.25f),
                    Radius = 4,
                },

                Children = new Drawable[]
                {
                    new DelayedLoadUnloadWrapper(() => new UserCoverBackground
                    {
                        RelativeSizeAxes = Axes.Both,
                        Anchor           = Anchor.Centre,
                        Origin           = Anchor.Centre,
                        User             = user,
                    }, 300, 5000)
                    {
                        RelativeSizeAxes = Axes.Both,
                    },
                    new Box
                    {
                        RelativeSizeAxes = Axes.Both,
                        Colour           = Color4.Black.Opacity(0.7f),
                    },
                    new Container
                    {
                        RelativeSizeAxes = Axes.X,
                        AutoSizeAxes     = Axes.Y,
                        Padding          = new MarginPadding {
                            Top = content_padding, Horizontal = content_padding
                        },
                        Children = new Drawable[]
                        {
                            new UpdateableAvatar
                            {
                                Size         = new Vector2(height - status_height - content_padding * 2),
                                User         = user,
                                Masking      = true,
                                CornerRadius = 5,
                                OpenOnClick  = { Value = false },
                                EdgeEffect   = new EdgeEffectParameters
                                {
                                    Type   = EdgeEffectType.Shadow,
                                    Colour = Color4.Black.Opacity(0.25f),
                                    Radius = 4,
                                },
                            },
                            new Container
                            {
                                RelativeSizeAxes = Axes.Both,
                                Padding          = new MarginPadding {
                                    Left = height - status_height - content_padding
                                },
                                Children = new Drawable[]
                                {
                                    new OsuSpriteText
                                    {
                                        Text = user.Username,
                                        Font = OsuFont.GetFont(weight: FontWeight.SemiBold, size: 18, italics: true),
                                    },
                                    infoContainer = new FillFlowContainer
                                    {
                                        Anchor       = Anchor.BottomLeft,
                                        Origin       = Anchor.BottomLeft,
                                        AutoSizeAxes = Axes.X,
                                        Height       = 20f,
                                        Direction    = FillDirection.Horizontal,
                                        Spacing      = new Vector2(5f, 0f),
                                        Children     = new Drawable[]
                                        {
                                            new UpdateableFlag(user.Country)
                                            {
                                                Width            = 30f,
                                                RelativeSizeAxes = Axes.Y,
                                            },
                                        },
                                    },
                                },
                            },
                        },
                    },
                    statusBar = new Container
                    {
                        Anchor           = Anchor.BottomLeft,
                        Origin           = Anchor.BottomLeft,
                        RelativeSizeAxes = Axes.X,
                        Alpha            = 0f,
                        Children         = new Drawable[]
                        {
                            statusBg = new Box
                            {
                                RelativeSizeAxes = Axes.Both,
                                Alpha            = 0.5f,
                            },
                            new FillFlowContainer
                            {
                                Anchor       = Anchor.Centre,
                                Origin       = Anchor.Centre,
                                AutoSizeAxes = Axes.Both,
                                Spacing      = new Vector2(5f, 0f),
                                Children     = new Drawable[]
                                {
                                    new SpriteIcon
                                    {
                                        Anchor = Anchor.CentreLeft,
                                        Origin = Anchor.CentreLeft,
                                        Icon   = FontAwesome.Regular.Circle,
                                        Shadow = true,
                                        Size   = new Vector2(14),
                                    },
                                    statusMessage = new OsuSpriteText
                                    {
                                        Anchor = Anchor.CentreLeft,
                                        Origin = Anchor.CentreLeft,
                                        Font   = OsuFont.GetFont(weight: FontWeight.SemiBold),
                                    },
                                },
                            },
                        },
                    },
                }
            });

            if (user.IsSupporter)
            {
                infoContainer.Add(new SupporterIcon
                {
                    Height       = 20f,
                    SupportLevel = user.SupportLevel
                });
            }

            Status.ValueChanged   += status => displayStatus(status.NewValue, Activity.Value);
            Activity.ValueChanged += activity => displayStatus(Status.Value, activity.NewValue);

            base.Action = ViewProfile = () =>
            {
                Action?.Invoke();
                profile?.ShowUser(user);
            };
        }
Esempio n. 16
0
        protected override void LoadComplete()
        {
            // this needs to be cached before base.LoadComplete as it is used by MenuCursorContainer.
            dependencies.Cache(screenshotManager = new ScreenshotManager());

            base.LoadComplete();

            // The next time this is updated is in UpdateAfterChildren, which occurs too late and results
            // in the cursor being shown for a few frames during the intro.
            // This prevents the cursor from showing until we have a screen with CursorVisible = true
            MenuCursorContainer.CanShowCursor = currentScreen?.CursorVisible ?? false;

            // hook up notifications to components.
            SkinManager.PostNotification    = n => notifications?.Post(n);
            BeatmapManager.PostNotification = n => notifications?.Post(n);

            BeatmapManager.GetStableStorage = GetStorageForStableInstall;

            AddRange(new Drawable[]
            {
                new VolumeControlReceptor
                {
                    RelativeSizeAxes = Axes.Both,
                    ActionRequested  = action => volume.Adjust(action)
                },
                mainContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                overlayContent = new Container {
                    RelativeSizeAxes = Axes.Both, Depth = float.MinValue
                },
            });

            loadComponentSingleFile(screenStack = new Loader(), d =>
            {
                screenStack.ModePushed += screenAdded;
                screenStack.Exited     += screenRemoved;
                mainContent.Add(screenStack);
            });

            loadComponentSingleFile(Toolbar = new Toolbar
            {
                Depth  = -5,
                OnHome = delegate
                {
                    hideAllOverlays();
                    intro?.ChildScreen?.MakeCurrent();
                },
            }, overlayContent.Add);

            loadComponentSingleFile(volume          = new VolumeOverlay(), overlayContent.Add);
            loadComponentSingleFile(onscreenDisplay = new OnScreenDisplay(), Add);

            loadComponentSingleFile(screenshotManager, Add);

            //overlay elements
            loadComponentSingleFile(direct = new DirectOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(social = new SocialOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(chat = new ChatOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(settings = new MainSettings
            {
                GetToolbarHeight = () => ToolbarOffset,
                Depth            = -1
            }, overlayContent.Add);
            loadComponentSingleFile(userProfile = new UserProfileOverlay {
                Depth = -2
            }, mainContent.Add);
            loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay {
                Depth = -3
            }, mainContent.Add);
            loadComponentSingleFile(musicController = new MusicController
            {
                Depth    = -4,
                Position = new Vector2(0, Toolbar.HEIGHT),
                Anchor   = Anchor.TopRight,
                Origin   = Anchor.TopRight,
            }, overlayContent.Add);

            loadComponentSingleFile(notifications = new NotificationOverlay
            {
                GetToolbarHeight = () => ToolbarOffset,
                Depth            = -4,
                Anchor           = Anchor.TopRight,
                Origin           = Anchor.TopRight,
            }, overlayContent.Add);

            loadComponentSingleFile(dialogOverlay = new DialogOverlay
            {
                Depth = -6,
            }, overlayContent.Add);

            forwardLoggedErrorsToNotifications();

            dependencies.Cache(settings);
            dependencies.Cache(onscreenDisplay);
            dependencies.Cache(social);
            dependencies.Cache(direct);
            dependencies.Cache(chat);
            dependencies.Cache(userProfile);
            dependencies.Cache(musicController);
            dependencies.Cache(beatmapSetOverlay);
            dependencies.Cache(notifications);
            dependencies.Cache(dialogOverlay);

            // ensure only one of these overlays are open at once.
            var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct };

            foreach (var overlay in singleDisplayOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }

                    foreach (var c in singleDisplayOverlays)
                    {
                        if (c == overlay)
                        {
                            continue;
                        }
                        c.State = Visibility.Hidden;
                    }
                };
            }

            var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications };

            foreach (var overlay in singleDisplaySideOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }

                    foreach (var c in singleDisplaySideOverlays)
                    {
                        if (c == overlay)
                        {
                            continue;
                        }
                        c.State = Visibility.Hidden;
                    }
                };
            }

            // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time.
            var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile };

            foreach (var overlay in informationalOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }

                    foreach (var c in informationalOverlays)
                    {
                        if (c == overlay)
                        {
                            continue;
                        }
                        c.State = Visibility.Hidden;
                    }
                };
            }

            void updateScreenOffset()
            {
                float offset = 0;

                if (settings.State == Visibility.Visible)
                {
                    offset += ToolbarButton.WIDTH / 2;
                }
                if (notifications.State == Visibility.Visible)
                {
                    offset -= ToolbarButton.WIDTH / 2;
                }

                screenStack.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint);
            }

            settings.StateChanged      += _ => updateScreenOffset();
            notifications.StateChanged += _ => updateScreenOffset();

            notifications.Enabled.BindTo(AllowOpeningOverlays);

            HideOverlaysOnEnter.ValueChanged += hide =>
            {
                //central game screen change logic.
                if (hide)
                {
                    hideAllOverlays();
                    musicController.State = Visibility.Hidden;
                    Toolbar.State         = Visibility.Hidden;
                }
                else
                {
                    Toolbar.State = Visibility.Visible;
                }
            };
        }
Esempio n. 17
0
 private void load(UserProfileOverlay profile)
 {
     this.profile = profile;
 }
Esempio n. 18
0
        protected override void LoadComplete()
        {
            base.LoadComplete();

            // hook up notifications to components.
            BeatmapManager.PostNotification = n => notifications?.Post(n);
            BeatmapManager.GetStableStorage = GetStorageForStableInstall;

            AddRange(new Drawable[]
            {
                new VolumeControlReceptor
                {
                    RelativeSizeAxes = Axes.Both,
                    ActionRequested  = action => volume.Adjust(action)
                },
                mainContent = new Container {
                    RelativeSizeAxes = Axes.Both
                },
                overlayContent = new Container {
                    RelativeSizeAxes = Axes.Both, Depth = float.MinValue
                },
            });

            loadComponentSingleFile(screenStack = new Loader(), d =>
            {
                screenStack.ModePushed += screenAdded;
                screenStack.Exited     += screenRemoved;
                mainContent.Add(screenStack);
            });

            loadComponentSingleFile(Toolbar = new Toolbar
            {
                Depth  = -5,
                OnHome = delegate
                {
                    hideAllOverlays();
                    intro?.ChildScreen?.MakeCurrent();
                },
            }, overlayContent.Add);

            loadComponentSingleFile(volume = new VolumeControl(), Add);
            loadComponentSingleFile(new OnScreenDisplay(), Add);

            //overlay elements
            loadComponentSingleFile(direct = new DirectOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(social = new SocialOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(chat = new ChatOverlay {
                Depth = -1
            }, mainContent.Add);
            loadComponentSingleFile(settings = new MainSettings
            {
                GetToolbarHeight = () => ToolbarOffset,
                Depth            = -1
            }, overlayContent.Add);
            loadComponentSingleFile(userProfile = new UserProfileOverlay {
                Depth = -2
            }, mainContent.Add);
            loadComponentSingleFile(beatmapSetOverlay = new BeatmapSetOverlay {
                Depth = -3
            }, mainContent.Add);
            loadComponentSingleFile(musicController = new MusicController
            {
                Depth    = -4,
                Position = new Vector2(0, Toolbar.HEIGHT),
                Anchor   = Anchor.TopRight,
                Origin   = Anchor.TopRight,
            }, overlayContent.Add);

            loadComponentSingleFile(notifications = new NotificationOverlay
            {
                GetToolbarHeight = () => ToolbarOffset,
                Depth            = -4,
                Anchor           = Anchor.TopRight,
                Origin           = Anchor.TopRight,
            }, overlayContent.Add);

            loadComponentSingleFile(dialogOverlay = new DialogOverlay
            {
                Depth = -6,
            }, overlayContent.Add);

            Logger.NewEntry += entry =>
            {
                if (entry.Level < LogLevel.Important)
                {
                    return;
                }

                notifications.Post(new SimpleNotification
                {
                    Text = $@"{entry.Level}: {entry.Message}"
                });
            };

            dependencies.Cache(settings);
            dependencies.Cache(social);
            dependencies.Cache(direct);
            dependencies.Cache(chat);
            dependencies.Cache(userProfile);
            dependencies.Cache(musicController);
            dependencies.Cache(beatmapSetOverlay);
            dependencies.Cache(notifications);
            dependencies.Cache(dialogOverlay);

            // ensure only one of these overlays are open at once.
            var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct };

            foreach (var overlay in singleDisplayOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }

                    foreach (var c in singleDisplayOverlays)
                    {
                        if (c == overlay)
                        {
                            continue;
                        }
                        c.State = Visibility.Hidden;
                    }
                };
            }

            // eventually informational overlays should be displayed in a stack, but for now let's only allow one to stay open at a time.
            var informationalOverlays = new OverlayContainer[] { beatmapSetOverlay, userProfile };

            foreach (var overlay in informationalOverlays)
            {
                overlay.StateChanged += state =>
                {
                    if (state == Visibility.Hidden)
                    {
                        return;
                    }

                    foreach (var c in informationalOverlays)
                    {
                        if (c == overlay)
                        {
                            continue;
                        }
                        c.State = Visibility.Hidden;
                    }
                };
            }

            void updateScreenOffset()
            {
                float offset = 0;

                if (settings.State == Visibility.Visible)
                {
                    offset += ToolbarButton.WIDTH / 2;
                }
                if (notifications.State == Visibility.Visible)
                {
                    offset -= ToolbarButton.WIDTH / 2;
                }

                screenStack.MoveToX(offset, SettingsOverlay.TRANSITION_LENGTH, Easing.OutQuint);
            }

            settings.StateChanged      += _ => updateScreenOffset();
            notifications.StateChanged += _ => updateScreenOffset();

            Cursor.State = Visibility.Hidden;
        }