// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. #nullable disable using System; using System.Collections.Generic; using osu.Framework.Configuration; using osu.Framework.Configuration.Tracking; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Transforms; using osu.Framework.Threading; using osu.Game.Overlays.OSD; using osuTK; namespace osu.Game.Overlays { /// /// An on-screen display which automatically tracks and displays toast notifications for . /// Can also display custom content via /// public partial class OnScreenDisplay : Container { private readonly Container box; private const float height = 110; private const float height_contracted = height * 0.9f; public OnScreenDisplay() { RelativeSizeAxes = Axes.Both; Children = new Drawable[] { box = new Container { Origin = Anchor.Centre, RelativePositionAxes = Axes.Both, Position = new Vector2(0.5f, 0.75f), Masking = true, AutoSizeAxes = Axes.X, Height = height_contracted, Alpha = 0, CornerRadius = 20, }, }; } private readonly Dictionary<(object, IConfigManager), TrackedSettings> trackedConfigManagers = new Dictionary<(object, IConfigManager), TrackedSettings>(); /// /// Registers a to have its settings tracked by this . /// /// The object that is registering the to be tracked. /// The to be tracked. /// If is null. /// If is already being tracked from the same . public void BeginTracking(object source, ITrackableConfigManager configManager) { ArgumentNullException.ThrowIfNull(configManager); if (trackedConfigManagers.ContainsKey((source, configManager))) throw new InvalidOperationException($"{nameof(configManager)} is already registered."); var trackedSettings = configManager.CreateTrackedSettings(); if (trackedSettings == null) return; configManager.LoadInto(trackedSettings); trackedSettings.SettingChanged += displayTrackedSettingChange; trackedConfigManagers.Add((source, configManager), trackedSettings); } /// /// Unregisters a from having its settings tracked by this . /// /// The object that registered the to be tracked. /// The that is being tracked. /// If is null. /// If is not being tracked from the same . public void StopTracking(object source, ITrackableConfigManager configManager) { ArgumentNullException.ThrowIfNull(configManager); if (!trackedConfigManagers.TryGetValue((source, configManager), out var existing)) return; existing.Unload(); existing.SettingChanged -= displayTrackedSettingChange; trackedConfigManagers.Remove((source, configManager)); } /// /// Displays the provided temporarily. /// /// public void Display(Toast toast) => Schedule(() => { box.Child = toast; DisplayTemporarily(box); }); private void displayTrackedSettingChange(SettingDescription description) => Scheduler.AddOnce(Display, new TrackedSettingToast(description)); private TransformSequence fadeIn; private ScheduledDelegate fadeOut; protected virtual void DisplayTemporarily(Drawable toDisplay) { // avoid starting a new fade-in if one is already active. if (fadeIn == null) { fadeIn = toDisplay.Animate( b => b.FadeIn(500, Easing.OutQuint), b => b.ResizeHeightTo(height, 500, Easing.OutQuint) ); fadeIn.Finally(_ => fadeIn = null); } fadeOut?.Cancel(); fadeOut = Scheduler.AddDelayed(() => { toDisplay.Animate( b => b.FadeOutFromOne(1500, Easing.InQuint), b => b.ResizeHeightTo(height_contracted, 1500, Easing.InQuint)); }, 500); } } }