mirror of
https://github.com/ppy/osu.git
synced 2026-05-16 06:52:36 +08:00
Compare commits
47 Commits
2018.712.0
...
2018.713.0
@@ -111,6 +111,8 @@ namespace osu.Desktop.Overlays
|
||||
|
||||
private class UpdateCompleteNotification : SimpleNotification
|
||||
{
|
||||
public override bool IsImportant => true;
|
||||
|
||||
public UpdateCompleteNotification(string version, Action<string> openUrl = null)
|
||||
{
|
||||
Text = $"You are now running osu!lazer {version}.\nClick to see what's new!";
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace osu.Game.Rulesets.Osu
|
||||
|
||||
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
|
||||
{
|
||||
new KeyBinding(InputKey.Z, OsuAction.LeftButton),
|
||||
new KeyBinding(InputKey.X, OsuAction.RightButton),
|
||||
new KeyBinding(InputKey.A, OsuAction.LeftButton),
|
||||
new KeyBinding(InputKey.S, OsuAction.RightButton),
|
||||
new KeyBinding(InputKey.MouseLeft, OsuAction.LeftButton),
|
||||
new KeyBinding(InputKey.MouseRight, OsuAction.RightButton),
|
||||
};
|
||||
|
||||
@@ -45,6 +45,11 @@ namespace osu.Game.Beatmaps
|
||||
/// </summary>
|
||||
public event Action<DownloadBeatmapSetRequest> BeatmapDownloadBegan;
|
||||
|
||||
/// <summary>
|
||||
/// Fired when a beatmap load is requested (into the interactive game UI).
|
||||
/// </summary>
|
||||
public Action<BeatmapSetInfo> PresentBeatmap;
|
||||
|
||||
/// <summary>
|
||||
/// A default representation of a WorkingBeatmap to use when no beatmap is available.
|
||||
/// </summary>
|
||||
@@ -92,7 +97,7 @@ namespace osu.Game.Beatmaps
|
||||
// by setting the model here, we can update the noline set id below.
|
||||
b.BeatmapSet = model;
|
||||
|
||||
fetchAndPopulateOnlineIDs(b);
|
||||
fetchAndPopulateOnlineIDs(b, model.Beatmaps);
|
||||
}
|
||||
|
||||
// check if a set already exists with the same online id, delete if it does.
|
||||
@@ -163,12 +168,20 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
Task.Factory.StartNew(() =>
|
||||
{
|
||||
BeatmapSetInfo importedBeatmap;
|
||||
|
||||
// This gets scheduled back to the update thread, but we want the import to run in the background.
|
||||
using (var stream = new MemoryStream(data))
|
||||
using (var archive = new ZipArchiveReader(stream, beatmapSetInfo.ToString()))
|
||||
Import(archive);
|
||||
importedBeatmap = Import(archive);
|
||||
|
||||
downloadNotification.CompletionClickAction = () =>
|
||||
{
|
||||
PresentBeatmap?.Invoke(importedBeatmap);
|
||||
return true;
|
||||
};
|
||||
downloadNotification.State = ProgressNotificationState.Completed;
|
||||
|
||||
currentDownloads.Remove(request);
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
};
|
||||
@@ -396,9 +409,10 @@ namespace osu.Game.Beatmaps
|
||||
/// Query the API to populate mising OnlineBeatmapID / OnlineBeatmapSetID properties.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to populate.</param>
|
||||
/// <param name="otherBeatmaps">The other beatmaps contained within this set.</param>
|
||||
/// <param name="force">Whether to re-query if the provided beatmap already has populated values.</param>
|
||||
/// <returns>True if population was successful.</returns>
|
||||
private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, bool force = false)
|
||||
private bool fetchAndPopulateOnlineIDs(BeatmapInfo beatmap, IEnumerable<BeatmapInfo> otherBeatmaps, bool force = false)
|
||||
{
|
||||
if (!force && beatmap.OnlineBeatmapID != null && beatmap.BeatmapSet.OnlineBeatmapSetID != null)
|
||||
return true;
|
||||
@@ -418,6 +432,12 @@ namespace osu.Game.Beatmaps
|
||||
|
||||
Logger.Log($"Successfully mapped to {res.OnlineBeatmapSetID} / {res.OnlineBeatmapID}.", LoggingTarget.Database);
|
||||
|
||||
if (otherBeatmaps.Any(b => b.OnlineBeatmapID == res.OnlineBeatmapID))
|
||||
{
|
||||
Logger.Log("Another beatmap in the same set already mapped to this ID. We'll skip adding it this time.", LoggingTarget.Database);
|
||||
return false;
|
||||
}
|
||||
|
||||
beatmap.BeatmapSet.OnlineBeatmapSetID = res.OnlineBeatmapSetID;
|
||||
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
|
||||
return true;
|
||||
|
||||
@@ -9,14 +9,14 @@ using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
public class DifficultyColouredContainer : Container, IHasAccentColour
|
||||
public abstract class DifficultyColouredContainer : Container, IHasAccentColour
|
||||
{
|
||||
public Color4 AccentColour { get; set; }
|
||||
|
||||
private readonly BeatmapInfo beatmap;
|
||||
private OsuColour palette;
|
||||
|
||||
public DifficultyColouredContainer(BeatmapInfo beatmap)
|
||||
protected DifficultyColouredContainer(BeatmapInfo beatmap)
|
||||
{
|
||||
this.beatmap = beatmap;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,14 @@
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
@@ -14,7 +18,8 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
private readonly BeatmapInfo beatmap;
|
||||
|
||||
public DifficultyIcon(BeatmapInfo beatmap) : base(beatmap)
|
||||
public DifficultyIcon(BeatmapInfo beatmap)
|
||||
: base(beatmap)
|
||||
{
|
||||
if (beatmap == null)
|
||||
throw new ArgumentNullException(nameof(beatmap));
|
||||
@@ -28,16 +33,29 @@ namespace osu.Game.Beatmaps.Drawables
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteIcon
|
||||
new CircularContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Scale = new Vector2(0.84f),
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = AccentColour,
|
||||
Icon = FontAwesome.fa_circle
|
||||
Masking = true,
|
||||
EdgeEffect = new EdgeEffectParameters
|
||||
{
|
||||
Colour = Color4.Black.Opacity(0.08f),
|
||||
Type = EdgeEffectType.Shadow,
|
||||
Radius = 5,
|
||||
},
|
||||
Child = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = AccentColour,
|
||||
},
|
||||
},
|
||||
new ConstrainedIconContainer
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// the null coalesce here is only present to make unit tests work (ruleset dlls aren't copied correctly for testing at the moment)
|
||||
Icon = beatmap.Ruleset?.CreateInstance().CreateIcon() ?? new SpriteIcon { Icon = FontAwesome.fa_question_circle_o }
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace osu.Game.Database
|
||||
/// <param name="paths">One or more archive locations on disk.</param>
|
||||
public void Import(params string[] paths)
|
||||
{
|
||||
var notification = new ProgressNotification
|
||||
var notification = new ImportNotification
|
||||
{
|
||||
Text = "Import is initialising...",
|
||||
Progress = 0,
|
||||
@@ -407,5 +407,10 @@ namespace osu.Game.Database
|
||||
return new LegacyFilesystemReader(path);
|
||||
throw new InvalidFormatException($"{path} is not a valid archive");
|
||||
}
|
||||
|
||||
private class ImportNotification : ProgressNotification
|
||||
{
|
||||
public override bool IsImportant => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,11 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
protected virtual bool PlaySamplesOnStateChange => true;
|
||||
|
||||
protected override bool BlockPassThroughKeyboard => true;
|
||||
|
||||
private PreviewTrackManager previewTrackManager;
|
||||
|
||||
|
||||
protected readonly Bindable<OverlayActivation> OverlayActivationMode = new Bindable<OverlayActivation>(OverlayActivation.All);
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
@@ -69,10 +72,13 @@ namespace osu.Game.Graphics.Containers
|
||||
|
||||
public virtual bool OnPressed(GlobalAction action)
|
||||
{
|
||||
if (action == GlobalAction.Back)
|
||||
switch (action)
|
||||
{
|
||||
State = Visibility.Hidden;
|
||||
return true;
|
||||
case GlobalAction.Back:
|
||||
State = Visibility.Hidden;
|
||||
return true;
|
||||
case GlobalAction.Select:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace osu.Game.Migrations
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.Sql("DELETE FROM KeyBinding WHERE RulesetID = 1");
|
||||
Logger.Log("osu!taiko bindings have been reset due to new defaults", LoggingTarget.Runtime, LogLevel.Important);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
|
||||
+57
-29
@@ -19,10 +19,12 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Overlays.Notifications;
|
||||
@@ -33,6 +35,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Skinning;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Overlays.Volume;
|
||||
using osu.Game.Screens.Select;
|
||||
|
||||
namespace osu.Game
|
||||
{
|
||||
@@ -178,6 +181,41 @@ namespace osu.Game
|
||||
/// <param name="setId">The set to display.</param>
|
||||
public void ShowBeatmapSet(int setId) => beatmapSetOverlay.FetchAndShowBeatmapSet(setId);
|
||||
|
||||
/// <summary>
|
||||
/// Present a beatmap at song select.
|
||||
/// </summary>
|
||||
/// <param name="beatmap">The beatmap to select.</param>
|
||||
public void PresentBeatmap(BeatmapSetInfo beatmap)
|
||||
{
|
||||
CloseAllOverlays(false);
|
||||
|
||||
void setBeatmap()
|
||||
{
|
||||
if (Beatmap.Disabled)
|
||||
{
|
||||
Schedule(setBeatmap);
|
||||
return;
|
||||
}
|
||||
|
||||
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(beatmap.Beatmaps.First());
|
||||
}
|
||||
|
||||
switch (currentScreen)
|
||||
{
|
||||
case SongSelect _:
|
||||
break;
|
||||
default:
|
||||
// navigate to song select if we are not already there.
|
||||
var menu = (MainMenu)intro.ChildScreen;
|
||||
|
||||
menu.MakeCurrent();
|
||||
menu.LoadToSolo();
|
||||
break;
|
||||
}
|
||||
|
||||
setBeatmap();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show a user's profile as an overlay.
|
||||
/// </summary>
|
||||
@@ -244,6 +282,7 @@ namespace osu.Game
|
||||
BeatmapManager.PostNotification = n => notifications?.Post(n);
|
||||
|
||||
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
||||
BeatmapManager.PresentBeatmap = PresentBeatmap;
|
||||
|
||||
AddRange(new Drawable[]
|
||||
{
|
||||
@@ -322,24 +361,6 @@ namespace osu.Game
|
||||
dependencies.Cache(notifications);
|
||||
dependencies.Cache(dialogOverlay);
|
||||
|
||||
// ensure only one of these overlays are open at once.
|
||||
var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct };
|
||||
overlays.AddRange(singleDisplayOverlays);
|
||||
|
||||
foreach (var overlay in singleDisplayOverlays)
|
||||
{
|
||||
overlay.StateChanged += state =>
|
||||
{
|
||||
if (state == Visibility.Hidden) return;
|
||||
|
||||
foreach (var c in singleDisplayOverlays)
|
||||
{
|
||||
if (c == overlay) continue;
|
||||
c.State = Visibility.Hidden;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var singleDisplaySideOverlays = new OverlayContainer[] { settings, notifications };
|
||||
overlays.AddRange(singleDisplaySideOverlays);
|
||||
|
||||
@@ -348,12 +369,7 @@ namespace osu.Game
|
||||
overlay.StateChanged += state =>
|
||||
{
|
||||
if (state == Visibility.Hidden) return;
|
||||
|
||||
foreach (var c in singleDisplaySideOverlays)
|
||||
{
|
||||
if (c == overlay) continue;
|
||||
c.State = Visibility.Hidden;
|
||||
}
|
||||
singleDisplaySideOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
|
||||
};
|
||||
}
|
||||
|
||||
@@ -366,12 +382,24 @@ namespace osu.Game
|
||||
overlay.StateChanged += state =>
|
||||
{
|
||||
if (state == Visibility.Hidden) return;
|
||||
informationalOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var c in informationalOverlays)
|
||||
{
|
||||
if (c == overlay) continue;
|
||||
c.State = Visibility.Hidden;
|
||||
}
|
||||
// ensure only one of these overlays are open at once.
|
||||
var singleDisplayOverlays = new OverlayContainer[] { chat, social, direct };
|
||||
overlays.AddRange(singleDisplayOverlays);
|
||||
|
||||
foreach (var overlay in singleDisplayOverlays)
|
||||
{
|
||||
overlay.StateChanged += state =>
|
||||
{
|
||||
// informational overlays should be dismissed on a show or hide of a full overlay.
|
||||
informationalOverlays.ForEach(o => o.Hide());
|
||||
|
||||
if (state == Visibility.Hidden) return;
|
||||
|
||||
singleDisplayOverlays.Where(o => o != overlay).ForEach(o => o.Hide());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace osu.Game.Overlays.Mods
|
||||
|
||||
private void rulesetChanged(RulesetInfo newRuleset)
|
||||
{
|
||||
if (newRuleset == null) return;
|
||||
|
||||
var instance = newRuleset.CreateInstance();
|
||||
|
||||
foreach (ModSection section in ModSectionsContainer.Children)
|
||||
@@ -173,7 +175,10 @@ namespace osu.Game.Overlays.Mods
|
||||
refreshSelectedMods();
|
||||
}
|
||||
|
||||
private void refreshSelectedMods() => SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
private void refreshSelectedMods()
|
||||
{
|
||||
SelectedMods.Value = ModSectionsContainer.Children.SelectMany(s => s.SelectedMods).ToArray();
|
||||
}
|
||||
|
||||
public ModSelectOverlay()
|
||||
{
|
||||
|
||||
@@ -128,7 +128,8 @@ namespace osu.Game.Overlays
|
||||
var section = sections.Children.FirstOrDefault(s => s.AcceptTypes.Any(accept => accept.IsAssignableFrom(ourType)));
|
||||
section?.Add(notification, notification.DisplayOnTop ? -runningDepth : runningDepth);
|
||||
|
||||
State = Visibility.Visible;
|
||||
if (notification.IsImportant)
|
||||
State = Visibility.Visible;
|
||||
|
||||
updateCounts();
|
||||
});
|
||||
|
||||
@@ -23,6 +23,11 @@ namespace osu.Game.Overlays.Notifications
|
||||
/// </summary>
|
||||
public event Action Closed;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this notification should forcefully display itself.
|
||||
/// </summary>
|
||||
public virtual bool IsImportant => false;
|
||||
|
||||
/// <summary>
|
||||
/// Run on user activating the notification. Return true to close.
|
||||
/// </summary>
|
||||
|
||||
@@ -158,6 +158,13 @@ namespace osu.Game.Overlays.Profile
|
||||
}
|
||||
}
|
||||
},
|
||||
new Box // this is a temporary workaround for incorrect masking behaviour of FillMode.Fill used in UserCoverBackground (see https://github.com/ppy/osu-framework/issues/1675)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = 1,
|
||||
Y = cover_height,
|
||||
Colour = OsuColour.Gray(34),
|
||||
},
|
||||
infoTextLeft = new LinkFlowContainer(t => t.TextSize = 14)
|
||||
{
|
||||
X = UserProfileOverlay.CONTENT_X_MARGIN,
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
LabelText = "Audio Offset",
|
||||
Bindable = config.GetBindable<double>(OsuSetting.AudioOffset),
|
||||
KeyboardStep = 100f
|
||||
KeyboardStep = 1f
|
||||
},
|
||||
new SettingsButton
|
||||
{
|
||||
|
||||
@@ -17,10 +17,10 @@ namespace osu.Game.Overlays.Settings.Sections.Audio
|
||||
{
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SettingsSlider<double> { LabelText = "Master", Bindable = audio.Volume, KeyboardStep = 0.1f },
|
||||
new SettingsSlider<double> { LabelText = "Master (Window Inactive)", Bindable = config.GetBindable<double>(OsuSetting.VolumeInactive), KeyboardStep = 0.1f },
|
||||
new SettingsSlider<double> { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.1f },
|
||||
new SettingsSlider<double> { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.1f },
|
||||
new SettingsSlider<double> { LabelText = "Master", Bindable = audio.Volume, KeyboardStep = 0.01f },
|
||||
new SettingsSlider<double> { LabelText = "Master (Window Inactive)", Bindable = config.GetBindable<double>(OsuSetting.VolumeInactive), KeyboardStep = 0.01f },
|
||||
new SettingsSlider<double> { LabelText = "Effect", Bindable = audio.VolumeSample, KeyboardStep = 0.01f },
|
||||
new SettingsSlider<double> { LabelText = "Music", Bindable = audio.VolumeTrack, KeyboardStep = 0.01f },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,13 +21,13 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
LabelText = "Background dim",
|
||||
Bindable = config.GetBindable<double>(OsuSetting.DimLevel),
|
||||
KeyboardStep = 0.1f
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Background blur",
|
||||
Bindable = config.GetBindable<double>(OsuSetting.BlurLevel),
|
||||
KeyboardStep = 0.1f
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
|
||||
@@ -31,13 +31,13 @@ namespace osu.Game.Overlays.Settings.Sections.Gameplay
|
||||
{
|
||||
LabelText = "Display beatmaps from",
|
||||
Bindable = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
|
||||
KeyboardStep = 1f
|
||||
KeyboardStep = 0.1f
|
||||
},
|
||||
new SettingsSlider<double, StarSlider>
|
||||
{
|
||||
LabelText = "up to",
|
||||
Bindable = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
|
||||
KeyboardStep = 1f
|
||||
KeyboardStep = 0.1f
|
||||
},
|
||||
new SettingsEnumDropdown<RandomSelectAlgorithm>
|
||||
{
|
||||
|
||||
@@ -50,13 +50,13 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
||||
{
|
||||
LabelText = "Horizontal position",
|
||||
Bindable = config.GetBindable<double>(FrameworkSetting.LetterboxPositionX),
|
||||
KeyboardStep = 0.1f
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
new SettingsSlider<double>
|
||||
{
|
||||
LabelText = "Vertical position",
|
||||
Bindable = config.GetBindable<double>(FrameworkSetting.LetterboxPositionY),
|
||||
KeyboardStep = 0.1f
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
@@ -36,13 +36,13 @@ namespace osu.Game.Overlays.Settings.Sections
|
||||
{
|
||||
LabelText = "Menu cursor size",
|
||||
Bindable = config.GetBindable<double>(OsuSetting.MenuCursorSize),
|
||||
KeyboardStep = 0.1f
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
new SettingsSlider<double, SizeSlider>
|
||||
{
|
||||
LabelText = "Gameplay cursor size",
|
||||
Bindable = config.GetBindable<double>(OsuSetting.GameplayCursorSize),
|
||||
KeyboardStep = 0.1f
|
||||
KeyboardStep = 0.01f
|
||||
},
|
||||
new SettingsCheckbox
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ using osu.Game.Rulesets.UI;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public class ModAutoplay<T> : ModAutoplay, IApplicableToRulesetContainer<T>
|
||||
public abstract class ModAutoplay<T> : ModAutoplay, IApplicableToRulesetContainer<T>
|
||||
where T : HitObject
|
||||
{
|
||||
protected virtual Score CreateReplayScore(Beatmap<T> beatmap) => new Score { Replay = new Replay() };
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace osu.Game.Screens.Menu
|
||||
OnChart = delegate { Push(new ChartListing()); },
|
||||
OnDirect = delegate { Push(new OnlineListing()); },
|
||||
OnEdit = delegate { Push(new Editor()); },
|
||||
OnSolo = delegate { Push(consumeSongSelect()); },
|
||||
OnSolo = onSolo,
|
||||
OnMulti = delegate { Push(new Multiplayer()); },
|
||||
OnExit = Exit,
|
||||
}
|
||||
@@ -85,6 +85,10 @@ namespace osu.Game.Screens.Menu
|
||||
LoadComponentAsync(songSelect = new PlaySongSelect());
|
||||
}
|
||||
|
||||
public void LoadToSolo() => Schedule(onSolo);
|
||||
|
||||
private void onSolo() => Push(consumeSongSelect());
|
||||
|
||||
private Screen consumeSongSelect()
|
||||
{
|
||||
var s = songSelect;
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
||||
{
|
||||
Rank = newRank;
|
||||
|
||||
if (IsLoaded)
|
||||
if (LoadState >= LoadState.Ready)
|
||||
updateTexture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,10 +84,10 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
protected override void UpdateBeatmap(WorkingBeatmap beatmap)
|
||||
{
|
||||
base.UpdateBeatmap(beatmap);
|
||||
|
||||
beatmap.Mods.BindTo(SelectedMods);
|
||||
|
||||
base.UpdateBeatmap(beatmap);
|
||||
|
||||
BeatmapDetails.Beatmap = beatmap;
|
||||
|
||||
if (beatmap.Track != null)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using OpenTK;
|
||||
using OpenTK.Input;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -20,6 +21,7 @@ using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Backgrounds;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Screens.Menu;
|
||||
@@ -70,7 +72,14 @@ namespace osu.Game.Screens.Select
|
||||
private DependencyContainer dependencies;
|
||||
|
||||
protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent)
|
||||
=> dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
{
|
||||
dependencies = new DependencyContainer(base.CreateChildDependencies(parent));
|
||||
dependencies.CacheAs(this);
|
||||
dependencies.CacheAs(Ruleset);
|
||||
dependencies.CacheAs<IBindable<RulesetInfo>>(Ruleset);
|
||||
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
protected SongSelect()
|
||||
{
|
||||
@@ -189,9 +198,9 @@ namespace osu.Game.Screens.Select
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(BeatmapManager beatmaps, AudioManager audio, DialogOverlay dialog, OsuColour colours)
|
||||
{
|
||||
dependencies.CacheAs(this);
|
||||
dependencies.CacheAs(Ruleset);
|
||||
dependencies.CacheAs<IBindable<RulesetInfo>>(Ruleset);
|
||||
// manual binding to parent ruleset to allow for delayed load in the incoming direction.
|
||||
base.Ruleset.ValueChanged += r => updateSelectedBeatmap(beatmapNoDebounce);
|
||||
Ruleset.ValueChanged += r => base.Ruleset.Value = r;
|
||||
|
||||
if (Footer != null)
|
||||
{
|
||||
@@ -277,7 +286,7 @@ namespace osu.Game.Screens.Select
|
||||
// If selecting new beatmap without bypassing filters failed, there's possibly a ruleset mismatch
|
||||
if (beatmap?.BeatmapInfo?.Ruleset != null && beatmap.BeatmapInfo.Ruleset != Ruleset.Value)
|
||||
{
|
||||
Ruleset.Value = beatmap.BeatmapInfo.Ruleset;
|
||||
base.Ruleset.Value = beatmap.BeatmapInfo.Ruleset;
|
||||
Carousel.SelectBeatmap(beatmap.BeatmapInfo);
|
||||
}
|
||||
}
|
||||
@@ -295,18 +304,25 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
void performLoad()
|
||||
{
|
||||
WorkingBeatmap working = Beatmap.Value;
|
||||
bool preview = false;
|
||||
|
||||
// We may be arriving here due to another component changing the bindable Beatmap.
|
||||
// In these cases, the other component has already loaded the beatmap, so we don't need to do so again.
|
||||
if (beatmap?.Equals(Beatmap.Value.BeatmapInfo) != true)
|
||||
{
|
||||
bool preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID;
|
||||
|
||||
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value);
|
||||
ensurePlayingSelected(preview);
|
||||
preview = beatmap?.BeatmapSetInfoID != Beatmap.Value?.BeatmapInfo.BeatmapSetInfoID;
|
||||
working = beatmaps.GetWorkingBeatmap(beatmap, Beatmap.Value);
|
||||
}
|
||||
|
||||
|
||||
working.Mods.Value = Enumerable.Empty<Mod>();
|
||||
|
||||
Beatmap.Value = working;
|
||||
Ruleset.Value = ruleset;
|
||||
|
||||
ensurePlayingSelected(preview);
|
||||
|
||||
UpdateBeatmap(Beatmap.Value);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.IO;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Beatmaps;
|
||||
|
||||
namespace osu.Game.Storyboards.Drawables
|
||||
{
|
||||
public class DrawableStoryboardSample : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The amount of time allowable beyond the start time of the sample, for the sample to start.
|
||||
/// </summary>
|
||||
private const double allowable_late_start = 100;
|
||||
|
||||
private readonly StoryboardSample sample;
|
||||
private SampleChannel channel;
|
||||
|
||||
public override bool RemoveWhenNotAlive => false;
|
||||
|
||||
public DrawableStoryboardSample(StoryboardSample sample)
|
||||
{
|
||||
this.sample = sample;
|
||||
LifetimeStart = sample.Time;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IBindableBeatmap beatmap)
|
||||
{
|
||||
// Try first with the full name, then attempt with no path
|
||||
channel = beatmap.Value.Skin.GetSample(sample.Path) ?? beatmap.Value.Skin.GetSample(Path.ChangeExtension(sample.Path, null));
|
||||
|
||||
if (channel != null)
|
||||
channel.Volume.Value = sample.Volume / 100;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
// TODO: this logic will need to be consolidated with other game samples like hitsounds.
|
||||
if (Time.Current < sample.Time)
|
||||
{
|
||||
// We've rewound before the start time of the sample
|
||||
channel?.Stop();
|
||||
|
||||
// In the case that the user fast-forwards to a point far beyond the start time of the sample,
|
||||
// we want to be able to fall into the if-conditional below (therefore we must not have a life time end)
|
||||
LifetimeStart = sample.Time;
|
||||
LifetimeEnd = double.MaxValue;
|
||||
}
|
||||
else if (Time.Current - Time.Elapsed < sample.Time)
|
||||
{
|
||||
// We've passed the start time of the sample. We only play the sample if we're within an allowable range
|
||||
// from the sample's start, to reduce layering if we've been fast-forwarded far into the future
|
||||
if (Time.Current - sample.Time < allowable_late_start)
|
||||
channel?.Play();
|
||||
|
||||
// In the case that the user rewinds to a point far behind the start time of the sample,
|
||||
// we want to be able to fall into the if-conditional above (therefore we must not have a life time start)
|
||||
LifetimeStart = double.MinValue;
|
||||
LifetimeEnd = sample.Time;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,14 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using System;
|
||||
using osu.Game.Storyboards.Drawables;
|
||||
|
||||
namespace osu.Game.Storyboards
|
||||
{
|
||||
public class StoryboardSample : IStoryboardElement
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public bool IsDrawable => false;
|
||||
public bool IsDrawable => true;
|
||||
|
||||
public double Time;
|
||||
public float Volume;
|
||||
@@ -21,9 +21,6 @@ namespace osu.Game.Storyboards
|
||||
Volume = volume;
|
||||
}
|
||||
|
||||
public Drawable CreateDrawable()
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
public Drawable CreateDrawable() => new DrawableStoryboardSample(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace osu.Game.Users
|
||||
|
||||
country = value;
|
||||
|
||||
if (IsLoaded)
|
||||
if (LoadState >= LoadState.Ready)
|
||||
sprite.Texture = getFlagTexture();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user