/// <summary> /// Toggles the chat overlay on/off. /// </summary> public static void ToggleChatOverlay(bool forceOpen = false) { if (Dialog.JoinChannelDialog != null && Dialog.JoinChannelDialog.IsOnTop) { return; } if (OnlineManager.Connected && (KeyboardManager.IsUniqueKeyPress(Keys.F8) || forceOpen || KeyboardManager.IsUniqueKeyPress(Keys.Escape) && IsActive) || (!OnlineManager.Connected && IsActive) && TimeSinceLastActivated >= 450) { TimeSinceLastActivated = 0; IsActive = !IsActive; var targetX = IsActive ? 0 : -Dialog.DialogContainer.Width; Dialog.DialogContainer.Animations.Clear(); Dialog.DialogContainer.Animations.Add(new Animation(AnimationProperty.X, Easing.OutQuint, Dialog.DialogContainer.X, targetX, 600)); if (!IsActive) { Dialog.IsClickable = false; ThreadScheduler.RunAfter(() => { DialogManager.Dismiss(Dialog); }, 450); } else { Dialog.IsClickable = true; DialogManager.Show(Dialog); } } }
/// <summary> /// Closes the dialog. /// </summary> public void Close() { if (IsClosing) { return; } IsClosing = true; Animations.Clear(); Animations.Add(new Animation(AnimationProperty.Alpha, Easing.Linear, Alpha, 0f, 200)); ThreadScheduler.RunAfter(() => { lock (DialogManager.Dialogs) DialogManager.Dismiss(this); ButtonManager.Remove(this); IsClosing = false; var game = GameBase.Game as QuaverGame; var screen = game?.CurrentScreen as EditorScreen; var view = screen?.View as EditorScreenView; view.ControlBar.Parent = view.Container; }, 450); }
/// <summary> /// Called when /// </summary> public void OnClicked() { var screen = (DownloadScreen)Container.View.Screen; // On the very first click of this mapset, set the bindables value // so that the download status can be aware of this clicked on mapset. if (screen.SelectedMapset.Value != this) { screen.SelectedMapset.Value = this; return; } if (Download != null) { NotificationManager.Show(NotificationLevel.Error, "This mapset is already downloading!"); return; } screen.SelectedMapset.Value = null; // Begin downloading the map. Download = MapsetDownloadManager.Download(Mapset); if (Download == null) { return; } // Update the progress bar Download.Progress.ValueChanged += (o, e) => Progress.Bindable.Value = e.Value.ProgressPercentage; // Handle download completions. Download.Completed.ValueChanged += (o, e) => { if (e.Value.Cancelled) { NotificationManager.Show(NotificationLevel.Info, $"Cancelled download for mapset: {MapsetId}!"); } else if (e.Value.Error == null) { NotificationManager.Show(NotificationLevel.Success, $"Downloaded: {Mapset["artist"]} - {Mapset["title"]}!"); // Animate it off-screen MoveToX(-Width, Easing.OutQuint, 400); // Remove the mapset from the list and destroy it. Container.Mapsets.Remove(this); ThreadScheduler.RunAfter(Destroy, 450); Container.RealignMapsets(); } else { NotificationManager.Show(NotificationLevel.Error, $"An error has occurred while downloading: {MapsetId}."); } }; }
/// <summary> /// Closes the dialog. /// </summary> private void Close() { if (isClosing) { return; } isClosing = true; InterfaceContainer.Animations.Clear(); InterfaceContainer.Animations.Add(new Animation(AnimationProperty.Y, Easing.OutQuint, InterfaceContainer.Y, InterfaceContainer.Height, 600)); ThreadScheduler.RunAfter(() => DialogManager.Dismiss(this), 450); }
/// <inheritdoc /> /// <summary> /// </summary> public OffsetCalibratorTip() { Tint = Color.Black; Size = new ScalableVector2(WindowManager.Width, 100); Alpha = 0; SetChildrenAlpha = true; FadeTo(0.85f, Easing.Linear, 400); Animations.Add(new Animation(AnimationProperty.Wait, Easing.Linear, 0, 1, 2000)); // ReSharper disable once ObjectCreationAsStatement new Sprite { Parent = this, Size = new ScalableVector2(Width, 2), Tint = Colors.MainAccent }; Icon = new Sprite { Parent = this, Alignment = Alignment.TopCenter, Image = FontAwesome.Get(FontAwesomeIcon.fa_information_button), Y = 18, Size = new ScalableVector2(24, 24) }; // ReSharper disable once ObjectCreationAsStatement var text = new SpriteTextBitmap(FontsBitmap.AllerRegular, "Play through the map, and at the end, a new global audio offset will be suggested to you.") { Parent = this, FontSize = 20, Y = Icon.Y + Icon.Height + 15, Alignment = Alignment.TopCenter }; // ReSharper disable once ObjectCreationAsStatement new Sprite { Parent = this, Size = new ScalableVector2(Width, 2), Tint = Colors.MainAccent, Alignment = Alignment.BotLeft }; ThreadScheduler.RunAfter(() => { ClearAnimations(); text.Visible = false; FadeTo(0, Easing.Linear, 200); }, 3500); }
/// <summary> /// Closes the dialog. /// </summary> public void Close() { if (IsClosing) { return; } IsClosing = true; CreateGameInterface.Animations.Clear(); CreateGameInterface.MoveToX(-CreateGameInterface.Width - 2, Easing.OutQuint, 400); Alpha = 0f; ThreadScheduler.RunAfter(() => DialogManager.Dismiss(this), 450); }
/// <summary> /// Closes the dialog. /// </summary> public void Close() { if (IsClosing) { return; } IsClosing = true; MetadataChanger.Animations.Clear(); MetadataChanger.MoveToX(-MetadataChanger.Width - 2, Easing.OutQuint, 400); Animations.Clear(); Animations.Add(new Animation(AnimationProperty.Alpha, Easing.Linear, Alpha, 0f, 200)); ThreadScheduler.RunAfter(() => DialogManager.Dismiss(this), 450); }
/// <summary> /// Called every frame. Waits for a skin reload to be queued up. /// </summary> public static void HandleSkinReloading() { // Reload skin when applicable if (TimeSkinReloadRequested != 0 && GameBase.Game.TimeRunning - TimeSkinReloadRequested >= 400) { Load(); TimeSkinReloadRequested = 0; ThreadScheduler.RunAfter(() => { Transitioner.FadeOut(); NotificationManager.Show(NotificationLevel.Success, "Skin has been successfully loaded!"); }, 200); } }
/// <summary> /// Closes the JoinChannelDialog if it is already open. /// </summary> public void CloseJoinChannelDialog() { if (JoinChannelDialog == null) { return; } TimeSinceLastChannelDialogOpened = 0; JoinChannelDialog.InterfaceContainer.Animations.Clear(); JoinChannelDialog.InterfaceContainer.Animations.Add(new Animation(AnimationProperty.Y, Easing.OutQuint, JoinChannelDialog.InterfaceContainer.Y, JoinChannelDialog.InterfaceContainer.Height, 600)); ThreadScheduler.RunAfter(() => DialogManager.Dismiss(JoinChannelDialog), 450); }
/// <summary> /// Called every frame. Waits for a skin reload to be queued up. /// </summary> private void HandleSkinReloading() { // Reload skin when applicable if (TimeSkinReloadRequested != 0 && GameBase.Game.TimeRunning - TimeSkinReloadRequested >= 400) { SkinManager.Load(); NewQueuedSkin = null; TimeSkinReloadRequested = 0; IsGloballyClickable = true; ThreadScheduler.RunAfter(() => { Transitioner.FadeOut(); NotificationManager.Show(NotificationLevel.Success, "Skin has been successfully loaded!"); }, 200); } }
/// <summary> /// Queues a load of the background for a map /// </summary> public static void Load(Map map) => ThreadScheduler.Run(async() => { Source.Cancel(); Source.Dispose(); Source = new CancellationTokenSource(); Map = map; var token = Source.Token; token.ThrowIfCancellationRequested(); try { var oldRawTexture = RawTexture; var oldBlurredTexture = BlurredTexture; var path = MapManager.GetBackgroundPath(map); var tex = File.Exists(path) ? AssetLoader.LoadTexture2DFromFile(path) : UserInterface.MenuBackgroundRaw; RawTexture = tex; ThreadScheduler.RunAfter(() => { if (oldRawTexture != null && oldRawTexture != UserInterface.MenuBackgroundRaw) { oldRawTexture?.Dispose(); oldBlurredTexture?.Dispose(); } }, 500); token.ThrowIfCancellationRequested(); await Task.Delay(100, token); ShouldBlur = true; Loaded?.Invoke(typeof(BackgroundHelper), new BackgroundLoadedEventArgs(map, tex)); } catch (OperationCanceledException e) { // ignored } catch (Exception e) { Logger.Error(e, LogType.Runtime); } });
/// <summary> /// Closes the dialog. /// </summary> public void Close() { if (IsClosing) { return; } IsClosing = true; Animations.Clear(); Animations.Add(new Animation(AnimationProperty.Alpha, Easing.Linear, Alpha, 0f, 200)); ThreadScheduler.RunAfter(() => { lock (DialogManager.Dialogs) DialogManager.Dismiss(this); ButtonManager.Remove(this); IsClosing = false; }, 450); }
/// <inheritdoc /> /// <summary> /// </summary> /// <param name="container"></param> /// <param name="game"></param> public DrawableMultiplayerGameButton(LobbyMatchScrollContainer container, DrawableMultiplayerGame game) : base(UserInterface.BlankBox) { Container = container; Game = game; Tint = Color.Black; Size = new ScalableVector2(game.Width, game.HEIGHT * 0.95f); Alignment = Alignment.MidLeft; UsePreviousSpriteBatchOptions = true; Clicked += (o, e) => { if (game.Item.HasPassword) { DialogManager.Show(new JoinPasswordedGameDialog(game.Item)); } else { DialogManager.Show(new JoiningGameDialog(JoiningGameDialogType.Joining)); ThreadScheduler.RunAfter(() => OnlineManager.Client.JoinGame(game.Item), 800); } }; }
/// <summary> /// </summary> public static void ExportToZip() { MapManager.Selected.Value.Mapset.ExportToZip(); ThreadScheduler.RunAfter(() => NotificationManager.Show(NotificationLevel.Success, "Successfully exported mapset!"), 100); }
/// <inheritdoc /> /// <summary> /// </summary> public sealed override void CreateContent() { var background = new Sprite { Parent = this, Alignment = Alignment.MidCenter, Tint = Color.Black, Size = new ScalableVector2(WindowManager.Width, 150), Alpha = 0, SetChildrenAlpha = true }; background.FadeTo(1, Easing.Linear, 150); // ReSharper disable once ObjectCreationAsStatement new Wobble.Graphics.Sprites.Sprite { Parent = background, Size = new ScalableVector2(Width, 2), Tint = Colors.MainAccent, Alpha = 0 }; var icon = new Sprite { Parent = background, Alignment = Alignment.TopCenter, Image = FontAwesome.Get(FontAwesomeIcon.fa_information_button), Y = 18, Size = new ScalableVector2(24, 24) }; // ReSharper disable once ObjectCreationAsStatement var text = new SpriteTextBitmap(FontsBitmap.AllerRegular, "Please enter the password to join this multiplayer game.") { Parent = background, FontSize = 20, Y = icon.Y + icon.Height + 15, Alignment = Alignment.TopCenter, Alpha = 1 }; // ReSharper disable once ObjectCreationAsStatement new Sprite { Parent = background, Size = new ScalableVector2(Width, 2), Tint = Colors.MainAccent, Alignment = Alignment.BotLeft }; PasswordBox = new Textbox(new ScalableVector2(392, 36), Fonts.SourceSansProSemiBold, 13, "", "Enter Password", (pw) => { if (pw.Length == 0) { NotificationManager.Show(NotificationLevel.Error, "You need to enter a valid password"); return; } DialogManager.Dismiss(this); DialogManager.Show(new JoiningGameDialog(JoiningGameDialogType.Joining)); ThreadScheduler.RunAfter(() => OnlineManager.Client.JoinGame(Game, pw), 800); }) { Parent = background, Alignment = Alignment.TopCenter, Y = text.Y + text.Height + 15, Image = UserInterface.SelectSearchBackground, Alpha = 0.65f, AlwaysFocused = true }; PasswordBox.InputText.Alignment = Alignment.MidLeft; PasswordBox.Cursor.Alignment = Alignment.MidLeft; PasswordBox.AddBorder(Color.White, 2); }
/// <summary> /// Closes the dialog. /// </summary> public void Close(bool changeMods = true) { if (isClosing) { return; } if (OnlineManager.CurrentGame != null && changeMods) { if (ModsWhenDialogOpen != ModManager.Mods) { var diffRating = OnlineManager.CurrentGame.DifficultyRating; // Only update the difficulty rating when closing if the selected map is still the same. // If the user switches maps, but changes modifiers, it'll be incorrect. if (MapManager.Selected.Value != null && MapManager.Selected.Value.Md5Checksum == OnlineManager.CurrentGame.MapMd5) { diffRating = MapManager.Selected.Value.DifficultyFromMods(ModManager.Mods); } var rateNow = ModHelper.GetRateFromMods(ModManager.Mods); // Change the global mods of the game var rateMod = (long)ModHelper.GetModsFromRate(rateNow); if (rateMod == -1) { rateMod = 0; } var activeModsWithoutRate = (long)ModManager.Mods - rateMod; ModIdentifier hostOnlyMods = 0L; var onlyHostChangeableMods = ModManager.CurrentModifiersList.FindAll(x => x.OnlyMultiplayerHostCanCanChange); if (onlyHostChangeableMods.Count != 0) { onlyHostChangeableMods.ForEach(x => { // ReSharper disable once AccessToModifiedClosure activeModsWithoutRate -= (long)x.ModIdentifier; hostOnlyMods |= x.ModIdentifier; }); } if (activeModsWithoutRate == -1) { activeModsWithoutRate = 0; } // If we're on regular free mod mode, when we change the rate, // ReSharper disable once CompareOfFloatsByEqualityOperator if (OnlineManager.CurrentGame.FreeModType == MultiplayerFreeModType.Regular && (ModHelper.GetRateFromMods(ModsWhenDialogOpen) != rateNow || hostOnlyMods != 0) && OnlineManager.CurrentGame.Host == OnlineManager.Self.OnlineUser) { OnlineManager.Client?.MultiplayerChangeGameModifiers(rateMod + (long)hostOnlyMods, diffRating); // Change the mods of ourselves minus the mods rate (gets all other activated modes) OnlineManager.Client?.MultiplayerChangePlayerModifiers(activeModsWithoutRate); } // Free mod is enabled, but we haven't done any rate changing, so just // enable player modifiers for us else if (OnlineManager.CurrentGame.FreeModType != MultiplayerFreeModType.None) { // Free Mod + Free Rate if (OnlineManager.CurrentGame.FreeModType.HasFlag(MultiplayerFreeModType.Regular) && OnlineManager.CurrentGame.FreeModType.HasFlag(MultiplayerFreeModType.Rate)) { if (OnlineManager.CurrentGame.Host == OnlineManager.Self.OnlineUser) { OnlineManager.Client?.MultiplayerChangeGameModifiers((long)hostOnlyMods, diffRating); } OnlineManager.Client?.MultiplayerChangePlayerModifiers((long)ModManager.Mods); } // Either Free Mod OR Free Rate else { switch (OnlineManager.CurrentGame.FreeModType) { case MultiplayerFreeModType.Regular: OnlineManager.Client?.MultiplayerChangePlayerModifiers(activeModsWithoutRate); if (OnlineManager.CurrentGame.Host == OnlineManager.Self.OnlineUser) { OnlineManager.Client?.MultiplayerChangeGameModifiers(rateMod + (long)hostOnlyMods, diffRating); } break; case MultiplayerFreeModType.Rate: OnlineManager.Client?.MultiplayerChangePlayerModifiers((long)ModHelper.GetModsFromRate(rateNow)); if (OnlineManager.CurrentGame.Host == OnlineManager.Self.OnlineUser) { OnlineManager.Client?.MultiplayerChangeGameModifiers(activeModsWithoutRate + (long)hostOnlyMods, diffRating); } break; } } } // We're host & free mod isn't enabled, so change the global game mods else if (OnlineManager.CurrentGame.Host == OnlineManager.Self.OnlineUser) { OnlineManager.Client?.MultiplayerChangeGameModifiers((long)ModManager.Mods, diffRating); } } } isClosing = true; InterfaceContainer.Animations.Clear(); InterfaceContainer.Animations.Add(new Animation(AnimationProperty.Y, Easing.OutQuint, InterfaceContainer.Y, InterfaceContainer.Height, 600)); ThreadScheduler.RunAfter(() => DialogManager.Dismiss(this), 450); }
/// <summary> /// Closes the chat channel. /// </summary> public void CloseActiveChatChannel() { var channelButton = Overlay.ChatChannelList.SelectedButton; // For public channels, request to leave the chat channel. if (!Overlay.ActiveChannel.IsPrivate) { if (ChatManager.JoinedChatChannels.Any(x => x.Name == Overlay.ActiveChannel.Name)) { OnlineManager.Client.LeaveChatChannel(Overlay.ActiveChannel); } } var tfX = new Animation(AnimationProperty.X, Easing.Linear, channelButton.X, -(channelButton.Width + 5), 100); channelButton.Animations.Add(tfX); // Check to see if there is another button before this one. var buttonIndex = Overlay.ChatChannelList.Buttons.FindIndex(x => x == channelButton); // Remove the button from the list of chat channel buttons. Overlay.ChatChannelList.Buttons.Remove(channelButton); // Remove the channel from the joined chat channels. ChatManager.JoinedChatChannels.Remove(Overlay.ActiveChannel); // Remove the chat channel container var messageContainer = Overlay.ChannelMessageContainers[Overlay.ActiveChannel]; Overlay.ChannelMessageContainers.Remove(Overlay.ActiveChannel); // Destroy the container instantly. messageContainer.Destroy(); // Make sure the buttons are realigned properly after closing this channel. Overlay.ChatChannelList.RealignButtons(); // Destroy the button after it finishes its Animation. ThreadScheduler.RunAfter(() => channelButton.Destroy(), 150); // Automatically select the button behind it. if it exists. if (buttonIndex != -1 && buttonIndex - 1 >= 0) { Overlay.ChatChannelList.Buttons[buttonIndex - 1].SelectChatChannel(); } // If theres still more buttons ahead, then we want to switch to the first one. // This is to handle the case of if the user closes the first channel in the list. else if (Overlay.ChatChannelList.Buttons.Count > 0) { Overlay.ChatChannelList.Buttons.First().SelectChatChannel(); } // No channels exist anymore. else { Overlay.ChatChannelList.SelectedButton = null; Overlay.ActiveChannel = null; UpdateTopicText(); Overlay.NoChannelMessageContainer.Visible = true; } Logger.Debug($"Closed chat channel: `{channelButton.Channel.Name}`", LogType.Runtime); }