Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #region Using Statements
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Drawing;
- using System.Globalization;
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Threading;
- using System.Windows.Forms;
- using Microsoft.Win32;
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- using Microsoft.Xna.Framework.Input;
- using osu.Audio;
- using osu.Configuration;
- using osu.GameModes.Edit;
- using osu.GameModes.Edit.Forms;
- using osu.GameModes.Menus;
- using osu.GameModes.Online;
- using osu.GameModes.Options;
- using osu.GameModes.Play;
- using osu.GameModes.Ranking;
- using osu.GameModes.Select;
- using osu.GameplayElements;
- using osu.GameplayElements.Beatmaps;
- using osu.GameplayElements.Scoring;
- using osu.Graphics;
- using osu.Graphics.Notifications;
- using osu.Graphics.OpenGl;
- using OpenTK.Graphics.ES20;
- using osu.Graphics.Primitives;
- using osu.Graphics.Renderers;
- using osu.Graphics.Skinning;
- using osu.Graphics.Sprites;
- using osu.Graphics.UserInterface;
- using osu.Helpers;
- using osu.Helpers.Forms;
- using osu.Input;
- using osu.Input.Handlers;
- using osu.Online;
- using osu.Online.Drawable;
- using osu_common;
- using osu_common.Helpers;
- using osudata;
- using Un4seen.Bass;
- using Color = Microsoft.Xna.Framework.Graphics.Color;
- using Keys = Microsoft.Xna.Framework.Input.Keys;
- using Menu = osu.GameModes.Menus.Menu;
- using Point = Microsoft.Xna.Framework.Point;
- using Rectangle = Microsoft.Xna.Framework.Rectangle;
- using System.Security;
- using ICSharpCode.SharpZipLib.Zip;
- using System.Net.NetworkInformation;
- using System.Security.Principal;
- using System.Security.AccessControl;
- using osu.GameModes.Play.Rulesets.Mania;
- using System.Drawing.Imaging;
- using osu.Framework;
- using osu.GameModes.Play.Components;
- using osu_common.Updater;
- using osu.Graphics.Tips;
- using osu.Online.Social;
- using osu.GameModes;
- using PixelFormat = System.Drawing.Imaging.PixelFormat;
- using osu.GameModes.Other.Drawings;
- using osu.Graphics.Shaders;
- using OpenTK.Graphics;
- using osu.GameModes.Other.Tournament;
- using Amib.Threading;
- using osu.Framework.GLControl;
- #endregion
- namespace osu
- {
- public partial class GameBase : Game
- {
- #region General
- private static ChatEngine chatEngine;
- private static List<pDialog> DialogQueue = new List<pDialog>();
- internal static EditorControl EditorControl;
- internal static WindowsGameForm Form => (Instance?.Window as WindowsGameWindow)?.Form;
- private static NotifyIcon notifyIcon;
- private const double FrameAimTime = (double)1000 / 60;
- /// <summary>
- /// The time a frame took to draw compared to 60fps standard.
- /// </summary>
- internal static double FrameRatio;
- internal static GameBase Instance;
- internal static bool IsMinimized;
- internal static LineManager LineManager;
- internal static bool MenuVisible;
- internal BackgroundAppDetector BackgroundAppDetector;
- internal DataStoreUpdater DataStoreUpdater;
- internal static int MenuHeight
- {
- get
- {
- return MenuVisible ? EditorControl.Height : 0;
- }
- }
- internal static readonly NumberFormatInfo nfi = new CultureInfo(@"en-US", false).NumberFormat;
- internal static int PixelShaderVersion;
- internal static PrimitiveBatch LineBatch;
- internal static pSprite s_fadeScreen;
- internal const double SIXTY_FRAME_TIME = (double)1000 / 60;
- internal double FrameLimitMillisecondsPerFrame
- {
- get
- {
- return 1000d / TargetFrameRate;
- }
- }
- internal static double TargetFrameRate
- {
- get
- {
- double result = 60;
- switch (ConfigManager.sFrameSync.Value)
- {
- case FrameSync.Custom:
- result = ConfigManager.sCustomFrameLimit.Value;
- break;
- case FrameSync.Unlimited:
- case FrameSync.CompletelyUnlimited:
- // With gameplay unlimited we want to have at _least_ the user-specified CustomFrameLimit outside of gameplay, or the monitor refresh (whichever is higher).
- result = Mode == OsuModes.Play && !Player.Paused ? Double.PositiveInfinity : Math.Max(RefreshRate, ConfigManager.sCustomFrameLimit.Value);
- #if !Public
- if (KeyboardHandler.AltPressed)
- result = Double.PositiveInfinity;
- #endif
- break;
- case FrameSync.Limit120:
- result = 120;
- break;
- // With VSync on the refresh rate is controlled by the graphics API, so this member variable shouldn't limit the frame rate in any way
- case FrameSync.VSync:
- result = Double.PositiveInfinity;
- break;
- }
- if (CanRunSlowly)
- {
- if (IsMinimized)
- result = Math.Min(15, result);
- else if (!Instance.IsActive)
- result = Math.Min(30, result);
- else
- result = Math.Min(RefreshRate, result);
- }
- Debug.Assert(result > 0);
- return result;
- }
- }
- internal static bool SixtyFramesPerSecondFrame;
- internal static double SixtyFramesPerSecondLength;
- internal static SpriteManager spriteManager;
- internal static SpriteManager spriteManagerCursor;
- internal static CursorTrailRenderer cursorTrailRenderer;
- internal static SpriteManager spriteManagerOverlay;
- internal static SpriteManager spriteManagerOverlayHighest;
- internal static SpriteManager spriteManagerTransition;
- internal static SpriteManager spriteManagerHighest;
- internal static Stopwatch stopWatch = new Stopwatch();
- internal static int Time;
- internal static pTexture WhitePixel;
- internal static bool PendingModeChange = true;
- internal static double TimeAccurateLastUpdate;
- private static double SixtyFrameLast;
- internal static double TimeAccurate;
- private static double AccumulatedSleepError;
- internal FpsDisplay FpsDisplay;
- internal static OnScreenDisplay OnScreenDisplay;
- internal static FrameTimeDisplay FrameTimeDisplay;
- internal static PerformanceMonitor PerformanceMonitor;
- internal static PhysicsManager PhysicsManager = new PhysicsManager();
- internal static BanchoStatusOverlay BanchoStatus;
- internal static VolumeControlSet Volume;
- /// <summary>
- /// This client is in Tournament mode.
- /// </summary>
- internal static bool Tournament;
- /// <summary>
- /// Special client for managing other tournament clients.
- /// </summary>
- internal static bool TournamentManager;
- /// <summary>
- /// Special tournament client for team drawings.
- /// </summary>
- internal static bool TournamentDrawings;
- internal static short TournamentClientId;
- internal static pText TourneySpectatorName;
- internal static bool TournamentBuffering;
- internal static bool TournamentSkipCalculations;
- internal static CoinsOverlay Coins;
- internal static TransitionManager TransitionManager;
- internal static double ModeTime;
- internal static string EXPORT_FOLDER => Path.Combine(OsuMain.UserPath, @"Exports");
- internal GameBase(string startupFile)
- : base(ConfigManager.sCompatibilityContext ? GraphicsContextFlags.Angle : GraphicsContextFlags.Default)
- {
- Instance = this;
- StartupNewFiles = startupFile;
- Application.EnableVisualStyles();
- Mouse.WindowHandle = Window.Handle;
- OpenTK.NativeWindow.OsuWindowHandle = Window.Handle;
- string exeName = Environment.CurrentDirectory + @"\" + Process.GetCurrentProcess().ProcessName.Replace(@".vshost", string.Empty) + @".exe";
- try
- {
- Form.Icon = Icon.ExtractAssociatedIcon(exeName);
- }
- catch
- {
- }
- Form.AllowDrop = true;
- Form.FormClosing += Form_FormClosing;
- Form.DragEnter += Form_DragEnter;
- Form.DragDrop += Form_DragDrop;
- Deactivated += Form_Deactivate;
- Activated += Form_Activated;
- FadeOutComplete += delegate { loadQueuedMode(0); };
- MainThread = Thread.CurrentThread;
- //If we have failed to update more than five times in a row, let's force an update.
- if (ConfigManager.sUpdateFailCount >= 5)
- {
- SplashScreen.CloseAll();
- ConfigManager.sUpdateFailCount.Value = 0;
- ConfigManager.SaveConfig();
- OsuMain.Repair();
- }
- LocalisationManager.SetLanguage(ConfigManager.sLanguage, ConfigManager.sLastVersion != General.BUILD_NAME, delegate
- {
- if (GameBase.Time > 0)
- {
- Scheduler.AddDelayed(delegate
- {
- ConfigManager.sLanguage.Value = LocalisationManager.CurrentLanguage;
- }, Math.Max(0, (Menu.IntroLength + 500) - GameBase.Time));
- return;
- }
- ConfigManager.sLanguage.Value = LocalisationManager.CurrentLanguage;
- }, osu.Properties.Resources.en);
- InitialDesktopResolution = ResolutionHelper.GetDesktopResolution();
- InitialDesktopLocation = ResolutionHelper.GetDesktopPosition();
- InitialRefreshRate = ResolutionHelper.GetCurrentRefreshRate();
- WindowManager = new WindowManager();
- KeyboardState keyState = Keyboard.GetState();
- if (keyState.IsKeyDown(Keys.LeftShift) || keyState.IsKeyDown(Keys.RightShift) || (OsuMain.Args.Length > 1 && OsuMain.Args[1] == @"-config"))
- {
- Helpers.Forms.Configuration configForm = new Helpers.Forms.Configuration();
- configForm.ShowDialog();
- }
- GameField = new GameField(WindowManager);
- InitializeSound();
- Native.SetThreadExecutionState(Native.ExecutionState.Continuous | Native.ExecutionState.SystemRequired | Native.ExecutionState.DisplayRequired);
- }
- internal delegate string DllRegisterServerInvoker();
- internal static void InitializeSound()
- {
- AudioEngine.SetAudioDevice(ConfigManager.sAudioDevice.Value);
- if (Tournament)
- AudioEngine.VolumeMaster.Value = 0;
- }
- internal static bool TopMost
- {
- get
- {
- return
- // We can only be topmost if we are active and not in the editor showing the menu. Otherwise osu! shouldn't steal the show from other programs
- (GameBase.Instance.IsActive && !GameBase.MenuVisible && GameBase.IsFullscreen)
- //Tournament clients should always be topmost
- || (Tournament && !TournamentManager);
- }
- }
- internal static bool MenuActive
- {
- get { return localMenuActive; }
- set
- {
- if (localMenuActive == value) return;
- localMenuActive = value;
- MouseManager.UpdateMouseCursorVisibility();
- MouseManager.ResetStatus();
- }
- }
- private static int bossKeyRestoreVolume = 0;
- internal static bool OnKeyPressed(object sender, Keys k)
- {
- Bindings bind = BindingManager.CheckKey(k);
- #if DEBUG
- if (SpriteManager.Placement && SpriteManager.ClickHandledSprite != null)
- {
- float increment = 1;
- if (KeyboardHandler.ShiftPressed)
- increment /= 5f;
- else if (KeyboardHandler.ControlPressed)
- increment *= 5f;
- pSprite p = SpriteManager.ClickHandledSprite;
- pText pt = p as pText;
- switch (k)
- {
- case Keys.Left:
- p.Position.X -= increment;
- break;
- case Keys.Right:
- p.Position.X += increment;
- break;
- case Keys.Up:
- p.Position.Y -= increment;
- break;
- case Keys.Down:
- p.Position.Y += increment;
- break;
- case Keys.Z:
- if (pt != null)
- pt.TextSize -= increment;
- else
- p.Scale -= increment / 100f;
- break;
- case Keys.X:
- if (pt != null)
- pt.TextSize += increment;
- else
- p.Scale += increment / 100f;
- break;
- case Keys.H:
- p.Bypass = !p.Bypass;
- break;
- }
- }
- #endif
- switch (bind)
- {
- case Bindings.Screenshot:
- Screenshot.TakeScreenshot(KeyboardHandler.ShiftPressed);
- return true;
- case Bindings.DisableMouseButtons:
- ConfigManager.sMouseDisableButtons.Toggle();
- NotificationManager.ShowMessageMassive("Mouse buttons are " + (ConfigManager.sMouseDisableButtons ? "disabled" : "enabled") + @".", 1000);
- return true;
- case Bindings.ToggleFrameLimiter:
- switch (ConfigManager.sFrameSync.Value)
- {
- case FrameSync.VSync:
- ConfigManager.sFrameSync.Value = FrameSync.Limit120;
- break;
- case FrameSync.Limit120:
- ConfigManager.sFrameSync.Value = FrameSync.Custom;
- break;
- case FrameSync.Custom:
- ConfigManager.sFrameSync.Value = FrameSync.Unlimited;
- break;
- case FrameSync.Unlimited:
- default:
- ConfigManager.sFrameSync.Value = FrameSync.Limit120;
- break;
- }
- return true;
- case Bindings.BossKey:
- MinimizedToTray = true;
- return true;
- }
- switch (k)
- {
- case Keys.O:
- if (KeyboardHandler.ControlPressed && !KeyboardHandler.AltPressed && Options.CanExpand)
- {
- Options.LoginOnly = false;
- Options.Expanded = true;
- return true;
- }
- break;
- case Keys.Enter:
- if (KeyboardHandler.AltPressed)
- {
- switch (Mode)
- {
- case OsuModes.Menu:
- case OsuModes.SelectPlay:
- case OsuModes.Lobby:
- ConfigManager.sFullscreen.Toggle();
- return true;
- }
- return false;
- }
- break;
- case Keys.S:
- if (KeyboardHandler.ShiftPressed && KeyboardHandler.AltPressed && KeyboardHandler.ControlPressed)
- {
- GameBase.OnNextModeChange += delegate {
- NotificationManager.ShowMessageMassive("Skin reloaded!", 2000);
- SkinManager.LoadSkin(null, true);
- TextureManager.Reload();
- };
- if (ModeCanReload)
- GameBase.ChangeMode(GameBase.Mode, true);
- else
- NotificationManager.ShowMessageMassive("Skin reload queued.", 2000);
- return true;
- }
- break;
- case Keys.R:
- if (KeyboardHandler.ControlPressed && Tournament)
- {
- User u = StreamingManager.CurrentlySpectating;
- if (u == null)
- u = BanchoClient.GetUserByName(TourneySpectatorName.Text);
- if (u != null)
- {
- StreamingManager.StopSpectating(true);
- StreamingManager.StartSpectating(u);
- }
- }
- break;
- case Keys.F11:
- if (KeyboardHandler.ControlPressed)
- {
- ConfigManager.sFrameTimeDisplay.Value = !ConfigManager.sFrameTimeDisplay.Value;
- NotificationManager.ShowMessage("Frame times are now " + (ConfigManager.sFrameTimeDisplay.Value ? "visible" : "hidden") + ". Press Ctrl+F11 to toggle.");
- return true;
- }
- else if (OnScreenDisplay != null)
- {
- OnScreenDisplay.ToggleShow();
- return true;
- }
- break;
- #if DEBUG
- case Keys.D0:
- if (KeyboardHandler.ControlPressed)
- {
- BanchoClient.SwitchServer();
- return true;
- }
- break;
- case Keys.G:
- if (KeyboardHandler.ControlPressed)
- GC.Collect();
- break;
- #endif
- }
- return false;
- }
- static int owcCount = 0;
- private static void Form_DragDrop(object sender, DragEventArgs e)
- {
- try
- {
- Array a = (Array)e.Data.GetData(DataFormats.FileDrop);
- OsuModes gs = OsuModes.Unknown;
- if (a != null)
- {
- string[] files = new string[a.Length];
- for (int i = 0; i < a.Length; i++)
- files[i] = a.GetValue(i).ToString();
- gs = ReceiveFile(files);
- }
- else
- {
- string text = e.Data.GetData(DataFormats.Text) as string;
- if (text.StartsWith(@"http"))
- ChatEngine.HandleLink(text);
- else
- gs = ReceiveFile(text);
- }
- if (gs != OsuModes.Unknown)
- ChangeMode(gs, true);
- }
- catch (Exception)
- {
- }
- }
- private static void Form_DragEnter(object sender, DragEventArgs e)
- {
- bool isFile = e.Data.GetDataPresent(DataFormats.FileDrop);
- bool isUrl = e.Data.GetDataPresent(DataFormats.Text);
- e.Effect = isFile || isUrl ? DragDropEffects.Copy : DragDropEffects.None;
- }
- private void Form_Deactivate(object sender, EventArgs e)
- {
- Native.SetThreadExecutionState(Native.ExecutionState.Continuous);
- if (Tournament) return;
- if (Player.Playing && !InputManager.ReplayMode)
- {
- Form.BringToFront();
- Form.Focus();
- }
- }
- void Form_Activated(object sender, EventArgs e)
- {
- Native.SetThreadExecutionState(Native.ExecutionState.Continuous | Native.ExecutionState.SystemRequired | Native.ExecutionState.DisplayRequired);
- InputManager.LastActionTime = GameBase.Time;
- }
- private void Form_FormClosing(object sender, FormClosingEventArgs e)
- {
- if (ChatEngine.Visibility == ChatVisibility.Full)
- {
- ChatEngine.HideChat();
- e.Cancel = true;
- return;
- }
- switch (Mode)
- {
- case OsuModes.Rank:
- ChangeMode(OsuModes.SelectPlay);
- e.Cancel = true;
- return;
- case OsuModes.RankingVs:
- case OsuModes.RankingTeam:
- case OsuModes.RankingTagCoop:
- ChangeMode(OsuModes.MatchSetup);
- e.Cancel = true;
- return;
- case OsuModes.Edit:
- Editor editor = RunningGameMode as Editor;
- if (editor != null)
- editor.Exit();
- e.Cancel = true;
- return;
- case OsuModes.Play:
- StreamingManager.StopSpectating();
- if (RunningGameMode is PlayerVs)
- MatchSetup.LeaveGame();
- else if (TestMode)
- ChangeMode(OsuModes.Edit);
- else
- ChangeMode(OsuModes.SelectPlay);
- e.Cancel = true;
- return;
- case OsuModes.Lobby:
- case OsuModes.OnlineSelection:
- case OsuModes.OptionsOffsetWizard:
- ChangeMode(OsuModes.Menu);
- e.Cancel = true;
- return;
- case OsuModes.MatchSetup:
- ChangeMode(OsuModes.Lobby);
- e.Cancel = true;
- return;
- }
- if (Mode != OsuModes.Exit && Mode != OsuModes.Update)
- {
- BeginExit(false);
- //Sleepable = false;
- e.Cancel = true;
- }
- }
- internal static event VoidDelegate OnNextModeChange;
- internal static event VoidDelegate OnModeChange;
- internal static event VoidDelegate OnExitFade;
- private static event VoidDelegate exitAction;
- protected override void OnExiting(object sender, EventArgs args)
- {
- if (exitAction != null) exitAction();
- BanchoClient.Exit();
- ImHelper.SetAllMusic(false, string.Empty, string.Empty, string.Empty, string.Empty);
- if (Mode == OsuModes.Edit)
- {
- try
- {
- ((Editor)RunningGameMode).Exit();
- }
- catch (Exception)
- {
- }
- }
- DataStoreUpdater.Save();
- try
- {
- if (Mode == OsuModes.Play && !InputManager.ReplayMode)
- Player.Instance.HandleScoreSubmission();
- }
- catch { }
- Screensaver.Restore();
- spriteManager.Dispose();
- spriteManagerOverlay.Dispose();
- spriteManagerOverlayHighest.Dispose();
- if (ConfigManager.sWiimote)
- WiimoteManager.Disconnect();
- Cursor.Show();
- Cursor.Clip = InputManager.CursorOriginalBounds;
- try
- {
- Directory.Delete(User.AvatarFilePath, true);
- }
- catch
- {
- }
- #if P2P
- Osup2pManager.Shutdown();
- #endif
- try
- {
- Bass.BASS_Free();
- }
- catch { }
- InputManager.Dispose();
- base.OnExiting(sender, args);
- }
- internal static event VoidDelegate OnResolutionChange;
- /// <summary>
- /// Uses a sledgehammer method to leave exclusive full screen mode forcibly. This messed up window borders and position and should only be used when absolutely necessary.
- /// </summary>
- private static void ForcefullyLeaveExclusiveFullscreen()
- {
- if (OsuGlControl.UsesAngle)
- GLControl.ToggleWindowed();
- else
- {
- System.Drawing.Point p = Form.Location;
- Form.Location = new System.Drawing.Point(p.X - 1, p.Y - 1);
- Form.FormBorderStyle = FormBorderStyle.FixedSingle;
- }
- }
- static VoidDelegate pendingScreenModeChange;
- internal static void SetScreenSize(int? width = null, int? height = null, bool saveToConfig = false, bool force = false)
- {
- try
- {
- if (width == WindowManager.Width && height == WindowManager.Height && !force) return;
- Instance.GlControl.VSync = ConfigManager.sFrameSync == FrameSync.VSync;
- UpdateDesktopProperties();
- if (pendingScreenModeChange == null && !PendingModeChange)
- {
- pendingScreenModeChange = delegate { SetScreenSize(width, height, saveToConfig, true); };
- ChangeMode(Mode, true);
- return;
- }
- bool wasFullscreen = IsFullscreen;
- IsFullscreen = ConfigManager.sFullscreen && !ForceNonExclusive;
- if (wasFullscreen && !IsFullscreen)
- ForcefullyLeaveExclusiveFullscreen();
- bool wasHighRes = UseHighResolutionSprites;
- if (width > 0 && height > 0)
- {
- //if width and height are specified, we should use them.
- WindowManager.Width = width.Value;
- WindowManager.Height = height.Value;
- if (saveToConfig)
- {
- if (ConfigManager.sFullscreen)
- {
- ConfigManager.sWidthFullscreen.Value = WindowManager.Width;
- ConfigManager.sHeightFullscreen.Value = WindowManager.Height;
- }
- else
- {
- ConfigManager.sWidth.Value = WindowManager.Width;
- ConfigManager.sHeight.Value = WindowManager.Height;
- }
- }
- }
- else
- {
- if (ConfigManager.sFullscreen)
- {
- WindowManager.Width = ConfigManager.sWidthFullscreen;
- WindowManager.Height = ConfigManager.sHeightFullscreen;
- }
- else
- {
- WindowManager.Width = ConfigManager.sWidth;
- WindowManager.Height = ConfigManager.sHeight;
- }
- if (WindowManager.Width == 9999 || WindowManager.Height == 9999)
- {
- //A fresh config file. Set some sane defaults based on the environment.
- if (ConfigManager.sFullscreen)
- {
- Size s = ResolutionHelper.FindNativeResolution();
- WindowManager.Width = ConfigManager.sWidthFullscreen.Value = s.Width;
- WindowManager.Height = ConfigManager.sHeightFullscreen.Value = s.Height;
- }
- else
- {
- WindowManager.Width = ConfigManager.sWidth.Value = InitialDesktopResolution.Width;
- WindowManager.Height = ConfigManager.sHeight.Value = InitialDesktopResolution.Height;
- }
- }
- }
- if (ConfigManager.sLetterboxing && (WindowManager.Width > InitialDesktopResolution.Width || WindowManager.Height > InitialDesktopResolution.Height))
- {
- ConfigManager.sLetterboxing.Value = false;
- return; // Changing the letterboxing setting will invoke SetScreenSize again, thus we can abort here.
- }
- if (ConfigManager.sFullscreen && !ConfigManager.sLetterboxing)
- {
- //check whether the full screen resolution we are about to enter is supported
- if (!ResolutionHelper.ChangeResolution(WindowManager.Width, WindowManager.Height, CustomRefreshRate, true))
- {
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.GameBase_ResolutionChangeFailed));
- ConfigManager.sOverrideRefreshRate.Value = false;
- if (!ResolutionHelper.ChangeResolution(WindowManager.Width, WindowManager.Height, null, true))
- {
- ConfigManager.sWidthFullscreen.Value = WindowManager.Width = InitialDesktopResolution.Width;
- ConfigManager.sHeightFullscreen.Value = WindowManager.Height = InitialDesktopResolution.Height;
- }
- }
- }
- WindowManager.Height -= MenuHeight;
- //limit the aspect ratio from being too square (just causes breaking).
- if (WindowManager.Height > WindowManager.Width * 0.8f) WindowManager.Height = (int)(WindowManager.Width * 0.8f);
- if (!IsFullscreen && AeroGlassHelper.DesktopCompositionEnabled)
- {
- Scheduler.AddDelayed(delegate
- {
- AeroGlassHelper.DisableGlass(Form);
- AeroGlassHelper.EnableGlass(Form);
- }, 250);
- }
- NativeText.ClearFontCache();
- InputManager.TextInput.Location = new System.Drawing.Point((int)(WindowManager.Width * 0.015), WindowManager.Height - (int)(WindowManager.Height * 0.052) + 2000);
- foreach (TextInputControl c in InputManager.TextInputControls)
- c.SetLocation();
- SkinManager.PrepareSliderRenderer();
- if (LastMode != OsuModes.Unknown && UseHighResolutionSprites != wasHighRes)
- TextureManager.Reload();
- if (EditorControl != null)
- EditorControl.Width = GameBase.InitialDesktopResolution.Width;
- if (s_fadeScreen != null)
- s_fadeScreen.VectorScale = new Vector2(WindowManager.Width, WindowManager.Height);
- GameField.Resize(GameBase.GameField.ScaleFactor, true);
- WindowRectangle = new Rectangle(-1 + WindowManager.NonWidescreenOffsetX, -1, WindowManager.Width - WindowManager.NonWidescreenOffsetX * 2 + 1, WindowManager.Height + 1);
- WindowRectangleWidescreen = new Rectangle(-1, -1, WindowManager.Width + 1, WindowManager.Height + 1);
- SpriteManager.ViewRectangleCurrent.Width = (int)Math.Ceiling(WindowManager.Width / WindowManager.Ratio);
- #if !Public
- if (testBuildOverlay != null)
- testBuildOverlay.VectorScale.X = Math.Max(1, (GameBase.WindowManager.Width / GameBase.WindowManager.RatioInverse) / testBuildOverlay.DrawWidth);
- #endif
- UpdateDesktopResolution();
- if (chatEngine != null) ChatEngine.OnResolutionChange();
- ResizeGL(ForceNonExclusive);
- if (OnResolutionChange != null)
- OnResolutionChange();
- }
- catch
- {
- ResizeGL(ForceNonExclusive);
- throw;
- }
- }
- private static int? CustomRefreshRate
- {
- get
- {
- if (ConfigManager.sOverrideRefreshRate.Value)
- return ConfigManager.sRefreshRate.Value;
- else
- return null;
- }
- }
- internal static void LetterboxPosition_ValueChanged(object sender, EventArgs e)
- {
- if (ConfigManager.sLetterboxing)
- {
- OsuGlControl.ResetViewport();
- UpdateClientBounds();
- }
- }
- private static void ResizeGL(bool forceNonExclusive)
- {
- //temporary hack to avoid running fullscreen when in editor
- int adjust = forceNonExclusive && !OsuGlControl.UsesAngle ? 1 : 0;
- if (ConfigManager.sLetterboxing)
- clientSize = new Size(InitialDesktopResolution.Width, InitialDesktopResolution.Height);
- else
- clientSize = new Size(WindowManager.Width, WindowManager.Height + MenuHeight);
- // This prevents exclusive fullscreen when we want to set a resolution equal to the current desktop resolution.
- Size currentResolution = ResolutionHelper.GetDesktopResolution();
- if (clientSize.Width == currentResolution.Width && clientSize.Height == currentResolution.Height)
- {
- clientSize.Height += adjust;
- ClientSizeAdjustment = adjust;
- }
- else
- {
- ClientSizeAdjustment = 0;
- }
- UpdateWindowBorders();
- OsuGlControl.ResetViewport();
- UpdateClientBounds();
- Form.ClientSize = clientSize;
- if (!GameBase.Tournament)
- {
- if (IsFillingScreen)
- Form.Location = InitialDesktopLocation;
- else if (Time == 0 || pendingScreenModeChange != null)
- //Center if this is the first initialized screen change, or a screen mode change is pending
- Form.CentreToScreen();
- }
- Form.Invalidate();
- }
- private static void UpdateWindowBorders()
- {
- if (IsFillingScreen)
- Form.FormBorderStyle = FormBorderStyle.None;
- else if (!Tournament)
- Form.FormBorderStyle = FormBorderStyle.FixedSingle;
- }
- private static void UpdateDesktopResolution()
- {
- if (ConfigManager.sFullscreen && !ConfigManager.sLetterboxing)
- ResolutionHelper.ChangeResolution(WindowManager.Width, WindowManager.Height + MenuHeight, CustomRefreshRate);
- else
- ResolutionHelper.ResetResolution();
- RefreshRate = ResolutionHelper.GetCurrentRefreshRate();
- }
- internal static int GetTime(Clocks clock)
- {
- switch (clock)
- {
- case Clocks.Audio:
- case Clocks.AudioOnce:
- return AudioEngine.Time;
- case Clocks.Game:
- return Time;
- }
- return 0;
- }
- internal static string ClientHash;
- protected override void Initialize()
- {
- if (!string.IsNullOrEmpty(ConfigManager.sUsername.Value))
- Logger.UserIdentifier = ConfigManager.sUsername.Value;
- Logger.VersionIdentifier = General.BUILD_NAME;
- OsuGlControl.InitializedEvent.WaitOne(5000);
- InitializeGl();
- LineBatch = new PrimitiveBatch(BeginMode.Lines);
- WhitePixel = pTexture.FromRawBytes(new byte[] { 255, 255, 255, 255 }, 1, 1);
- LineManager = new LineManager();
- #if DEBUG
- if (!Tournament || TournamentManager)
- {
- OnScreenDisplay = new OnScreenDisplay();
- }
- Debug.Print(@"Running on " + Environment.OSVersion);
- Debug.Print(@"Graphics mode: " + GlControl.GraphicsMode);
- #endif
- //Tourney Initialisation
- if (Tournament)
- {
- General.SUBVERSION = @"tourney";
- AudioEngine.VolumeMaster.Value = 35;
- AudioEngine.VolumeMusic.Value = TournamentManager ? 100 : 0;
- AudioEngine.VolumeEffect.Value = TournamentClientId == 0 ? 100 : 0;
- Form.FormBorderStyle = FormBorderStyle.None;
- string tourneyServer = GameModes.Other.Tournament.Tournament.Config.GetValue(@"privateserver", string.Empty);
- if (!string.IsNullOrEmpty(tourneyServer))
- BanchoClient.SetServer(new[] { tourneyServer });
- Scheduler.Add(delegate
- {
- Form.StartPosition = FormStartPosition.Manual;
- if (TournamentManager)
- {
- Form.Location = new System.Drawing.Point(0, 0);
- }
- else
- {
- Vector2 pos = TournamentLayout.ClientPositions[TournamentClientId];
- Form.Location = new System.Drawing.Point((int)pos.X, (int)pos.Y);
- }
- }, true);
- }
- startupThreadOperation = RunBackgroundThread(delegate
- {
- if (!Tournament)
- {
- CheckFilePermissions();
- HandleRegistryAssociations(false);
- Screensaver.Disable();
- }
- IPC.AcceptConnections(IpcChannelName);
- });
- BackgroundAppDetector = new BackgroundAppDetector();
- BackgroundAppDetector.AllowBackgroundExecution = ConfigManager.sDetectPerformanceIssues;
- BackgroundAppDetector.OnNewAppDetection += delegate (BackgroundAppDetector.AppDetection app)
- {
- NotificationManager.ShowMessage(string.Format(LocalisationManager.GetString(OsuString.GameBase_DetectedBackgroundApp), app.AppName), Color.Orange, 10000);
- };
- BackgroundAppDetector.Start();
- DataStoreUpdater = new DataStoreUpdater();
- NewGraphicsAvailable = File.Exists(@"osu!gameplay.dll") && File.Exists(@"osu!ui.dll");
- NativeText.Initialize();
- Player.Mode = SongSelection.LastSelectMode;
- UpdateScreenDevice();
- Window.ScreenDeviceNameChanged += Window_ScreenDeviceNameChanged;
- Form.LocationChanged += OnLocationChanged;
- Form.SizeChanged += OnLocationChanged;
- Form.ResizeEnd += OnLocationChanged;
- Form.Activated += OnLocationChanged;
- Form.ClientSizeChanged += OnLocationChanged;
- SystemResolutionWidth = Screen.PrimaryScreen.Bounds.Width;
- SystemResolutionHeight = Screen.PrimaryScreen.Bounds.Height;
- List<string> checkFiles = new List<string>()
- {
- @"1812a3605d6a596a67b5f2250f82307d",
- @"83d489cce95f15b275e480de15bafa88",
- @"f3bf7a5f31a97c2e01dbfd88d49fdcb0",
- @"80ea471ed63c89c4b7db3c3b70ee20a3"
- };
- try
- {
- Directory.CreateDirectory(BeatmapManager.SongsDirectory);
- string dataPath = Path.Combine(OsuMain.UserPath, @"Data");
- Directory.CreateDirectory(dataPath);
- Directory.CreateDirectory(Path.Combine(dataPath, @"r"));
- Directory.CreateDirectory(Path.Combine(dataPath, @"a"));
- GeneralHelper.FileDelete(@"error_update.txt");
- GeneralHelper.FileDelete(@"update_log.txt");
- GeneralHelper.FileDelete(@"update_log_success.txt");
- GeneralHelper.FileDelete(@".gl_compatible");
- if (!OsuMain.IsWine)
- {
- if (!File.Exists(Path.Combine(OsuMain.UserPath, @"osu!.exe")))
- {
- //user's UserPath is in a different location from the osu! executable install.
- //make sure we have a shortcut to osu!
- string runShortcut = Path.Combine(OsuMain.UserPath, @"start osu!.lnk");
- if (!File.Exists(runShortcut)) ShellLinkHelper.Create(runShortcut, Path.Combine(Environment.CurrentDirectory, @"osu!.exe"), @"osu!");
- }
- string repairShortcut = Path.Combine(OsuMain.UserPath, @"repair osu!.lnk");
- if (!File.Exists(repairShortcut)) ShellLinkHelper.Create(repairShortcut, Path.Combine(Environment.CurrentDirectory, @"osu!.exe"), @"repair osu!", @"-config");
- }
- try
- {
- List<string> files = new List<string>();
- files.AddRange(Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)));
- files.AddRange(Directory.GetDirectories(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)));
- foreach (string s in files)
- {
- if (checkFiles.Contains(CryptoHelper.GetMd5String(@"osu!" + Path.GetFileName(s).ToLower())))
- checkFilesMatched = true;
- }
- }
- catch { }
- }
- catch { }
- PerformanceMonitor = new PerformanceMonitor();
- BeatmapManager.Initialize();
- InputManager.Initialize();
- spriteManagerOverlay = new SpriteManager(true);
- spriteManagerOverlay.HandleOverlayInput = true;
- spriteManagerOverlayHighest = new SpriteManager(true);
- spriteManagerOverlayHighest.HandleOverlayInput = true;
- spriteManagerTransition = new SpriteManager(true);
- spriteManager = new SpriteManager();
- spriteManagerCursor = new SpriteManager(true) { HandleInput = false };
- cursorTrailRenderer = new CursorTrailRenderer();
- spriteManagerHighest = new SpriteManager(true);
- if (Tournament)
- {
- TourneySpectatorName = new pText(string.Empty, TournamentClientManager.ClientNameSize * TournamentLayout.ClientSizeRatio, new Vector2(3, 3), 1, true, Color.Yellow);
- TourneySpectatorName.FontFace = FontFace.ExoMedium;
- TourneySpectatorName.Field = Fields.TopLeft;
- TourneySpectatorName.Origin = Origins.TopLeft;
- TourneySpectatorName.TextShadow = true;
- TourneySpectatorName.TextBold = true;
- TourneySpectatorName.OnRefreshTexture += delegate { TourneySpectatorName.Alpha = 1; };
- spriteManagerOverlayHighest.Add(TourneySpectatorName);
- }
- s_fadeScreen = new pSprite(WhitePixel, Fields.Native, Origins.TopLeft, Clocks.Game, Vector2.Zero, 0, true, Color.Black);
- #if !Public
- if (!Tournament)
- {
- testBuildOverlay = new pSprite(TextureManager.Load(@"test-build-overlay", SkinSource.Osu), Fields.BottomRight, Origins.BottomRight, Clocks.Game, Vector2.Zero, 1, true, Color.White);
- spriteManagerOverlayHighest.Add(testBuildOverlay);
- testBuildVersion = new pText(General.BUILD_NAME, 14, new Vector2(0, 0), 0.99f, true, Color.White);
- testBuildVersion.TextShadow = true;
- testBuildVersion.Alpha = 0.4f;
- testBuildVersion.Field = Fields.BottomCentre;
- testBuildVersion.Origin = Origins.BottomCentre;
- testBuildVersion.TextRenderSpecific = false;
- spriteManagerOverlayHighest.Add(testBuildVersion);
- }
- #endif
- SetScreenSize();
- SkinManager.Initialize();
- AudioEngine.Initialize();
- TransitionManager = new TransitionManager();
- BanchoStatus = new BanchoStatusOverlay();
- spriteManagerTransition.Add(s_fadeScreen);
- float scale = DpiHelper.DPI(GameBase.Form) / 96.0f;
- ToolTip = new pTooltip(string.Empty, 11, Vector2.Zero, Vector2.Zero, 1, true, Color.White, false);
- spriteManagerHighest.Add(ToolTip);
- Options = new Options(this);
- FpsDisplay = new FpsDisplay(PerformanceMonitor);
- osuDirect = new OsuDirect(this);
- osuDirect.Initialize();
- chatEngine = new ChatEngine(this);
- chatEngine.Initialize();
- Volume = new VolumeControlSet();
- //Coins = new CoinsOverlay();
- MusicControl = new MusicControl(this);
- MusicControl.Initialize();
- #if Local
- if (!IsFirstInstance)
- ConfigManager.sUsername.Value = "General Pepper";
- else
- ConfigManager.sUsername.Value = "peppy";
- #endif
- User = new User(ConfigManager.sUsername);
- User.DrawAt(new Vector2(0, 0), false, 0);
- #if !ARCADE
- //For the time being let's make this not clickable for arcade. Not sure whether this is required, though.
- User.Clickable = true;
- User.Sprites[0].KeepEventsBound = true;
- User.Sprites[0].OnClick += ShowLocalUserOptions;
- #endif
- BanchoClient.Start();
- OsuModes gs = ReceiveFile(StartupNewFiles);
- QueuedMode = gs != OsuModes.Unknown ? gs : QueuedMode;
- if (BenchmarkMode)
- {
- BeatmapManager.Current = BeatmapManager.Beatmaps.Find(b => b.PlayMode == PlayModes.Osu);
- ModManager.ModStatus |= Mods.Autoplay;
- //ModManager.ModDoubleTime = true;
- QueuedMode = OsuModes.Play;
- }
- #if DEBUG
- InitializeTester();
- #endif
- FadeState = FadeStates.WaitingLoad;
- loadQueuedMode();
- IdleHandler.Initialize();
- #if P2P
- //activate P2P system
- Osup2pManager.Initialize(new P2PSettings());
- Osup2pManager.Activate();
- //Osup2pManager.LoadMagnet("3oh!3 - I Can't Do It Alone.osz2.osuMagnet");
- #endif
- BringToFront();
- base.Initialize();
- if (!string.IsNullOrEmpty(ConfigManager.sLastVersion))
- {
- ConfigManager.sUpdateFailCount.Value = 0;
- if (ConfigManager.sLastVersion != General.BUILD_NAME)
- {
- SetUpdateState(UpdateStates.Completed);
- }
- else if (ConfigManager.sUpdatePending)
- {
- SetUpdateState(UpdateStates.Completed);
- }
- }
- ConfigManager.sLastVersion.Value = General.BUILD_NAME;
- ConfigManager.dDisableFBO?.TriggerChange();
- ConfigManager.dDisableVBO?.TriggerChange();
- stopWatch.Start();
- BeatmapImport.Start();
- }
- private static void UpdateScreenDevice()
- {
- Screen currentScreen = Screen.FromHandle(Instance.Window.Handle);
- string displayName = currentScreen.DeviceName;
- try
- {
- ConfigManager.sDisplay.Value = Int32.Parse(displayName[displayName.Length - 1].ToString());
- Debug.Print("Changed to monitor #" + ConfigManager.sDisplay.Value + " ( " + displayName + " )");
- }
- catch
- {
- }
- UpdateDesktopProperties();
- }
- internal static void UpdateDesktopProperties(bool force = false)
- {
- RefreshRate = ResolutionHelper.GetCurrentRefreshRate();
- //Find the current desktop parameters. If we are fullscreen, then we might have changed the desktop resolution, so we may not change these parameters under any circumstances.
- if ((!ConfigManager.sFullscreen && !IsFullscreen) || force)
- {
- InitialDesktopResolution = ResolutionHelper.GetDesktopResolution();
- InitialDesktopLocation = ResolutionHelper.GetDesktopPosition();
- InitialRefreshRate = RefreshRate;
- if (Options != null)
- Options.UpdateResolutions();
- }
- }
- private static string createUniqueCheck()
- {
- return CryptoHelper.GetMd5String(UniqueId + 0x08 + 0x200 + UniqueId2);
- }
- internal static string CreateUniqueId()
- {
- try
- {
- string guid = Uninstaller.GetUninstallId().ToString();
- UniqueId.Value = CryptoHelper.GetMd5String(guid);
- }
- catch { }
- try
- {
- UniqueId2.Value = CryptoHelper.GetMd5String(identifier("Win32_DiskDrive", "Signature", "SerialNumber"));
- }
- catch { }
- UniqueId2.allowDestruction = false;
- UniqueId.allowDestruction = false;
- UniqueCheck.Value = createUniqueCheck();
- return UniqueId + @"|" + UniqueId2;
- }
- internal static bool CheckUniqueId()
- {
- if (GameBase.Time == 0) return true;
- return createUniqueCheck() == UniqueCheck.Value && UniqueId.c <= 3 + ChangeAllowance && UniqueId2.c <= 3 + ChangeAllowance;
- }
- internal static string identifier(string wmiClass, params string[] wmiProperty)
- //Return a hardware identifier
- {
- try
- {
- System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
- System.Management.ManagementObjectCollection moc = mc.GetInstances();
- foreach (System.Management.ManagementObject mo in moc)
- {
- foreach (string w in wmiProperty)
- {
- try
- {
- object o = mo[w];
- if (o == null)
- continue;
- return mo[w].ToString();
- }
- catch
- {
- }
- }
- }
- }
- catch { }
- return string.Empty;
- }
- internal static void BringToFront()
- {
- Form.BringToFront();
- SetForegroundWindow(Form.Handle);
- }
- /// <summary> The RegisterHotKey function defines a system-wide hot key </summary>
- /// <param name="hwnd">Handle to the window that will receive WM_HOTKEY messages
- /// generated by the hot key.</param>
- /// <param name="id">Specifies the identifier of the hot key.</param>
- /// <param name="fsModifiers">Specifies keys that must be pressed in combination with the key
- /// specified by the 'vk' parameter in order to generate the WM_HOTKEY message.</param>
- /// <param name="vk">Specifies the virtual-key code of the hot key</param>
- /// <returns><c>true</c> if the function succeeds, otherwise <c>false</c></returns>
- /// <seealso cref="http://msdn.microsoft.com/en-us/library/ms646309(VS.85).aspx"/>
- [DllImport(@"user32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
- #region fields
- private static int MOD_ALT = 0x1;
- private static int MOD_CONTROL = 0x2;
- private static int MOD_SHIFT = 0x4;
- private static int MOD_WIN = 0x8;
- private static int WM_HOTKEY = 0x312;
- #endregion
- private static void OnLocationChanged(object sender, EventArgs e)
- {
- UpdateClientBounds();
- }
- private static void UpdateClientBounds()
- {
- System.Drawing.Rectangle actualViewport = new System.Drawing.Rectangle(OsuGlControl.Viewport.Left, clientSize.Height - OsuGlControl.Viewport.Bottom, OsuGlControl.Viewport.Width, OsuGlControl.Viewport.Height);
- ClientBounds = Form.RectangleToScreen(actualViewport);
- }
- internal static Point ViewportOffset
- {
- get
- {
- return new Point(OsuGlControl.Viewport.Left, clientSize.Height - OsuGlControl.Viewport.Bottom);
- }
- }
- internal static bool MouseVisible = true;
- internal static void HandleRegistryAssociations(bool runningElevated)
- {
- //ensure we only run this operation once before release (in the case it is actually run).
- if (!runningElevated && ConfigManager.sLastVersionPermissionsFailed.Value == General.BUILD_NAME)
- return;
- bool success = true;
- //make sure we've initialised our uniqueId here.
- if (Uninstaller.GetUninstallId() == Guid.Empty)
- success = false;
- if (!GeneralHelper.RegistryCheck("osu!", OsuMain.FullPath))
- {
- success &= GeneralHelper.RegistryAdd("osz", "osu!", "osu! beatmap", OsuMain.FullPath);
- if (success) success &= GeneralHelper.RegistryAdd("osz2", "osu!", "osu! beatmap v2", OsuMain.FullPath);
- if (success) success &= GeneralHelper.RegistryAdd("osr", "osu!", "osu! replay", OsuMain.FullPath);
- if (success) success &= GeneralHelper.RegistryAdd("osk", "osu!", "osu! skin", OsuMain.FullPath);
- if (Registry.ClassesRoot.GetValue(string.Empty, string.Empty).ToString() == "osu") Registry.ClassesRoot.DeleteValue(string.Empty, false);
- }
- if (!GeneralHelper.RegistryCheck("osu", OsuMain.FullPath) && !GeneralHelper.RegistryAdd(string.Empty, "osu", "osu! url handler", OsuMain.FullPath, true))
- success = false;
- if (!Uninstaller.CreateUninstaller())
- success = false;
- if (!success && !runningElevated)
- {
- GameBase.SetPermissions(true);
- ConfigManager.sLastVersionPermissionsFailed.Value = General.BUILD_NAME;
- }
- }
- /// <summary>
- /// Permission test for vista crap shit fuck.
- /// </summary>
- private static void CheckFilePermissions()
- {
- OperatingSystem osInfo = Environment.OSVersion;
- if (osInfo.Platform != PlatformID.Win32NT || osInfo.Version.Major != 6)
- return;
- try
- {
- Directory.CreateDirectory(".test");
- Directory.Delete(".test");
- }
- catch (Exception)
- {
- SetPermissions(false);
- try
- {
- Directory.Delete(".test");
- }
- catch { }
- }
- }
- internal static void SetPermissions(bool registryOnly)
- {
- if (!OsuMain.IsElevated)
- {
- Scheduler.AddDelayed(() =>
- {
- bool didPause = AudioEngine.PauseAudioTrackIfPlaying();
- RunNonExclusive(() => { OsuMain.Elevate(registryOnly ? "-setassociations" : "-setpermissions", true); });
- if (didPause) AudioEngine.TogglePause();
- }, Math.Max(500, (Menu.IntroLength + 500) - GameBase.Time));
- return;
- }
- GameBase.HandleRegistryAssociations(true);
- if (registryOnly) return;
- OsuMain.SetDirectoryPermissions();
- }
- private void InitializeGl()
- {
- GlControl.InitializeGl();
- TextureGlSingle.Initialize();
- clientSize = Form.ClientSize;
- if (ConfigManager.sShaders && !ShaderManager.CanUseShaders)
- ConfigManager.sShaders.Value = false;
- }
- private void Window_ScreenDeviceNameChanged(object sender, EventArgs e)
- {
- UpdateScreenDevice();
- }
- //todo: this can be optimised
- internal static bool HasLogin { get { return !string.IsNullOrEmpty(ConfigManager.sPassword) && !string.IsNullOrEmpty(ConfigManager.sUsername); } }
- internal static void ShowLocalUserOptions(object sender, EventArgs e)
- {
- if (!GameBase.HasLogin)
- ShowLogin();
- else
- UserProfile.DisplayProfileFor(User, false);
- }
- /// <summary>
- /// We are running in the background or during a period where we should be favouring other threads.
- /// </summary>
- internal static bool CanRunSlowly
- {
- get
- {
- return (IsMinimized || MenuActive || (!Instance.IsActive && !Tournament) || BackgroundLoading) && !Player.Playing && !InputManager.ReplayStreaming && !InputManager.ReplayMode;
- }
- }
- protected override void Update()
- {
- PerformanceMonitor.EndCollecting(FrameTimeType.BetweenFrames);
- #if !DEBUG
- try
- {
- #endif
- PerformanceMonitor.BeginCollecting(FrameTimeType.Update);
- IsMinimized = Window.IsMinimized || (Window.ClientBounds.X < -10000 && Window.ClientBounds.Y < -10000);
- if (OnScreenDisplay != null) OnScreenDisplay.Update();
- PerformanceMonitor.BeginCollecting(FrameTimeType.Scheduler);
- Scheduler.Update();
- PerformanceMonitor.EndCollecting(FrameTimeType.Scheduler);
- updateWindowState();
- FpsDisplay.Update();
- chatEngine.Update();
- osuDirect.Update();
- MusicControl.Update();
- UpdateDialogQueue();
- bool oldBloomPass = BloomRenderer.ExtraPass;
- ChildrenUpdated = false;
- BloomRenderer.ExtraPass = false;
- UpdateFadeState();
- PhysicsManager.Update();
- BanchoStatus.Update();
- TransitionManager.Update();
- Options.Update();
- Volume.Update();
- if (Coins != null) Coins.Update();
- InputManager.UpdateFrame(() =>
- {
- Components.ForEach(c => c.Update());
- base.Update();
- ChildrenUpdated = true;
- });
- cursorTrailRenderer.Update();
- if (!ChildrenUpdated)
- //In the case children are not updated, we need to remember the bloom pass state.
- //This happens when replays/auto are skipping frames (but we don't want the bloom pass to flicker during this).
- BloomRenderer.ExtraPass = oldBloomPass;
- NotificationManager.Update();
- OsuTipManager.Update();
- SkinManager.Cleanup();
- InputManager.CheckTextInputFocus(false);
- UpdateSystemWideDisables();
- #if !Release
- if (GameBase.BenchmarkMode && GameBase.Time > 120000)
- BeginExit(false);
- #endif
- #if !DEBUG
- }
- catch (Exception e)
- {
- if (ExceptionCount++ > 1 || Mode == OsuModes.Exit || QueuedMode == OsuModes.Exit)
- throw;
- softHandle(e);
- }
- #endif
- #if !Public
- if (testBuildOverlay != null && testBuildOverlay.Transformations.Count == 0)
- {
- bool hide = Player.Playing || ChatEngine.IsVisible || InputManager.ReplayMode || ConfigManager.sFrameTimeDisplay;
- bool hideText = hide || (Mode == OsuModes.Menu && Menu.titleImageUrl != null);
- testBuildOverlay.MoveTo(new Vector2(0, hide ? -5 : 0), 500);
- testBuildVersion.FadeTo(hideText ? 0 : 0.4f, 500);
- }
- #endif
- if (Tournament && !TournamentManager)
- {
- User u = StreamingManager.CurrentlySpectating;
- TourneySpectatorName.Text = u == null ? string.Empty : u.Name;
- if (GameBase.Time > 40000 && GameBase.Time - IPC.LastContact > 10000)
- BeginExit();
- }
- if (Form.WindowState == FormWindowState.Maximized)
- {
- //switch to borderless fullscreen.
- Form.WindowState = FormWindowState.Normal;
- SetScreenSize(InitialDesktopResolution.Width, InitialDesktopResolution.Height, true);
- }
- bool shallBeTopMost = TopMost;
- if (Form.TopMost != shallBeTopMost)
- {
- Form.TopMost = shallBeTopMost;
- }
- SpriteManager handler = null;
- if (InputManager.HandleInput)
- handler = SpriteManager.CheckInputGlobal();
- //update tooltip
- if (handler != null && handler.CurrentHoverSprite != null)
- ToolTip.Text = handler.CurrentHoverSprite.ToolTip;
- else
- ToolTip.Text = null;
- PerformanceMonitor.EndCollecting(FrameTimeType.Update);
- }
- private bool handleWindowedToggle = true;
- private void updateWindowState()
- {
- if (!IsFullscreen)
- return;
- if (Time < 1000 || handleWindowedToggle)
- {
- // The window should be active, let's keep forcing focus until it activates
- if (IsActive)
- handleWindowedToggle = false;
- else if (!GLControl.ForcedWindowed)
- Form.Focus();
- return;
- }
- if (IsActive && GLControl.ForcedWindowed)
- {
- // Enter fullscreen
- GLControl.ToggleWindowed();
- UpdateDesktopResolution();
- bool forceNonExclusive = ForceNonExclusive;
- ResizeGL(forceNonExclusive);
- if (!forceNonExclusive)
- {
- // TopMost is already true at this point from the main loop, we however need to touch it again after changing the resolution so that windows understands.
- Form.TopMost = true;
- }
- if (OsuGlControl.UsesAngle)
- {
- // D3D window will be unfocused upon device reset causing us to immediately fall through the !IsActive branch below. We don't want this so let's make sure the window
- // is properly focused before that branch can be executed.
- handleWindowedToggle = true;
- }
- }
- else if (!IsActive && !GLControl.ForcedWindowed)
- {
- // We need to enter the windowed state, but this is also handled inside ForcefullyLeaveExclusiveFullscreen() for Angle.
- if (!OsuGlControl.UsesAngle)
- GLControl.ToggleWindowed();
- // We forcefully leave exclusive fullscreen mode, both when we want to minimize and when we don't want to. On some graphics hardware otherwise exclusive fullscreen
- // won't be left on minimize, resulting in a frozen screen.
- ForcefullyLeaveExclusiveFullscreen();
- ResizeGL(true);
- // We need to perform the minimization and resolution change delayed due to some hardware failing to leave exclusive fullscreen mode otherwise
- GameBase.Scheduler.Add(() =>
- {
- if (OsuGlControl.UsesAngle || ConfigManager.sConfineMouse.Value > ConfineMouseMode.Never ||
- clientSize.Width < InitialDesktopResolution.Width || clientSize.Height < InitialDesktopResolution.Height || RefreshRate != InitialRefreshRate)
- {
- Form.WindowState = FormWindowState.Minimized;
- }
- // This condition catches minimization via the boss key, too.
- if (Form.WindowState == FormWindowState.Minimized)
- ResolutionHelper.ResetResolution();
- }, true);
- }
- }
- private static void UpdateDialogQueue()
- {
- if (DialogQueue.Count > 0 && ActiveDialog == null && (!Player.Playing || ChatEngine.Visibility == ChatVisibility.Full))
- {
- TextInputControl tic = InputManager.GetActiveTextInputControl();
- if (tic != null && tic.AcceptText)
- {
- ActiveDialogMutedTextControl = tic;
- ActiveDialogMutedTextControl.AcceptText = false;
- }
- ActiveDialog = DialogQueue[0];
- ActiveDialog.Display();
- ActiveDialog.DisplayAfter();
- ActiveDialog.Closed += dialog_Closed;
- }
- if (ActiveDialog != null)
- ActiveDialog.Update();
- }
- /// <summary>
- /// Main time-keeping function. Handles different kinds of frame limiters and ensures constant velocity where required.
- /// </summary>
- private void UpdateTiming()
- {
- PerformanceMonitor.BeginCollecting(FrameTimeType.Sleep);
- double stopwatchTime = stopWatch.GetElapsedMillisecondsPrecise();
- double targetMilliseconds = FrameLimitMillisecondsPerFrame;
- int timeToSleepFloored = 0;
- //If we are limiting to a specific rate, and not enough time has passed for the next frame to be accepted we should pause here.
- if (targetMilliseconds > 0)
- {
- if (stopwatchTime - TimeAccurate < targetMilliseconds)
- {
- // Using ticks for sleeping is pointless due to them being rounded to milliseconds internally anyways (in windows at least).
- double timeToSleep = targetMilliseconds - (stopwatchTime - TimeAccurate);
- timeToSleepFloored = (int)Math.Floor(timeToSleep);
- Debug.Assert(timeToSleepFloored >= 0);
- AccumulatedSleepError += timeToSleep - (double)timeToSleepFloored;
- int accumulatedSleepErrorCompensation = (int)Math.Round(AccumulatedSleepError);
- // Can't sleep a negative amount of time
- accumulatedSleepErrorCompensation = Math.Max(accumulatedSleepErrorCompensation, -timeToSleepFloored);
- AccumulatedSleepError -= accumulatedSleepErrorCompensation;
- timeToSleepFloored += accumulatedSleepErrorCompensation;
- // We don't want re-schedules with Thread.Sleep(0). We already have that case down below.
- if (timeToSleepFloored > 0)
- Thread.Sleep(timeToSleepFloored);
- // Sleep is not guaranteed to be an exact time. It only guaranteed to sleep AT LEAST the specified time. We also used some time to compute the above things, so this is also factored in here.
- double afterSleepTime = stopWatch.GetElapsedMillisecondsPrecise();
- AccumulatedSleepError += (double)timeToSleepFloored - (afterSleepTime - stopwatchTime);
- stopwatchTime = afterSleepTime;
- }
- else
- {
- // We use the negative spareTime to compensate for framerate jitter slightly.
- double spareTime = (stopwatchTime - TimeAccurate) - targetMilliseconds;
- AccumulatedSleepError = -spareTime;
- }
- }
- // Call the scheduler to give lower-priority background processes a chance to do stuff.
- if (timeToSleepFloored == 0)
- Thread.Sleep(0);
- TimeAccurateLastUpdate = TimeAccurate;
- TimeAccurate = stopwatchTime;
- Time = (int)Math.Round(TimeAccurate, 0);
- if (TimeAccurate - SixtyFrameLast >= SIXTY_FRAME_TIME || PendingModeChange)
- {
- if (PendingModeChange || (!Player.IsSpinning && !Player.IsSliding && !InputManager.ReplayMode && (IsMinimized || !IsActive || Time - SixtyFrameLast > 500)))
- {
- //This is a kind of catch-up mode, where we ignore the fact 60fps frames haven't been handled
- //and force the game back into sync. 500ms is arbitrary, but seems to work well.
- SixtyFramesPerSecondLength = TimeAccurate - SixtyFrameLast;
- SixtyFrameLast = TimeAccurate - SIXTY_FRAME_TIME;
- }
- else
- {
- SixtyFramesPerSecondLength = TimeAccurate - SixtyFrameLast;
- SixtyFrameLast = TimeAccurate - (SixtyFramesPerSecondLength - SIXTY_FRAME_TIME);
- }
- SixtyFramesPerSecondFrame = true;
- PendingModeChange = false;
- }
- else
- SixtyFramesPerSecondFrame = false;
- ElapsedMilliseconds = TimeAccurate - TimeAccurateLastUpdate;
- FrameRatio = ElapsedMilliseconds / FrameAimTime;
- ModeTime += ElapsedMilliseconds;
- PerformanceMonitor.EndCollecting(FrameTimeType.Sleep);
- }
- private static void UpdateSystemWideDisables()
- {
- //Handle whether the screensaver should be disabled or not.
- //todo: run less frequently
- if (Instance.IsActive)
- Screensaver.Disable();
- else
- Screensaver.Restore();
- if (Instance.IsActive && Player.Playing && !InputManager.ReplayMode)
- WindowsKey.Disable();
- else
- WindowsKey.Enable();
- }
- #if DEBUG
- internal static int AmountVBO = 0;
- internal static int AmountTextures = 0;
- #endif
- private void UpdateFadeState()
- {
- if (FadeState != FadeStates.Idle || fadeLevel > 0)
- {
- if (ConfigManager.sShaders && !s_fadeScreen.Bypass)
- {
- BloomRenderer.ExtraPass = true;
- BloomRenderer.Magnitude = 0.004f;
- BloomRenderer.Additive = false;
- BloomRenderer.HiRange = false;
- BloomRenderer.Alpha = OsuMathHelper.Clamp((float)fadeLevel, 0, 100) / 100;
- }
- if (FadeState == FadeStates.FadeIn)
- {
- if (fadeLevel <= 0)
- {
- FadeState = FadeStates.Idle;
- if (FadeInComplete != null)
- FadeInComplete(this, null);
- }
- else
- fadeLevel = Math.Max(-1, fadeLevel - fadeInRate * FrameRatio);
- }
- else if (FadeState == FadeStates.FadeOut)
- {
- if (fadeLevel >= 100)
- {
- FadeState = FadeStates.WaitingLoad;
- if (FadeOutComplete != null)
- FadeOutComplete(this, null);
- }
- else
- {
- fadeLevel = Math.Min(100, fadeLevel + fadeOutRate * FrameRatio);
- if (QueuedMode == OsuModes.Exit || QueuedMode == OsuModes.Update)
- {
- AudioEngine.SetVolumeMusicFade((int)(100 * Math.Pow(1 - fadeLevel / 100, 3)), true);
- Form.Opacity = Math.Min(1, 3 - 3 * fadeLevel / 100);
- }
- else if (Mode == OsuModes.Play)
- {
- if (AudioEngine.volumeMusicFade > 50)
- AudioEngine.SetVolumeMusicFade(AudioEngine.volumeMusicFade - 1);
- }
- else
- AudioEngine.SetVolumeMusicFade(AudioEngine.volumeMusicFade - 5);
- }
- }
- }
- #if TRIANGLES
- spriteManagerTransition.Alpha = OsuMathHelper.Clamp((float)fadeLevel, 0, 100) / 200;
- #else
- spriteManagerTransition.Alpha = OsuMathHelper.Clamp((float)fadeLevel, 0, 100) / 100;
- #endif
- }
- internal static void ShowDialog(pDialog dialog)
- {
- DialogQueue.Add(dialog);
- }
- private static void dialog_Closed(object sender, EventArgs e)
- {
- if (ActiveDialog == null)
- return;
- ActiveDialog.spriteManager.SpriteList.ForEach(s => { s.FadeOut(180); s.AlwaysDraw = false; });
- pDialog disposedDialog = ActiveDialog;
- Scheduler.AddDelayed(delegate { disposedDialog.spriteManager.Dispose(); }, 180);
- spriteManagerOverlay.Add(ActiveDialog.spriteManager.SpriteList);
- ActiveDialog = null;
- if (ActiveDialogMutedTextControl != null)
- {
- ActiveDialogMutedTextControl.AcceptText = true;
- ActiveDialogMutedTextControl = null;
- }
- DialogQueue.Remove((pDialog)sender);
- Instance.Components.Remove((GameComponent)sender);
- }
- static int ExceptionCount;
- protected override void Draw()
- {
- #if !DEBUG
- try
- {
- #endif
- PerformanceMonitor.BeginCollecting(FrameTimeType.Draw);
- OsuGlControl.ResetState();
- GraphicsScheduler.Update();
- TextureGl.UploadNext();
- if (IsMinimized && CanRunSlowly && TotalFramesRendered % 4 != 0)
- {
- //We don't need to draw much when minimised.
- //We do need to draw occasionally though, else there can be cases where, for example,
- //Update creates many sprites which are never cleaned up by SpriteManager's Draw call.
- //Once every 4 frames sounds like a fair compromise (once every second, as we run 15fps when minimised).
- PerformanceMonitor.EndCollecting(FrameTimeType.Draw);
- return;
- }
- SpriteManager.NewFrame();
- Shader.SetGlobalProperty(@"g_Time", Time);
- OsuGlControl.TextureShader2D.Begin();
- HitObjectManager.DrawTargets();
- GL.Clear(ClearBufferMask.ColorBufferBit);
- bool replayCursor = InputManager.ReplayMode && Mode == OsuModes.Play;
- //Begin bloom virtual renderer.
- if (ConfigManager.sShaders) BloomRenderer.BloomStart();
- TransitionManager.Draw();
- base.Draw();
- Components.ForEach(c => (c as DrawableGameComponent)?.Draw());
- spriteManager.Draw();
- //if ((BanchoClient.Permission & Permissions.Supporter) > 0)
- if (replayCursor)
- {
- cursorTrailRenderer.Draw();
- spriteManagerCursor.Draw();
- }
- Options.Draw();
- osuDirect.Draw();
- spriteManagerOverlay.Draw();
- chatEngine.Draw();
- MusicControl.Draw();
- if (Coins != null) Coins.Draw();
- if (ActiveDialog != null)
- ActiveDialog.Draw();
- Volume.Draw();
- if (FrameTimeDisplay != null && ConfigManager.sFrameTimeDisplay.Value) FrameTimeDisplay.Draw();
- spriteManagerOverlayHighest.Draw();
- FpsDisplay.Draw();
- BanchoStatus.Draw();
- if (OnScreenDisplay != null) OnScreenDisplay.Draw();
- if (!replayCursor)
- {
- cursorTrailRenderer.Draw();
- spriteManagerCursor.Draw();
- }
- spriteManagerHighest.Draw();
- if (FadeState != FadeStates.Idle || spriteManagerTransition.Alpha > 0)
- spriteManagerTransition.Draw();
- TransitionManager.DrawHigh();
- //Draw bloom overlay.
- if (ConfigManager.sShaders) BloomRenderer.BloomEnd();
- OsuGlControl.TextureShader2D.End();
- PerformanceMonitor.EndCollecting(FrameTimeType.Draw);
- PerformanceMonitor.BeginCollecting(FrameTimeType.Sleep);
- Thread.Sleep(0);
- PerformanceMonitor.EndCollecting(FrameTimeType.Sleep);
- PerformanceMonitor.BeginCollecting(FrameTimeType.SwapBuffer);
- GlControl.SwapBuffers();
- PerformanceMonitor.EndCollecting(FrameTimeType.SwapBuffer);
- #if !DEBUG
- }
- catch (Exception e)
- {
- if (ExceptionCount++ > 1 || Mode == OsuModes.Exit || QueuedMode == OsuModes.Exit)
- throw;
- softHandle(e);
- }
- #endif
- TotalFramesRendered++;
- }
- protected override void PostFrame()
- {
- PerformanceMonitor.BeginCollecting(FrameTimeType.Update);
- base.PostFrame();
- UpdateTiming();
- PerformanceMonitor.EndCollecting(FrameTimeType.Update);
- if (ConfigManager.sFrameTimeDisplay)
- {
- if (FrameTimeDisplay == null) FrameTimeDisplay = new FrameTimeDisplay(PerformanceMonitor);
- FrameTimeDisplay.Update();
- }
- PerformanceMonitor.NewFrame();
- PerformanceMonitor.BeginCollecting(FrameTimeType.BetweenFrames);
- }
- private static void softHandle(Exception e)
- {
- Logger.Log($@"Soft handled: {e}", LoggingTarget.Runtime, LogLevel.Error);
- if (ExceptionCount == 1) //report error the first time
- {
- ErrorSubmission.Submit(new OsuError(e) { Feedback = "soft handle" });
- NotificationManager.ShowMessage("An error occurred somewhere in osu! and has been reported. osu! will attempt to keep running.", Color.Red, 5000);
- }
- if (e is MissingFieldException || e is MissingMethodException || e is MissingMemberException)
- GameBase.ChangeMode(OsuModes.Update);
- GameBase.Scheduler.AddDelayed(delegate { ExceptionCount--; }, 1000);
- }
- //used for flashlight cheat detecting
- internal static Color[] PixelColorAt(Vector2 pos, int count)
- {
- try
- {
- {
- Color[] c = new Color[count];
- using (Bitmap b = new Bitmap(WindowManager.Width, WindowManager.Height, PixelFormat.Format32bppArgb))
- {
- BitmapData bd = b.LockBits(new System.Drawing.Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
- GL.ReadPixels(0, 0, WindowManager.Width, WindowManager.Height, OpenTK.Graphics.ES20.PixelFormat.Rgba, PixelType.UnsignedByte, bd.Scan0);
- b.UnlockBits(bd);
- for (int i = 0; i < count; i++)
- {
- System.Drawing.Color sc = b.GetPixel((int)pos.X, (int)pos.Y + i);
- c[i] = new Color(sc.R, sc.G, sc.B);
- }
- }
- return c;
- }
- }
- catch
- {
- return null;
- }
- }
- internal static MemoryStream GetScreenShotStream()
- {
- try
- {
- MemoryStream image = new MemoryStream();
- {
- using (Bitmap b = new Bitmap(WindowManager.Width, WindowManager.Height, PixelFormat.Format32bppArgb))
- {
- BitmapData bd = b.LockBits(new System.Drawing.Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadOnly, b.PixelFormat);
- GL.ReadPixels(0, 0, WindowManager.Width, WindowManager.Height, OpenTK.Graphics.ES20.PixelFormat.Rgba, PixelType.UnsignedByte, bd.Scan0);
- b.UnlockBits(bd);
- b.RotateFlip(RotateFlipType.RotateNoneFlipY);
- b.Save(image, ImageFormat.Jpeg);
- }
- return image;
- }
- }
- catch
- {
- return null;
- }
- }
- #endregion
- #region Gamefield/Window Manipulation
- internal static GameField GameField;
- internal static WindowManager WindowManager;
- internal static bool IsBorderlessWindow
- {
- get
- {
- return !ConfigManager.sFullscreen.Value && WindowManager.Width == InitialDesktopResolution.Width && WindowManager.Height == InitialDesktopResolution.Height;
- }
- }
- private static int InitialRefreshRate = 0;
- internal static int RefreshRate = 0;
- #endregion
- #region Sprites
- internal static Rectangle WindowRectangle;
- internal static Rectangle WindowRectangleWidescreen;
- #endregion
- #region State Management
- internal static double fadeLevel;
- internal static FadeStates FadeState = FadeStates.Idle;
- internal static OsuModes QueuedMode = OsuModes.Menu;
- internal static OsuModes Mode = OsuModes.Unknown;
- internal static pGameMode RunningGameMode;
- /// <summary>
- /// Track whether the exit dialog box is displaying (so we don't display more than one).
- /// </summary>
- static bool exitDialogDisplaying;
- /// <summary>
- /// Handle exit confirmation when required.
- /// </summary>
- internal static void BeginExit(bool forceConfirm = false)
- {
- bool downloadsActive = OsuDirect.ActiveDownloads.Count > 0;
- bool waitingPrivateMessages = ChatEngine.channelTabs.Tabs.FindAll(t => t.Alerting && t.tabText.Text != null && !t.tabText.Text.StartsWith(@"#")).Count > 0;
- if (Tournament)
- {
- ChangeMode(OsuModes.Exit);
- return;
- }
- if (!downloadsActive && !waitingPrivateMessages && !ConfigManager.sConfirmExit && !forceConfirm)
- {
- ChangeMode(OsuModes.Exit);
- return;
- }
- if (exitDialogDisplaying) return;
- exitDialogDisplaying = true;
- string confirmMessage = "Are you sure you want to exit osu!?";
- if (downloadsActive)
- confirmMessage = "Exiting will cancel all active downloads!\n" + confirmMessage;
- else if (waitingPrivateMessages)
- confirmMessage = "You have unread chat messages.\n" + confirmMessage;
- pDialogConfirmation pd = new pDialogConfirmation(confirmMessage,
- delegate { ChangeMode(OsuModes.Exit); },
- delegate { exitDialogDisplaying = false; }
- );
- pd.Closed += delegate { exitDialogDisplaying = false; };
- ShowDialog(pd);
- }
- internal static void ChangeMode(OsuModes newMode = OsuModes.Unknown, bool force = false)
- {
- if (newMode == OsuModes.Unknown)
- {
- newMode = Mode;
- force = true;
- }
- if (newMode != OsuModes.Menu && Time < Menu.IntroLength)
- {
- //170ms delay = 120ms transition fade out + 50ms transition scheduling
- Scheduler.AddDelayed(delegate { ChangeMode(newMode, force); }, Menu.IntroLength - Time + 170);
- return;
- }
- //If we are in the editor and not yet prompted for confirmation, do so now.
- if (Mode == OsuModes.Edit && !((Editor)RunningGameMode).ExitedProperly && !((Editor)RunningGameMode).Exit())
- return;
- if ((newMode != OsuModes.Exit && newMode != OsuModes.Update) && (!BanchoClient.CheckAuth(false) || !AudioEngine.CheckAudioDevice()))
- {
- newMode = OsuModes.Menu;
- force = true;
- }
- if (Tournament)
- {
- switch (newMode)
- {
- case OsuModes.Rank:
- case OsuModes.Exit:
- case OsuModes.Busy:
- break;
- case OsuModes.SelectPlay:
- newMode = OsuModes.Menu;
- break;
- default:
- if (Mode == OsuModes.Play && !AudioEngine.Paused &&
- (InputManager.ReplayToEnd || (Player.Instance != null && Player.Instance.Status == PlayerStatus.Outro)))
- return;
- break;
- }
- //todo: figure a proper fix for this.
- if (Mode == OsuModes.Rank && newMode == OsuModes.Play && ModeTime < 10000)
- return;
- }
- NotificationManager.ClearMessageMassive();
- if (newMode == Mode && !force)
- return;
- if (newMode == QueuedMode && !force)
- return;
- if (QueuedMode == OsuModes.Exit)
- return;
- Debug.Print("Queued mode change to {0}", newMode.ToString());
- //Close dialogs which are specific to the old game mode.
- List<pDialog> closeUs = new List<pDialog>();
- foreach (pDialog p in DialogQueue)
- if (p.GameModeSpecific)
- closeUs.Add(p);
- foreach (pDialog p in closeUs)
- p.Close();
- QueuedMode = newMode;
- s_fadeScreen.Bypass = false;
- fadeOutRate = 10;
- spriteManagerTransition.Clear();
- spriteManagerTransition.Add(s_fadeScreen);
- switch (newMode)
- {
- case OsuModes.Exit:
- if (OnExitFade != null) OnExitFade();
- if (!ConfigManager.sMenuVoice || (UpdateState == UpdateStates.NeedsRestart && OsuMain.Restart) || Tournament)
- fadeOutRate = 5;
- else
- {
- fadeOutRate = 0.6;
- AudioEngine.PlaySample(@"seeya", 100, (BanchoClient.Permission & Permissions.Supporter) > 0 ? SkinSource.ExceptBeatmap : SkinSource.Osu);
- }
- InputManager.HandleInput = false;
- break;
- }
- FadeState = FadeStates.FadeOut;
- }
- internal static void ChangeModeInstant(OsuModes newMode, bool force = false, int disposalDelay = 0)
- {
- if (newMode != OsuModes.Menu && Time < Menu.IntroLength)
- {
- //170ms delay = 120ms transition fade out + 50ms transition scheduling
- Scheduler.AddDelayed(delegate { ChangeModeInstant(newMode, force, disposalDelay); }, Menu.IntroLength - Time + 170);
- return;
- }
- Scheduler.Add(delegate
- {
- if (newMode == Mode && !force)
- return;
- FadeState = FadeStates.Idle;
- //Close dialogs which are specific to the old game mode.
- List<pDialog> closeUs = new List<pDialog>();
- foreach (pDialog p in DialogQueue)
- if (p.GameModeSpecific)
- closeUs.Add(p);
- foreach (pDialog p in closeUs)
- p.Close();
- QueuedMode = newMode;
- loadQueuedMode(disposalDelay);
- if (FadeInComplete != null)
- FadeInComplete(null, null);
- });
- }
- internal static OsuModes LastMode = OsuModes.Unknown;
- /// <summary>
- /// Returns the LastMode entered if it's not the current mode and it has been set, otherwise returns a fallback mode.
- /// </summary>
- internal static OsuModes CallbackMode => LastMode != Mode && LastMode != OsuModes.Unknown ? LastMode : OsuModes.Menu;
- private static void loadQueuedMode(int disposalDelay = 0)
- {
- if (QueuedMode == OsuModes.Unknown) return;
- Debug.Print("Mode change in progress.");
- if (QueuedMode != OsuModes.Play || LastMode != OsuModes.Play)
- SetTitle();
- if (Mode != QueuedMode)
- Options.Expanded = false;
- IdleHandler.ForceActivity();
- switch (QueuedMode)
- {
- case OsuModes.Rank:
- case OsuModes.RankingTagCoop:
- case OsuModes.RankingTeam:
- case OsuModes.RankingVs:
- break;
- default:
- //Only clear this cache if we aren't entering the ranking screen. We want these samples to keep playing otherwise.
- AudioEngine.ClearSampleEvents();
- break;
- }
- PendingModeChange = true; //Allows skipping of sync frames after load.
- bool previousForceNonExclusive = ForceNonExclusive;
- LastMode = Mode;
- Mode = QueuedMode;
- if (RunningGameMode != null)
- {
- pGameMode gamemodeToDispose = RunningGameMode;
- if (disposalDelay > 0)
- {
- Scheduler.AddDelayed(delegate
- {
- Instance.Components.Remove(gamemodeToDispose);
- ((GameComponent)gamemodeToDispose).Dispose();
- }, disposalDelay);
- }
- else
- {
- Instance.Components.Remove(gamemodeToDispose);
- ((GameComponent)gamemodeToDispose).Dispose();
- }
- RunningGameMode = null;
- }
- OnNextModeChange?.Invoke();
- OnModeChange?.Invoke();
- OnNextModeChange = null;
- if (!Options.CanExpand)
- Options.PoppedOut = false;
- //This is after QueuedMode is assigned to Mode
- Debug.Assert(Mode == QueuedMode);
- if (Mode == OsuModes.Exit)
- {
- Instance.Exit();
- goto Finish;
- }
- if (LastMode != OsuModes.Unknown)
- {
- if (LastMode != Mode)
- SkinManager.LoadSkin();
- else
- SkinManager.LoadCursor(false);
- }
- BloomRenderer.RedTint = 0;
- ModeTime = 0;
- bool forceScreenSize = false;
- if (Mode == OsuModes.Edit)
- {
- if (EditorControl == null) EditorControl = new EditorControl();
- if (!MenuVisible)
- {
- MenuVisible = true;
- EditorControl.Parent = Form;
- forceScreenSize = true;
- }
- }
- else
- {
- if (EditorControl != null)
- {
- EditorControl.Dispose();
- EditorControl = null;
- }
- if (MenuVisible)
- {
- MenuVisible = false;
- forceScreenSize = true;
- }
- }
- forceScreenSize |= previousForceNonExclusive != ForceNonExclusive;
- if (!Tournament)
- {
- if (pendingScreenModeChange != null)
- pendingScreenModeChange();
- else if (forceScreenSize)
- SetScreenSize();
- pendingScreenModeChange = null;
- }
- GameField.Resize(GameBase.GameField.ScaleFactor, true);
- InputManager.FullTextEnabled = ChatEngine.IsVisible;
- InputManager.fullTextGameBuffer = string.Empty;
- AudioEngine.cachedSeekPending = false;
- bool showMusicControls = false;
- ForceGC(true);
- bool allowMaximize = false;
- switch (Mode)
- {
- case OsuModes.Edit:
- AudioEngine.ResetAudioTrack();
- AudioEngine.Stop();
- RunningGameMode = new Editor(Instance);
- break;
- case OsuModes.Play:
- if (LastMode == OsuModes.MatchSetup || PlayerVs.Match != null)
- RunningGameMode = new PlayerVs(MatchSetup.Match);
- else if (TestMode)
- RunningGameMode = new PlayerTest();
- else if (InputManager.ReplayMode || InputManager.ReplayStreaming || ModManager.CheckActive(Mods.Autoplay))
- RunningGameMode = new ReplayWatcher();
- else
- RunningGameMode = new Player();
- break;
- case OsuModes.SelectPlay:
- case OsuModes.SelectEdit:
- case OsuModes.SelectMulti:
- allowMaximize = true;
- //check for new beatmaps once after starting osu!
- if (BeatmapImport.DoNewBeatmapCheck ||
- (LastMode != OsuModes.BeatmapImport && BeatmapManager.Beatmaps.Count == 0))
- {
- LastMode = Mode;
- RunningGameMode = new BeatmapImport(Instance);
- Mode = OsuModes.BeatmapImport;
- }
- else
- RunningGameMode = new SongSelection(Instance);
- break;
- case OsuModes.SelectDrawings:
- allowMaximize = true;
- RunningGameMode = new Drawings(Instance);
- break;
- case OsuModes.OptionsOffsetWizard:
- allowMaximize = true;
- showMusicControls = true;
- RunningGameMode = new OptionsOffsetWizard(Instance);
- break;
- case OsuModes.Menu:
- allowMaximize = true;
- if (LastMode != OsuModes.Unknown) Menu.FirstLoad = false;
- showMusicControls = true;
- RunningGameMode = new Menu(Instance);
- break;
- case OsuModes.Lobby:
- allowMaximize = true;
- showMusicControls = true;
- RunningGameMode = new Lobby(Instance);
- break;
- case OsuModes.MatchSetup:
- //check for new beatmaps once after starting osu!
- if (BeatmapImport.DoNewBeatmapCheck)
- {
- LastMode = Mode;
- RunningGameMode = new BeatmapImport(Instance);
- Mode = OsuModes.BeatmapImport;
- }
- else
- RunningGameMode = new MatchSetup(Instance);
- break;
- case OsuModes.OnlineSelection:
- allowMaximize = true;
- RunningGameMode = new OnlineSelection(Instance);
- break;
- case OsuModes.RankingVs:
- RunningGameMode = new RankingVs(Instance);
- break;
- case OsuModes.RankingTagCoop:
- RunningGameMode = new RankingTagCoop(Instance);
- break;
- case OsuModes.RankingTeam:
- RunningGameMode = new RankingTeamVs(Instance);
- break;
- case OsuModes.Rank:
- RunningGameMode = new Ranking(Instance);
- break;
- case OsuModes.BeatmapImport:
- RunningGameMode = new BeatmapImport(Instance);
- break;
- case OsuModes.PackageUpdater:
- RunningGameMode = new PackageUpdater(Instance);
- break;
- case OsuModes.Benchmark:
- RunningGameMode = new Benchmark(Instance);
- break;
- case OsuModes.Tourney:
- RunningGameMode = new osu.GameModes.Other.Tournament.Tournament(Instance);
- break;
- case OsuModes.Charts:
- RunningGameMode = new Charts();
- break;
- case OsuModes.Update:
- OsuMain.ForceUpdate();
- Instance.Exit();
- goto Finish;
- case OsuModes.Busy:
- goto Finish;
- }
- if (Form.FormBorderStyle != FormBorderStyle.None)
- Form.MaximizeBox = allowMaximize;
- MusicControl.ShowControls = showMusicControls;
- UpdateClientBounds();
- Instance.Components.Add(RunningGameMode);
- RunningGameMode.Initialize();
- Debug.Print("RunningGameMode is now {0} (was {1})", RunningGameMode, LastMode);
- Finish:
- if (QueuedMode == Mode)
- QueuedMode = OsuModes.Unknown;
- }
- internal static void LoadComplete()
- {
- BanchoClient.UpdateStatus();
- BeginFadeIn();
- ChatEngine.UpdateNowPlaying(false, false);
- }
- internal static void BeginFadeIn()
- {
- if (FadeState != FadeStates.Idle)
- fadeLevel = 140;
- FadeState = FadeStates.FadeIn;
- }
- #endregion
- #region User Input Handling
- internal static double ElapsedMilliseconds;
- private static bool localMenuActive;
- internal static bool TestMode;
- internal static int TestTime;
- private readonly string StartupNewFiles;
- #endregion
- #region Events
- internal static event EventHandler FadeInComplete;
- internal static event EventHandler FadeOutComplete;
- #endregion
- //private static readonly Queue<VoidDelegate> schedulerQueue = new Queue<VoidDelegate>();
- internal static readonly Scheduler Scheduler = new Scheduler();
- internal static readonly ThreadedScheduler BackgroundScheduler = new ThreadedScheduler();
- internal static readonly Scheduler GraphicsScheduler = new Scheduler();
- internal static pDialog ActiveDialog;
- private static TextInputControl ActiveDialogMutedTextControl;
- internal static System.Drawing.Rectangle ClientBounds;
- private static double fadeOutRate = 8;
- private static double fadeInRate = 4;
- internal static int SystemResolutionHeight;
- internal static int SystemResolutionWidth;
- internal static pTooltip ToolTip;
- /// <summary>
- /// The local user's user/panel object.
- /// </summary>
- internal static User User;
- private OsuDirect osuDirect;
- internal static void SetTitle()
- {
- string titleAddition = string.Empty;
- User current = StreamingManager.CurrentlySpectating;
- if (current != null)
- titleAddition += " (watching " + current.Name + ")";
- SetTitle(titleAddition);
- }
- internal static void SetTitle(string title)
- {
- Scheduler.Add(delegate
- {
- string t = (string.Format(@"osu!{0} {1} {2}", General.SUBVERSION, General.PUBLIC_NAME, title.Length > 0 ? @"- " + title : string.Empty)).Trim();
- if (Tournament && !TournamentManager)
- t += string.Format(@" Tournament Client {0}", TournamentClientId);
- if (TournamentManager)
- t += @" Tournament Manager";
- Instance.Window.Title = t;
- });
- }
- static bool isShowingLogin;
- internal static void ShowLogin(bool callback = false)
- {
- if (Tournament) return;
- if (isShowingLogin && !callback) return;
- isShowingLogin = true;
- if (!GameBase.Instance.IsActive || !startupThreadOperation.IsCompleted)
- {
- GameBase.Scheduler.AddDelayed(delegate { ShowLogin(true); }, 100);
- return;
- }
- MenuActive = true;
- Options.Expanded = true;
- Options.LoginOnly = true;
- MenuActive = false;
- isShowingLogin = false;
- }
- internal static OsuModes ReceiveFile(params string[] files)
- {
- if (BeatmapManager.Beatmaps == null)
- {
- Scheduler.Add(delegate { ReceiveFile(files); }, true);
- return OsuModes.Unknown;
- }
- if (files == null || files.Length == 0 || (files.Length == 1 && String.IsNullOrEmpty(files[0])))
- return OsuModes.Unknown;
- string firstFile = files[0];
- //Base the extension on the first file dragged.
- //This could fail if there are multiple filetypes, but the user shouldn't be doing this.
- FileType ext = GeneralHelper.GetFileType(firstFile);
- try
- {
- switch (ext)
- {
- case FileType.BeatmapPackage2:
- //TODO: reimplement
- //string newPath = Application.StartupPath + "/Songs/" + Path.GetFileName(files);
- //BeatmapManager.ChangedPackages.Add(newPath);
- //goto case "osz";
- case FileType.BeatmapPackage:
- case FileType.Zip:
- string songs_fullpath = Path.GetFullPath(BeatmapManager.SongsDirectory);
- foreach (string f in files)
- {
- string filename = Path.GetFileName(f);
- int charsOver = (songs_fullpath.Length + filename.Length) - GeneralHelper.MAX_PATH_LENGTH;
- if (charsOver > 0)
- {
- int newLength = filename.Length - charsOver;
- //Leave enough room for file chars + extension
- if (newLength > (ext != FileType.BeatmapPackage2 ? 3 : 4) + 1)
- {
- filename = filename.Remove(newLength) + Path.GetExtension(filename);
- }
- else
- {
- NotificationManager.ShowMessage("Error moving " + filename + ". Path is too long.", Color.Red, 1000);
- continue;
- }
- }
- string newPath = Path.Combine(BeatmapManager.SongsDirectory, filename);
- Beatmap beatmap = BeatmapManager.Beatmaps.Find(bm => bm.InOszContainer && bm.ContainingFolderAbsolute == newPath);
- if (beatmap != null)
- //in the case a map is already loaded, select it as the current map rather than attempt import.
- BeatmapManager.Current = beatmap;
- else if (GeneralHelper.FileMove(f, newPath))
- BeatmapImport.SignalBeatmapCheck(true);
- else
- {
- if (BeatmapManager.ChangedPackages.Contains(newPath))
- BeatmapManager.ChangedPackages.Remove(newPath);
- TopMostMessageBox.Show("Error moving file " + filename);
- return OsuModes.Unknown;
- }
- }
- switch (Mode)
- {
- case OsuModes.MatchSetup:
- case OsuModes.SelectEdit:
- case OsuModes.SelectMulti:
- case OsuModes.SelectDrawings:
- return Mode;
- case OsuModes.Edit:
- case OsuModes.Play:
- NotificationManager.ShowMessageMassive(
- "New beatmap available - visit song select to finish importing!", 1000);
- return OsuModes.Unknown;
- default:
- return OsuModes.SelectPlay;
- }
- #if P2P
- case FileType.OsuMagnet:
- OsuDirect.StartDownload(new P2PDirectDownload(filename, true));
- break;
- #endif
- case FileType.AudioTrack:
- BeatmapImport.SignalBeatmapCheck(true);
- foreach (string f in files)
- {
- string dest = Path.Combine(BeatmapManager.SongsDirectory, Path.GetFileName(f));
- GeneralHelper.FileDelete(dest);
- File.Copy(f, dest);
- }
- return OsuModes.SelectEdit;
- case FileType.Replay:
- {
- Score score = ScoreManager.ReadReplayFromFile(firstFile);
- switch (Mode)
- {
- case OsuModes.MatchSetup:
- case OsuModes.Edit:
- case OsuModes.Play:
- NotificationManager.ShowMessageMassive("Replay has been loaded.", 1000);
- return OsuModes.Unknown;
- }
- if (MatchSetup.Match != null)
- {
- NotificationManager.ShowMessageMassive("Replay has been loaded.", 1000);
- return OsuModes.Unknown;
- }
- if (score != null)
- {
- Beatmap b = BeatmapManager.GetBeatmapByChecksum(score.FileChecksum);
- if (BeatmapManager.Current != b)
- {
- BeatmapManager.Current = b;
- AudioEngine.LoadAudioForPreview(b, true, false);
- }
- InputManager.ReplayScore = score;
- InputManager.ReplayMode = true;
- return OsuModes.Rank;
- }
- return OsuModes.Unknown;
- }
- case FileType.Skin:
- foreach (string f in files)
- {
- string filename = Path.GetFileName(f);
- string filenameNoExt = Path.GetFileNameWithoutExtension(filename);
- try
- {
- string basePath = Path.Combine(SkinManager.SKINS_FOLDER, filenameNoExt);
- string path = Path.Combine(SkinManager.SKINS_FOLDER, filename);
- GeneralHelper.FileMove(f, path);
- string tempFolder = GeneralHelper.GetTempPath(filenameNoExt);
- Directory.CreateDirectory(tempFolder);
- FastZip fz = new FastZip();
- fz.ExtractZip(path, tempFolder, ".*");
- //Force removal of readonly flag.
- FileInfo myFile = new FileInfo(path);
- if ((myFile.Attributes & FileAttributes.ReadOnly) > 0)
- myFile.Attributes &= ~FileAttributes.ReadOnly;
- GeneralHelper.RecursiveMove(tempFolder, basePath);
- GeneralHelper.FileDelete(path);
- // So now we have the skin extracted in Skins/SkinName/
- // but they may still be in a subdirectory depending on how the skin was packaged.
- int maximumTries = 5;
- while (Directory.GetFiles(basePath).Length < 1 && maximumTries-- > 0)
- {
- string[] dirs = Directory.GetDirectories(basePath);
- GeneralHelper.RecursiveMove(dirs[0], basePath);
- }
- SkinManager.RefreshAvailableSkins();
- ConfigManager.sSkin.Value = filenameNoExt;
- SkinManager.LoadSkin(null, true);
- InputManager.ReplayMode = false;
- Options.Expanded = true;
- Options.ScrollTo(GameBase.Options.SkinSection);
- return OsuModes.Menu;
- }
- catch
- {
- NotificationManager.ShowMessage("Unable to import skin \"" + filename + "\".");
- }
- }
- return OsuModes.Unknown;
- case FileType.Image:
- case FileType.Video:
- if (Mode == OsuModes.Menu && (BanchoClient.Permission & Permissions.Supporter) > 0 && ext == FileType.Image)
- {
- SkinManager.CreateUserSkin();
- string dest = GeneralHelper.PathSanitise(Path.Combine(SkinManager.Current.FullPath, @"menu-background.jpg"));
- GeneralHelper.FileDelete(dest);
- File.Copy(firstFile, dest);
- SkinManager.LoadSkin(ConfigManager.sSkin, true);
- return OsuModes.Menu;
- }
- if (Mode != OsuModes.Edit)
- {
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.General_File_EnterEditor));
- return OsuModes.Unknown;
- }
- pDialogConfirmation d = new pDialogConfirmation("Would you like to use \"" + Path.GetFileName(firstFile) + "\" as your map's background?",
- delegate { Editor.Instance.Design.InsertBackground(firstFile); }, null);
- GameBase.ShowDialog(d);
- return OsuModes.Unknown;
- default:
- if (firstFile.StartsWith(@"osu://"))
- {
- if (BanchoClient.Connected)
- ChatEngine.HandleLink(firstFile);
- else
- {
- VoidDelegate del = null;
- del = delegate
- {
- ChatEngine.HandleLink(firstFile);
- BanchoClient.OnPermissionChange -= del;
- };
- BanchoClient.OnPermissionChange += del;
- }
- return OsuModes.Unknown;
- }
- if (!firstFile.StartsWith(@"-") && firstFile.Contains(@"."))
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.General_File_UnknownType) + @" (" + firstFile + @")");
- return OsuModes.Unknown;
- }
- }
- catch (Exception e)
- {
- NotificationManager.ShowMessage(LocalisationManager.GetString(OsuString.GameBase_FileImportError));
- ErrorSubmission.Submit(new OsuError(e) { Feedback = @"file handling" });
- }
- return OsuModes.Unknown;
- }
- internal static void PackageFile(string filename, string saveDirectory)
- {
- string exportFolder = EXPORT_FOLDER;
- Directory.CreateDirectory(exportFolder);
- string filepath = Path.Combine(exportFolder, GeneralHelper.WindowsFilenameStrip(filename));
- ZipConstants.DefaultCodePage = 932;
- FastZip fz = new FastZip();
- fz.CreateZip(filepath, saveDirectory, true, "[^z]+$");
- NotificationManager.ShowMessage(filename + " has been exported. Opening the Exports folder...", Color.YellowGreen, 6000);
- OpenFolder(exportFolder);
- }
- internal static void OpenFolderToFile(string filePath)
- {
- if (OsuMain.IsWine)
- OpenFolder(Path.GetDirectoryName(filePath));
- else
- Process.Start(@"explorer.exe", string.Format(@"/select,""{0}""", Path.GetFullPath(filePath)));
- }
- internal static void OpenFolder(string folderPath)
- {
- if (String.IsNullOrEmpty(folderPath)) return;
- if (folderPath[folderPath.Length - 1] != Path.DirectorySeparatorChar)
- folderPath += Path.DirectorySeparatorChar;
- GameBase.ProcessStart(folderPath);
- }
- [return: MarshalAs(UnmanagedType.Bool)]
- [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
- public static extern bool SetForegroundWindow(IntPtr hwnd);
- [SuppressUnmanagedCodeSecurityAttribute()]
- [DllImport(@"user32.dll")]
- internal static extern bool FlashWindow(IntPtr hwnd, bool bInvert);
- [DllImport(@"user32.dll")]
- public static extern bool GetLayeredWindowAttributes(IntPtr hwnd, out IntPtr pcrKey, out IntPtr pbAlpha, out IntPtr pdwFlags);
- internal static void FlashWindow()
- {
- if (GameBase.Tournament) return;
- try
- {
- if (ConfigManager.sChatAudibleHighlight)
- AudioEngine.PlaySample(@"match-start");
- Form.Invoke(new VoidDelegate(delegate { FlashWindow(Form.Handle, true); }));
- }
- catch { }
- }
- internal static void Restart(VoidDelegate restartAction = null)
- {
- if (restartAction != null) exitAction += restartAction;
- OsuMain.Restart = true;
- ChangeMode(OsuModes.Exit);
- }
- internal static bool IsFormOpacityHacked()
- {
- try
- {
- IntPtr pcr = IntPtr.Zero;
- IntPtr alpha = IntPtr.Zero;
- IntPtr flag = new IntPtr(0x00000002);//LWA_ALPHA
- if (GetLayeredWindowAttributes(Form.Handle, out pcr, out alpha, out flag))
- return alpha.ToInt32() < 255;
- }
- catch { }
- return false;
- }
- internal static MusicControl MusicControl;
- internal static Options Options;
- private static pSprite s_WidescreenLeft;
- private static pSprite s_WidescreenRight;
- private static SmartThreadPool mainThreadPool = new SmartThreadPool(new STPStartInfo()
- {
- AreThreadsBackground = true,
- IdleTimeout = 300000,
- MaxWorkerThreads = 32,
- MinWorkerThreads = 8
- });
- internal static IWorkItemResult RunBackgroundThread(VoidDelegate d)
- {
- return mainThreadPool.QueueWorkItem(delegate
- {
- try
- {
- d();
- }
- catch (Exception e)
- {
- softHandle(e);
- }
- });
- }
- /// <summary>
- /// Ensures the delegate function is run in non-exclusive display mode (for windows forms etc.)
- /// </summary>
- private static void RunNonExclusive(VoidDelegate run)
- {
- bool requireExclusiveExit = GameBase.IsFullscreen && !GameBase.ForceNonExclusive;
- if (requireExclusiveExit)
- {
- GameBase.ForcefullyLeaveExclusiveFullscreen();
- GameBase.ResizeGL(true);
- }
- run();
- if (requireExclusiveExit)
- {
- GameBase.ResizeGL(false);
- // TopMost is already true at this point from the main loop, we however need to touch it again so that windows understands.
- GameBase.Form.TopMost = true;
- }
- }
- internal static Thread MainThread;
- private bool ChildrenUpdated;
- public static int LastForcedGC;
- internal static Obfuscated<string> UniqueCheck = "unknown";
- internal static Obfuscated<string> UniqueId = "unknown";
- internal static Obfuscated<string> UniqueId2 = "unknown";
- internal static bool BenchmarkMode;
- internal static string IpcChannelName = "osu!";
- public static bool BackgroundLoading;
- internal static void ForceGC(bool ignoreTime = false)
- {
- if (GameBase.Time - LastForcedGC < 5000 && !ignoreTime) return;
- LastForcedGC = GameBase.Time;
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
- internal static void ProcessStart(string process, string flags = null)
- {
- if (Tournament) return;
- #if ARCADE
- //We don't want the user to be able to start any external processes.
- //This includes the ability to open URLs (which is handled through this method).
- return;
- #endif
- RunBackgroundThread(delegate
- {
- try
- {
- ProcessStartInfo psi = new ProcessStartInfo(process, flags);
- Process.Start(psi);
- }
- catch (Exception)
- { }
- });
- }
- public static int IdleTime
- {
- get
- {
- return GameBase.Time - InputManager.LastActionTime;
- }
- }
- public static bool HasPendingDialog { get { return ActiveDialog != null || DialogQueue.Count > 0; } }
- public static bool UseHighResolutionSprites { get { return (WindowManager.Height >= 800 || ConfigManager.sHighResolution) && !ConfigManager.sLowResolution && OsuGlControl.MaxTextureSize > 2048; } }
- public static bool NewGraphicsAvailable;
- internal static Size InitialDesktopResolution;
- internal static System.Drawing.Point InitialDesktopLocation;
- public static long TotalFramesRendered;
- #if !Public
- private static pSprite testBuildOverlay;
- private static pText testBuildVersion;
- #endif
- internal static int ChangeAllowance;
- internal static Process[] Processes;
- public static bool IsWindows81
- {
- get
- {
- OperatingSystem os = Environment.OSVersion;
- return os.Platform == PlatformID.Win32NT && os.Version.Major >= 6 && os.Version.Minor >= 3;
- }
- }
- static bool minimizedToTray;
- internal static bool checkFilesMatched;
- internal static bool IsFullscreen;
- private static Size clientSize;
- internal static bool IsFillingScreen
- {
- get
- {
- return ConfigManager.sFullscreen || ConfigManager.sLetterboxing || (clientSize.Width >= InitialDesktopResolution.Width && clientSize.Height >= InitialDesktopResolution.Height);
- }
- }
- internal static bool ForceNonExclusive
- {
- get
- {
- switch (Mode)
- {
- case OsuModes.SelectEdit:
- case OsuModes.Edit:
- return true;
- case OsuModes.Play:
- if (TestMode)
- return true;
- break;
- }
- return MenuVisible || !ConfigManager.sFullscreen;
- }
- }
- internal static int ClientSizeAdjustment = 0;
- private List<GameComponent> Components = new List<GameComponent>();
- private static IWorkItemResult startupThreadOperation;
- public static bool MinimizedToTray
- {
- get
- {
- return minimizedToTray;
- }
- set
- {
- //don't allow boss mode when running under wine (reported failure https://osu.ppy.sh/forum/t/362773)
- if (OsuMain.IsWine) return;
- if (value == minimizedToTray) return;
- minimizedToTray = value;
- if (minimizedToTray)
- {
- if (notifyIcon == null)
- {
- notifyIcon = new NotifyIcon();
- notifyIcon.Icon = Form.Icon;
- notifyIcon.Click += (obj, e) => { MinimizedToTray = false; };
- }
- notifyIcon.Visible = true;
- if (ConfigManager.sBossKeyFirstActivation)
- {
- notifyIcon.ShowBalloonTip(10000, LocalisationManager.GetString(OsuString.BossKeyActivated), LocalisationManager.GetString(OsuString.BossKeyActivated_Tooltip), ToolTipIcon.Info);
- ConfigManager.sBossKeyFirstActivation.Value = false;
- }
- Form.WindowState = FormWindowState.Minimized;
- Form.Visible = false;
- Player p = Player.Instance;
- if (p != null && !(p is PlayerVs && Player.Loaded) && !AudioEngine.Paused && !Player.Paused && !InputManager.ReplayMode)
- p.TogglePause();
- bossKeyRestoreVolume = AudioEngine.VolumeMaster.Value;
- AudioEngine.VolumeMaster.Value = 0;
- }
- else
- {
- Form.Visible = true;
- Form.WindowState = FormWindowState.Normal;
- Form.ShowInTaskbar = true;
- notifyIcon.Visible = false;
- BringToFront();
- AudioEngine.VolumeMaster.Value = bossKeyRestoreVolume;
- }
- }
- }
- /// <summary>
- /// Are we able to (forcefully) reload the current game mode without having an adverse effect on the overall state of osu!?
- /// </summary>
- public static bool ModeCanReload
- {
- get
- {
- switch (Mode)
- {
- case OsuModes.Play:
- return ModManager.CheckActive(Mods.Autoplay);
- case OsuModes.Rank:
- case OsuModes.RankingVs:
- case OsuModes.RankingTeam:
- case OsuModes.RankingTagCoop:
- return false;
- }
- return true;
- }
- }
- }
- public enum OsuModes
- {
- Menu,
- Edit,
- Play,
- Exit,
- SelectEdit,
- SelectPlay,
- SelectDrawings,
- Rank,
- Update,
- Busy,
- Unknown,
- Lobby,
- MatchSetup,
- SelectMulti,
- RankingVs,
- OnlineSelection,
- OptionsOffsetWizard,
- RankingTagCoop,
- RankingTeam,
- BeatmapImport,
- PackageUpdater,
- Benchmark,
- Tourney,
- Charts
- };
- internal enum FadeStates
- {
- FadeOut,
- FadeIn,
- Idle,
- WaitingLoad,
- };
- public enum FrameSync
- {
- VSync = 1,
- Limit120 = 0,
- Unlimited = 2,
- CompletelyUnlimited = 4,
- Custom = 5
- };
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement