diff --git a/osu.Desktop/OsuGameDesktop.cs b/osu.Desktop/OsuGameDesktop.cs
index 64adcecba4..a4270f22b4 100644
--- a/osu.Desktop/OsuGameDesktop.cs
+++ b/osu.Desktop/OsuGameDesktop.cs
@@ -12,6 +12,7 @@ using osu.Framework.Platform;
using osu.Game;
using OpenTK.Input;
using Microsoft.Win32;
+using osu.Desktop.Updater;
using osu.Framework.Platform.Windows;
namespace osu.Desktop
@@ -38,6 +39,52 @@ namespace osu.Desktop
}
}
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ if (!noVersionOverlay)
+ {
+ LoadComponentAsync(new VersionManager { Depth = int.MinValue }, v =>
+ {
+ Add(v);
+ v.State = Visibility.Visible;
+ });
+
+#if NET_FRAMEWORK
+ Add(new SquirrelUpdateManager());
+#else
+ Add(new SimpleUpdateManager());
+#endif
+ }
+ }
+
+ public override void SetHost(GameHost host)
+ {
+ base.SetHost(host);
+ var desktopWindow = host.Window as DesktopGameWindow;
+ if (desktopWindow != null)
+ {
+ desktopWindow.CursorState |= CursorState.Hidden;
+
+ desktopWindow.SetIconFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico"));
+ desktopWindow.Title = Name;
+
+ desktopWindow.FileDrop += fileDrop;
+ }
+ }
+
+ private void fileDrop(object sender, FileDropEventArgs e)
+ {
+ var filePaths = new[] { e.FileName };
+
+ var firstExtension = Path.GetExtension(filePaths.First());
+
+ if (filePaths.Any(f => Path.GetExtension(f) != firstExtension)) return;
+
+ Task.Factory.StartNew(() => Import(filePaths), TaskCreationOptions.LongRunning);
+ }
+
///
/// A method of accessing an osu-stable install in a controlled fashion.
///
@@ -77,45 +124,5 @@ namespace osu.Desktop
{
}
}
-
- protected override void LoadComplete()
- {
- base.LoadComplete();
-
- if (!noVersionOverlay)
- {
- LoadComponentAsync(new VersionManager { Depth = int.MinValue }, v =>
- {
- Add(v);
- v.State = Visibility.Visible;
- });
- }
- }
-
- public override void SetHost(GameHost host)
- {
- base.SetHost(host);
- var desktopWindow = host.Window as DesktopGameWindow;
- if (desktopWindow != null)
- {
- desktopWindow.CursorState |= CursorState.Hidden;
-
- desktopWindow.SetIconFromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico"));
- desktopWindow.Title = Name;
-
- desktopWindow.FileDrop += fileDrop;
- }
- }
-
- private void fileDrop(object sender, FileDropEventArgs e)
- {
- var filePaths = new[] { e.FileName };
-
- var firstExtension = Path.GetExtension(filePaths.First());
-
- if (filePaths.Any(f => Path.GetExtension(f) != firstExtension)) return;
-
- Task.Factory.StartNew(() => Import(filePaths), TaskCreationOptions.LongRunning);
- }
}
}
diff --git a/osu.Desktop/Overlays/VersionManager.cs b/osu.Desktop/Overlays/VersionManager.cs
index bc1faec822..1129969694 100644
--- a/osu.Desktop/Overlays/VersionManager.cs
+++ b/osu.Desktop/Overlays/VersionManager.cs
@@ -91,10 +91,6 @@ namespace osu.Desktop.Overlays
}
}
};
-
-#if NET_FRAMEWORK
- Add(new SquirrelUpdateManager());
-#endif
}
protected override void LoadComplete()
diff --git a/osu.Desktop/Updater/SimpleUpdateManager.cs b/osu.Desktop/Updater/SimpleUpdateManager.cs
new file mode 100644
index 0000000000..cda8e6a7ca
--- /dev/null
+++ b/osu.Desktop/Updater/SimpleUpdateManager.cs
@@ -0,0 +1,103 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using osu.Framework;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.IO.Network;
+using osu.Framework.Platform;
+using osu.Game;
+using osu.Game.Graphics;
+using osu.Game.Overlays;
+using osu.Game.Overlays.Notifications;
+
+namespace osu.Desktop.Updater
+{
+ ///
+ /// An update manager that shows notifications if a newer release is detected.
+ /// Installation is left up to the user.
+ ///
+ internal class SimpleUpdateManager : CompositeDrawable
+ {
+ private NotificationOverlay notificationOverlay;
+ private string version;
+ private GameHost host;
+
+ [BackgroundDependencyLoader]
+ private void load(NotificationOverlay notification, OsuGameBase game, GameHost host)
+ {
+ notificationOverlay = notification;
+
+ this.host = host;
+ version = game.Version;
+
+ if (game.IsDeployedBuild)
+ Schedule(() => Task.Run(() => checkForUpdateAsync()));
+ }
+
+ private async void checkForUpdateAsync()
+ {
+ var releases = new JsonWebRequest("https://api.github.com/repos/ppy/osu/releases/latest");
+ await releases.PerformAsync();
+
+ var latest = releases.ResponseObject;
+
+ if (latest.TagName != version)
+ {
+ notificationOverlay.Post(new SimpleNotification
+ {
+ Text = $"A newer release of osu! has been found ({version} → {latest.TagName}).\n\n"
+ + "Click here to download the new version, which can be installed over the top of your existing installation",
+ Icon = FontAwesome.fa_upload,
+ Activated = () =>
+ {
+ host.OpenUrlExternally(getBestUrl(latest));
+ return true;
+ }
+ });
+ }
+ }
+
+ private string getBestUrl(GitHubRelease release)
+ {
+ GitHubAsset bestAsset = null;
+
+ switch (RuntimeInfo.OS)
+ {
+ case RuntimeInfo.Platform.Windows:
+ bestAsset = release.Assets?.FirstOrDefault(f => f.Name.EndsWith(".exe"));
+ break;
+ case RuntimeInfo.Platform.MacOsx:
+ bestAsset = release.Assets?.FirstOrDefault(f => f.Name.EndsWith(".dmg"));
+ break;
+ }
+
+ return bestAsset?.BrowserDownloadUrl ?? release.HtmlUrl;
+ }
+
+ public class GitHubRelease
+ {
+ [JsonProperty("html_url")]
+ public string HtmlUrl { get; set; }
+
+ [JsonProperty("tag_name")]
+ public string TagName { get; set; }
+
+ [JsonProperty("assets")]
+ public List Assets { get; set; }
+ }
+
+ public class GitHubAsset
+ {
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("browser_download_url")]
+ public string BrowserDownloadUrl { get; set; }
+ }
+ }
+}
diff --git a/osu.Desktop/Overlays/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs
similarity index 97%
rename from osu.Desktop/Overlays/SquirrelUpdateManager.cs
rename to osu.Desktop/Updater/SquirrelUpdateManager.cs
index ea86d2f028..81da26cff2 100644
--- a/osu.Desktop/Overlays/SquirrelUpdateManager.cs
+++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs
@@ -3,6 +3,7 @@
#if NET_FRAMEWORK
using System;
+using System.Threading.Tasks;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
@@ -16,7 +17,7 @@ using OpenTK;
using OpenTK.Graphics;
using Squirrel;
-namespace osu.Desktop.Overlays
+namespace osu.Desktop.Updater
{
public class SquirrelUpdateManager : Component
{
@@ -35,7 +36,7 @@ namespace osu.Desktop.Overlays
notificationOverlay = notification;
if (game.IsDeployedBuild)
- Schedule(() => checkForUpdateAsync());
+ Schedule(() => Task.Run(() => checkForUpdateAsync()));
}
private async void checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null)
diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs
index e488dacf80..fd24e4297b 100644
--- a/osu.Game/Beatmaps/BeatmapManager.cs
+++ b/osu.Game/Beatmaps/BeatmapManager.cs
@@ -339,6 +339,8 @@ namespace osu.Game.Beatmaps
{
var beatmapInfos = new List();
+ bool invalidateOnlineIDs = false;
+
foreach (var name in reader.Filenames.Where(f => f.EndsWith(".osu")))
{
using (var raw = reader.GetStream(name))
@@ -355,9 +357,18 @@ namespace osu.Game.Beatmaps
beatmap.BeatmapInfo.Hash = ms.ComputeSHA2Hash();
beatmap.BeatmapInfo.MD5Hash = ms.ComputeMD5Hash();
- // check that no existing beatmap exists that is imported with the same online beatmap ID. if so, give it precedence.
- if (beatmap.BeatmapInfo.OnlineBeatmapID.HasValue && QueryBeatmap(b => b.OnlineBeatmapID.Value == beatmap.BeatmapInfo.OnlineBeatmapID.Value) != null)
- beatmap.BeatmapInfo.OnlineBeatmapID = null;
+ if (beatmap.BeatmapInfo.OnlineBeatmapID.HasValue)
+ {
+ var ourId = beatmap.BeatmapInfo.OnlineBeatmapID;
+
+ // check that no existing beatmap in database exists that is imported with the same online beatmap ID. if so, give it precedence.
+ if (QueryBeatmap(b => b.OnlineBeatmapID.Value == ourId) != null)
+ beatmap.BeatmapInfo.OnlineBeatmapID = null;
+
+ // check that no other beatmap in this imported set has a conflicting online beatmap ID. If so, presume *all* are incorrect.
+ if (beatmapInfos.Any(b => b.OnlineBeatmapID == ourId))
+ invalidateOnlineIDs = true;
+ }
RulesetInfo ruleset = rulesets.GetRuleset(beatmap.BeatmapInfo.RulesetID);
@@ -375,6 +386,9 @@ namespace osu.Game.Beatmaps
}
}
+ if (invalidateOnlineIDs)
+ beatmapInfos.ForEach(b => b.OnlineBeatmapID = null);
+
return beatmapInfos;
}
diff --git a/osu.Game/OsuGameBase.cs b/osu.Game/OsuGameBase.cs
index 246229a794..c1d5ae581e 100644
--- a/osu.Game/OsuGameBase.cs
+++ b/osu.Game/OsuGameBase.cs
@@ -20,6 +20,7 @@ using osu.Game.Graphics.Cursor;
using osu.Game.Online.API;
using osu.Framework.Graphics.Performance;
using osu.Framework.Graphics.Textures;
+using osu.Framework.Input;
using osu.Framework.Logging;
using osu.Game.Audio;
using osu.Game.Database;
@@ -30,6 +31,7 @@ using osu.Game.IO;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
+using OpenTK.Input;
using DebugUtils = osu.Game.Utils.DebugUtils;
namespace osu.Game
@@ -98,6 +100,8 @@ namespace osu.Game
private DatabaseContextFactory contextFactory;
+ protected override UserInputManager CreateUserInputManager() => new OsuUserInputManager();
+
[BackgroundDependencyLoader]
private void load()
{
@@ -267,5 +271,31 @@ namespace osu.Game
return copy;
}
}
+
+ private class OsuUserInputManager : UserInputManager
+ {
+ protected override MouseButtonEventManager CreateButtonManagerFor(MouseButton button)
+ {
+ switch (button)
+ {
+ case MouseButton.Right:
+ return new RightMouseManager(button);
+ }
+
+ return base.CreateButtonManagerFor(button);
+ }
+
+ private class RightMouseManager : MouseButtonEventManager
+ {
+ public RightMouseManager(MouseButton button)
+ : base(button)
+ {
+ }
+
+ public override bool EnableDrag => true; // allow right-mouse dragging for absolute scroll in scroll containers.
+ public override bool EnableClick => false;
+ public override bool ChangeFocusOnClick => false;
+ }
+ }
}
}