private void updateSize()
        {
            const float fade_time = 500;

            if (targetMode == ScalingMode.Everything)
            {
                // the top level scaling container manages the background to be displayed while scaling.
                if (requiresBackgroundVisible)
                {
                    if (backgroundStack == null)
                    {
                        AddInternal(backgroundStack = new BackgroundScreenStack
                        {
                            Colour = OsuColour.Gray(0.1f),
                            Alpha  = 0,
                            Depth  = float.MaxValue
                        });

                        backgroundStack.Push(new ScalingBackgroundScreen());
                    }

                    backgroundStack.FadeIn(fade_time);
                }
                else
                {
                    backgroundStack?.FadeOut(fade_time);
                }
            }

            bool scaling = targetMode == null || scalingMode.Value == targetMode;

            var  targetSize      = scaling ? new Vector2(sizeX.Value, sizeY.Value) : Vector2.One;
            var  targetPosition  = scaling ? new Vector2(posX.Value, posY.Value) * (Vector2.One - targetSize) : Vector2.Zero;
            bool requiresMasking = scaling && targetSize != Vector2.One;

            if (requiresMasking)
            {
                sizableContainer.Masking = true;
            }

            sizableContainer.MoveTo(targetPosition, 500, Easing.OutQuart);
            sizableContainer.ResizeTo(targetSize, 500, Easing.OutQuart).OnComplete(_ => { sizableContainer.Masking = requiresMasking; });
        }
Exemple #2
0
 public void SetUpSteps()
 {
     AddStep("create background stack", () => Child         = stack = new BackgroundScreenStack());
     AddStep("push default screen", () => stack.Push(screen = new BackgroundScreenDefault(false)));
     AddUntilStep("wait for screen to load", () => screen.IsCurrentScreen());
 }
Exemple #3
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.PresentImport    = items => PresentScore(items.First());

            Container logoContainer;

            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[]
                    {
                        backgroundParallax = new ParallaxContainer
                        {
                            RelativeSizeAxes = Axes.Both,
                            Child            = backgroundStack = new BackgroundScreenStack {
                                RelativeSizeAxes = Axes.Both
                            },
                        },
                        screenStack = new ScreenStack {
                            RelativeSizeAxes = Axes.Both
                        },
                        logoContainer = new Container {
                            RelativeSizeAxes = Axes.Both
                        },
                    }
                },
                overlayContent = new Container
                {
                    RelativeSizeAxes = Axes.Both,
                },
                floatingOverlayContent = new Container {
                    RelativeSizeAxes = Axes.Both, Depth = float.MinValue
                },
                idleTracker = new GameIdleTracker(6000)
            });

            dependencies.Cache(backgroundStack);

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

            loadComponentSingleFile(osuLogo, logoContainer.Add);

            loadComponentSingleFile(new Loader
            {
                RelativeSizeAxes = Axes.Both
            }, screenStack.Push);

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

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

            loadComponentSingleFile(screenshotManager, Add);

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

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

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

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

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

            dependencies.CacheAs(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 += mode =>
            {
                if (mode.NewValue != 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();
        }
Exemple #4
0
        private void updateSize()
        {
            if (targetMode == ScalingMode.Everything)
            {
                // the top level scaling container manages the background to be displayed while scaling.
                if (requiresBackgroundVisible)
                {
                    if (backgroundStack == null)
                    {
                        AddInternal(backgroundStack = new BackgroundScreenStack
                        {
                            Colour = OsuColour.Gray(0.1f),
                            Alpha  = 0,
                            Depth  = float.MaxValue
                        });

                        backgroundStack.Push(new ScalingBackgroundScreen());
                    }

                    backgroundStack.FadeIn(duration);
                }
                else
                {
                    backgroundStack?.FadeOut(duration);
                }
            }

            RectangleF targetRect = new RectangleF(Vector2.Zero, Vector2.One);

            if (customRect != null)
            {
                sizableContainer.RelativePositionAxes = customRectIsRelativePosition ? Axes.Both : Axes.None;

                targetRect = customRect.Value;
            }
            else if (targetMode == null || scalingMode.Value == targetMode)
            {
                sizableContainer.RelativePositionAxes = Axes.Both;

                Vector2 scale = new Vector2(sizeX.Value, sizeY.Value);
                Vector2 pos   = new Vector2(posX.Value, posY.Value) * (Vector2.One - scale);

                targetRect = new RectangleF(pos, scale);
            }

            bool requiresMasking = targetRect.Size != Vector2.One
                                   // For the top level scaling container, for now we apply masking if safe areas are in use.
                                   // In the future this can likely be removed as more of the actual UI supports overflowing into the safe areas.
                                   || (targetMode == ScalingMode.Everything && safeAreaPadding.Value.Total != Vector2.Zero);

            if (requiresMasking)
            {
                sizableContainer.Masking = true;
            }

            sizableContainer.MoveTo(targetRect.Location, duration, Easing.OutQuart);
            sizableContainer.ResizeTo(targetRect.Size, duration, Easing.OutQuart);

            // Of note, this will not work great in the case of nested ScalingContainers where multiple are applying corner radius.
            // Masking and corner radius should likely only be applied at one point in the full game stack to fix this.
            // An example of how this can occur is when the skin editor is visible and the game screen scaling is set to "Everything".
            sizableContainer.TransformTo(nameof(CornerRadius), requiresMasking ? corner_radius : 0, duration, requiresMasking ? Easing.OutQuart : Easing.None)
            .OnComplete(_ => { sizableContainer.Masking = requiresMasking; });
        }