From e54741619331b81a002a3d58cbc520e35a5ccf64 Mon Sep 17 00:00:00 2001 From: Damnae Date: Thu, 7 Sep 2017 23:55:05 +0200 Subject: [PATCH 01/64] Storyboards implementation. --- .../Visual/TestCaseStoryboard.cs | 91 +++++++ osu.Desktop.Tests/osu.Desktop.Tests.csproj | 1 + osu.Game/Beatmaps/Beatmap.cs | 6 + osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 222 ++++++++++++++++-- osu.Game/Storyboards/AnimationDefinition.cs | 33 +++ osu.Game/Storyboards/CommandLoop.cs | 27 +++ osu.Game/Storyboards/CommandTimeline.cs | 61 +++++ osu.Game/Storyboards/CommandTimelineGroup.cs | 94 ++++++++ osu.Game/Storyboards/CommandTrigger.cs | 24 ++ osu.Game/Storyboards/Drawables/IFlippable.cs | 11 + osu.Game/Storyboards/Drawables/Storyboard.cs | 59 +++++ .../Drawables/StoryboardAnimation.cs | 55 +++++ .../Storyboards/Drawables/StoryboardLayer.cs | 37 +++ .../Storyboards/Drawables/StoryboardSprite.cs | 49 ++++ osu.Game/Storyboards/ElementDefinition.cs | 13 + osu.Game/Storyboards/LayerDefinition.cs | 33 +++ osu.Game/Storyboards/SampleDefinition.cs | 24 ++ osu.Game/Storyboards/SpriteDefinition.cs | 59 +++++ osu.Game/Storyboards/StoryboardDefinition.cs | 36 +++ osu.Game/osu.Game.csproj | 15 ++ 20 files changed, 925 insertions(+), 25 deletions(-) create mode 100644 osu.Desktop.Tests/Visual/TestCaseStoryboard.cs create mode 100644 osu.Game/Storyboards/AnimationDefinition.cs create mode 100644 osu.Game/Storyboards/CommandLoop.cs create mode 100644 osu.Game/Storyboards/CommandTimeline.cs create mode 100644 osu.Game/Storyboards/CommandTimelineGroup.cs create mode 100644 osu.Game/Storyboards/CommandTrigger.cs create mode 100644 osu.Game/Storyboards/Drawables/IFlippable.cs create mode 100644 osu.Game/Storyboards/Drawables/Storyboard.cs create mode 100644 osu.Game/Storyboards/Drawables/StoryboardAnimation.cs create mode 100644 osu.Game/Storyboards/Drawables/StoryboardLayer.cs create mode 100644 osu.Game/Storyboards/Drawables/StoryboardSprite.cs create mode 100644 osu.Game/Storyboards/ElementDefinition.cs create mode 100644 osu.Game/Storyboards/LayerDefinition.cs create mode 100644 osu.Game/Storyboards/SampleDefinition.cs create mode 100644 osu.Game/Storyboards/SpriteDefinition.cs create mode 100644 osu.Game/Storyboards/StoryboardDefinition.cs diff --git a/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs new file mode 100644 index 0000000000..1d7b3dffd2 --- /dev/null +++ b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs @@ -0,0 +1,91 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK.Graphics; +using osu.Framework.Allocation; +using osu.Framework.Configuration; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Framework.Timing; +using osu.Game; +using osu.Game.Beatmaps; +using osu.Game.Overlays; +using osu.Game.Storyboards.Drawables; + +namespace osu.Desktop.Tests.Visual +{ + internal class TestCaseStoryboard : OsuTestCase + { + public override string Description => @"Tests storyboards."; + + private readonly Bindable beatmapBacking = new Bindable(); + + private MusicController musicController; + private Container storyboardContainer; + private Storyboard storyboard; + + public TestCaseStoryboard() + { + Clock = new FramedClock(); + + Add(new Container + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black, + }, + storyboardContainer = new Container + { + RelativeSizeAxes = Axes.Both, + }, + }, + }); + Add(musicController = new MusicController + { + Origin = Anchor.TopRight, + Anchor = Anchor.TopRight, + State = Visibility.Visible, + }); + + AddStep("Restart", restart); + AddToggleStep("Passing", passing => { if (storyboard != null) storyboard.Passing = passing; }); + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase game) + { + beatmapBacking.BindTo(game.Beatmap); + beatmapBacking.ValueChanged += beatmapChanged; + } + + private void beatmapChanged(WorkingBeatmap working) + => loadStoryboard(working); + + private void restart() + { + var track = beatmapBacking.Value.Track; + + track.Reset(); + loadStoryboard(beatmapBacking.Value); + track.Start(); + } + + private void loadStoryboard(WorkingBeatmap working) + { + if (storyboard != null) + storyboardContainer.Remove(storyboard); + + var decoupledClock = new DecoupleableInterpolatingFramedClock { IsCoupled = true }; + decoupledClock.ChangeSource(working.Track); + storyboardContainer.Clock = decoupledClock; + + storyboardContainer.Add(storyboard = working.Beatmap.Storyboard.CreateDrawable()); + storyboard.Passing = false; + } + } +} diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index 86268e6110..6bd190a1f6 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -91,6 +91,7 @@ + diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index 82777734bb..e4568a1919 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps.ControlPoints; using osu.Game.IO.Serialization; +using osu.Game.Storyboards; namespace osu.Game.Beatmaps { @@ -40,6 +41,11 @@ namespace osu.Game.Beatmaps /// public double TotalBreakTime => Breaks.Sum(b => b.Duration); + /// + /// The Beatmap's Storyboard. + /// + public StoryboardDefinition Storyboard = new StoryboardDefinition(); + /// /// Constructs a new beatmap. /// diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index b51ea607dd..08e1d06621 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -10,6 +10,10 @@ using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Legacy; using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Storyboards; +using OpenTK; +using osu.Framework.Graphics; +using osu.Framework.IO.File; namespace osu.Game.Beatmaps.Formats { @@ -238,42 +242,208 @@ namespace osu.Game.Beatmaps.Formats } } - private void handleEvents(Beatmap beatmap, string line) + private void handleEvents(Beatmap beatmap, string line, ref SpriteDefinition spriteDefinition, ref CommandTimelineGroup timelineGroup) { + var depth = 0; + while (line.StartsWith(" ") || line.StartsWith("_")) + { + ++depth; + line = line.Substring(depth); + } + decodeVariables(ref line); string[] split = line.Split(','); - EventType type; - if (!Enum.TryParse(split[0], out type)) - throw new InvalidDataException($@"Unknown event type {split[0]}"); - - // Todo: Implement the rest - switch (type) + if (depth == 0) { - case EventType.Video: - case EventType.Background: - string filename = split[2].Trim('"'); + spriteDefinition = null; - if (type == EventType.Background) - beatmap.BeatmapInfo.Metadata.BackgroundFile = filename; + EventType type; + if (!Enum.TryParse(split[0], out type)) + throw new InvalidDataException($@"Unknown event type {split[0]}"); - break; - case EventType.Break: - var breakEvent = new BreakPeriod - { - StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo), - EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo) - }; + switch (type) + { + case EventType.Video: + case EventType.Background: + string filename = split[2].Trim('"'); - if (!breakEvent.HasEffect) - return; + if (type == EventType.Background) + beatmap.BeatmapInfo.Metadata.BackgroundFile = filename; - beatmap.Breaks.Add(breakEvent); - break; + break; + case EventType.Break: + var breakEvent = new BreakPeriod + { + StartTime = double.Parse(split[1], NumberFormatInfo.InvariantInfo), + EndTime = double.Parse(split[2], NumberFormatInfo.InvariantInfo) + }; + + if (!breakEvent.HasEffect) + return; + + beatmap.Breaks.Add(breakEvent); + break; + case EventType.Sprite: + { + var layer = split[1]; + var origin = (Anchor)Enum.Parse(typeof(Anchor), split[2]); + var path = cleanFilename(split[3]); + var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); + var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); + spriteDefinition = new SpriteDefinition(path, origin, new Vector2(x, y)); + beatmap.Storyboard.GetLayer(layer).Add(spriteDefinition); + } + break; + case EventType.Animation: + { + var layer = split[1]; + var origin = (Anchor)Enum.Parse(typeof(Anchor), split[2]); + var path = cleanFilename(split[3]); + var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); + var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); + var frameCount = int.Parse(split[6]); + var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo); + var loopType = (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]); + spriteDefinition = new AnimationDefinition(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); + beatmap.Storyboard.GetLayer(layer).Add(spriteDefinition); + } + break; + case EventType.Sample: + { + var time = double.Parse(split[1], CultureInfo.InvariantCulture); + var layer = split[2]; + var path = cleanFilename(split[3]); + var volume = float.Parse(split[4], CultureInfo.InvariantCulture); + beatmap.Storyboard.GetLayer(layer).Add(new SampleDefinition(path, time, volume)); + } + break; + } + } + else + { + if (depth < 2) + timelineGroup = spriteDefinition; + + switch (split[0]) + { + case "T": + { + var triggerName = split[1]; + var startTime = double.Parse(split[2], CultureInfo.InvariantCulture); + var endTime = double.Parse(split[3], CultureInfo.InvariantCulture); + var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0; + timelineGroup = spriteDefinition?.AddTrigger(triggerName, startTime, endTime, groupNumber); + } + break; + case "L": + { + var startTime = double.Parse(split[1], CultureInfo.InvariantCulture); + var loopCount = int.Parse(split[2]); + timelineGroup = spriteDefinition?.AddLoop(startTime, loopCount); + } + break; + default: + { + if (string.IsNullOrEmpty(split[3])) + split[3] = split[2]; + + var commandType = split[0]; + var easing = (Easing)int.Parse(split[1]); + var startTime = double.Parse(split[2], CultureInfo.InvariantCulture); + var endTime = double.Parse(split[3], CultureInfo.InvariantCulture); + + switch (commandType) + { + case "F": + { + var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); + var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; + timelineGroup?.Alpha.Add(easing, startTime, endTime, startValue, endValue); + } + break; + case "S": + { + var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); + var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; + timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startValue), new Vector2(endValue)); + } + break; + case "V": + { + var startX = float.Parse(split[4], CultureInfo.InvariantCulture); + var startY = float.Parse(split[5], CultureInfo.InvariantCulture); + var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; + var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; + timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(startX, endY)); + } + break; + case "R": + { + var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); + var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; + timelineGroup?.Rotation.Add(easing, startTime, endTime, MathHelper.RadiansToDegrees(startValue), MathHelper.RadiansToDegrees(endValue)); + } + break; + case "M": + { + var startX = float.Parse(split[4], CultureInfo.InvariantCulture); + var startY = float.Parse(split[5], CultureInfo.InvariantCulture); + var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; + var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; + timelineGroup?.X.Add(easing, startTime, endTime, startX, endX); + timelineGroup?.Y.Add(easing, startTime, endTime, startY, endY); + } + break; + case "MX": + { + var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); + var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; + timelineGroup?.X.Add(easing, startTime, endTime, startValue, endValue); + } + break; + case "MY": + { + var startValue = float.Parse(split[4], CultureInfo.InvariantCulture); + var endValue = split.Length > 5 ? float.Parse(split[5], CultureInfo.InvariantCulture) : startValue; + timelineGroup?.Y.Add(easing, startTime, endTime, startValue, endValue); + } + break; + case "C": + { + var startRed = float.Parse(split[4], CultureInfo.InvariantCulture); + var startGreen = float.Parse(split[5], CultureInfo.InvariantCulture); + var startBlue = float.Parse(split[6], CultureInfo.InvariantCulture); + var endRed = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startRed; + var endGreen = split.Length > 8 ? float.Parse(split[8], CultureInfo.InvariantCulture) : startGreen; + var endBlue = split.Length > 9 ? float.Parse(split[9], CultureInfo.InvariantCulture) : startBlue; + timelineGroup?.Colour.Add(easing, startTime, endTime, + new Color4(startRed / 255f, startGreen / 255f, startBlue / 255f, 1), + new Color4(endRed / 255f, endGreen / 255f, endBlue / 255f, 1)); + } + break; + case "P": + { + var type = split[4]; + switch (type) + { + case "A": timelineGroup?.Additive.Add(easing, startTime, endTime, true, true); break; + case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, true); break; + case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, true); break; + } + } + break; + } + } + break; + } } } + private static string cleanFilename(string path) + => FileSafety.PathStandardise(path.Trim('\"')); + private void handleTimingPoints(Beatmap beatmap, string line) { string[] split = line.Split(','); @@ -414,6 +584,8 @@ namespace osu.Game.Beatmaps.Formats Section section = Section.None; bool hasCustomColours = false; + SpriteDefinition spriteDefinition = null; + CommandTimelineGroup timelineGroup = null; string line; while ((line = stream.ReadLine()) != null) @@ -421,7 +593,7 @@ namespace osu.Game.Beatmaps.Formats if (string.IsNullOrEmpty(line)) continue; - if (line.StartsWith(" ") || line.StartsWith("_") || line.StartsWith("//")) + if (line.StartsWith("//")) continue; if (line.StartsWith(@"osu file format v")) @@ -452,7 +624,7 @@ namespace osu.Game.Beatmaps.Formats handleDifficulty(beatmap, line); break; case Section.Events: - handleEvents(beatmap, line); + handleEvents(beatmap, line, ref spriteDefinition, ref timelineGroup); break; case Section.TimingPoints: handleTimingPoints(beatmap, line); diff --git a/osu.Game/Storyboards/AnimationDefinition.cs b/osu.Game/Storyboards/AnimationDefinition.cs new file mode 100644 index 0000000000..3ac9cbfe0e --- /dev/null +++ b/osu.Game/Storyboards/AnimationDefinition.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Game.Storyboards.Drawables; + +namespace osu.Game.Storyboards +{ + public class AnimationDefinition : SpriteDefinition + { + public int FrameCount; + public double FrameDelay; + public AnimationLoopType LoopType; + + public AnimationDefinition(string path, Anchor origin, Vector2 initialPosition, int frameCount, double frameDelay, AnimationLoopType loopType) + : base(path, origin, initialPosition) + { + FrameCount = frameCount; + FrameDelay = frameDelay; + LoopType = loopType; + } + + public override Drawable CreateDrawable() + => new StoryboardAnimation(this); + } + + public enum AnimationLoopType + { + LoopForever, + LoopOnce, + } +} diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs new file mode 100644 index 0000000000..b93a04cea1 --- /dev/null +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; + +namespace osu.Game.Storyboards +{ + public class CommandLoop : CommandTimelineGroup + { + private double startTime; + private int loopCount; + + public CommandLoop(double startTime, int loopCount) + { + this.startTime = startTime; + this.loopCount = loopCount; + } + + public override void ApplyTransforms(Drawable drawable) + { + //base.ApplyTransforms(drawable); + } + + public override string ToString() + => $"{startTime} x{loopCount}"; + } +} diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs new file mode 100644 index 0000000000..04e165aa38 --- /dev/null +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Caching; +using osu.Framework.Graphics; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Storyboards +{ + public class CommandTimeline : CommandTimeline + { + private readonly List commands = new List(); + public IEnumerable Commands => commands.OrderBy(c => c.StartTime); + public bool HasCommands => commands.Count > 0; + + private Cached startTimeBacking; + public double StartTime => startTimeBacking.IsValid ? startTimeBacking : (startTimeBacking.Value = HasCommands ? commands.Min(c => c.StartTime) : double.MinValue); + + private Cached endTimeBacking; + public double EndTime => endTimeBacking.IsValid ? endTimeBacking : (endTimeBacking.Value = HasCommands ? commands.Max(c => c.EndTime) : double.MaxValue); + + public T StartValue => HasCommands ? commands.OrderBy(c => c.StartTime).First().StartValue : default(T); + public T EndValue => HasCommands ? commands.OrderByDescending(c => c.EndTime).First().EndValue : default(T); + + public void Add(Easing easing, double startTime, double endTime, T startValue, T endValue) + { + if (endTime < startTime) + return; + + commands.Add(new Command { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue, }); + + startTimeBacking.Invalidate(); + endTimeBacking.Invalidate(); + } + + public override string ToString() + => $"{commands.Count} command(s)"; + + public class Command + { + public Easing Easing; + public double StartTime; + public double EndTime; + public T StartValue; + public T EndValue; + + public double Duration => EndTime - StartTime; + + public override string ToString() + => $"{StartTime} -> {EndTime}, {StartValue} -> {EndValue} {Easing}"; + } + } + + public interface CommandTimeline + { + double StartTime { get; } + double EndTime { get; } + bool HasCommands { get; } + } +} diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs new file mode 100644 index 0000000000..cc67c9dd68 --- /dev/null +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -0,0 +1,94 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using OpenTK.Graphics; +using osu.Framework.Graphics; +using osu.Game.Storyboards.Drawables; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Storyboards +{ + public class CommandTimelineGroup + { + public CommandTimeline X = new CommandTimeline(); + public CommandTimeline Y = new CommandTimeline(); + public CommandTimeline Scale = new CommandTimeline(); + public CommandTimeline Rotation = new CommandTimeline(); + public CommandTimeline Colour = new CommandTimeline(); + public CommandTimeline Alpha = new CommandTimeline(); + public CommandTimeline Additive = new CommandTimeline(); + public CommandTimeline FlipH = new CommandTimeline(); + public CommandTimeline FlipV = new CommandTimeline(); + + public IEnumerable Timelines + { + get + { + yield return X; + yield return Y; + yield return Scale; + yield return Rotation; + yield return Colour; + yield return Alpha; + yield return Additive; + yield return FlipH; + yield return FlipV; + } + } + + public double StartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime); + public double EndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime); + public bool HasCommands => Timelines.Any(t => t.HasCommands); + + public virtual void ApplyTransforms(Drawable drawable) + { + if (X.HasCommands) drawable.X = X.StartValue; + foreach (var command in X.Commands) + using (drawable.BeginAbsoluteSequence(command.StartTime)) + drawable.MoveToX(command.StartValue) + .MoveToX(command.EndValue, command.Duration, command.Easing); + + if (Y.HasCommands) drawable.Y = Y.StartValue; + foreach (var command in Y.Commands) + using (drawable.BeginAbsoluteSequence(command.StartTime)) + drawable.MoveToY(command.StartValue) + .MoveToY(command.EndValue, command.Duration, command.Easing); + + if (Scale.HasCommands) drawable.Scale = Scale.StartValue; + foreach (var command in Scale.Commands) + using (drawable.BeginAbsoluteSequence(command.StartTime)) + drawable.ScaleTo(command.StartValue) + .ScaleTo(command.EndValue, command.Duration, command.Easing); + + if (Rotation.HasCommands) drawable.Rotation = Rotation.StartValue; + foreach (var command in Rotation.Commands) + using (drawable.BeginAbsoluteSequence(command.StartTime)) + drawable.RotateTo(command.StartValue) + .RotateTo(command.EndValue, command.Duration, command.Easing); + + if (Colour.HasCommands) drawable.Colour = Colour.StartValue; + foreach (var command in Colour.Commands) + using (drawable.BeginAbsoluteSequence(command.StartTime)) + drawable.FadeColour(command.StartValue) + .FadeColour(command.EndValue, command.Duration, command.Easing); + + if (Alpha.HasCommands) drawable.Alpha = Alpha.StartValue; + foreach (var command in Alpha.Commands) + using (drawable.BeginAbsoluteSequence(command.StartTime)) + drawable.FadeTo(command.StartValue) + .FadeTo(command.EndValue, command.Duration, command.Easing); + + if (Additive.HasCommands) + drawable.BlendingMode = BlendingMode.Additive; + + var flippable = drawable as IFlippable; + if (flippable != null) + { + flippable.FlipH = FlipH.HasCommands; + flippable.FlipV = FlipV.HasCommands; + } + } + } +} diff --git a/osu.Game/Storyboards/CommandTrigger.cs b/osu.Game/Storyboards/CommandTrigger.cs new file mode 100644 index 0000000000..e7133e170f --- /dev/null +++ b/osu.Game/Storyboards/CommandTrigger.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Storyboards +{ + public class CommandTrigger : CommandTimelineGroup + { + private string triggerName; + private double startTime; + private double endTime; + private int groupNumber; + + public CommandTrigger(string triggerName, double startTime, double endTime, int groupNumber) + { + this.triggerName = triggerName; + this.startTime = startTime; + this.endTime = endTime; + this.groupNumber = groupNumber; + } + + public override string ToString() + => $"{triggerName} {startTime} -> {endTime} ({groupNumber})"; + } +} diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs new file mode 100644 index 0000000000..a1899d1411 --- /dev/null +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -0,0 +1,11 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +namespace osu.Game.Storyboards.Drawables +{ + public interface IFlippable + { + bool FlipH { get; set; } + bool FlipV { get; set; } + } +} diff --git a/osu.Game/Storyboards/Drawables/Storyboard.cs b/osu.Game/Storyboards/Drawables/Storyboard.cs new file mode 100644 index 0000000000..a5b242357f --- /dev/null +++ b/osu.Game/Storyboards/Drawables/Storyboard.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Textures; +using osu.Game.IO; + +namespace osu.Game.Storyboards.Drawables +{ + public class Storyboard : Container + { + public StoryboardDefinition Definition { get; private set; } + + protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); + public override bool HandleInput => false; + + private bool passing = true; + public bool Passing + { + get { return passing; } + set + { + if (passing == value) return; + passing = value; + updateLayerVisibility(); + } + } + + private DependencyContainer dependencies; + protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => + dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); + + public Storyboard(StoryboardDefinition definition) + { + Definition = definition; + Size = new Vector2(640, 480); + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + } + + [BackgroundDependencyLoader] + private void load(FileStore fileStore) + { + dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, }); + + foreach (var layerDefinition in Definition.Layers) + Add(layerDefinition.CreateDrawable()); + } + + private void updateLayerVisibility() + { + foreach (var layer in Children) + layer.Enabled = passing ? layer.Definition.EnabledWhenPassing : layer.Definition.ShowWhenFailing; + } + } +} diff --git a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs new file mode 100644 index 0000000000..583a0d13c3 --- /dev/null +++ b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Animations; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.File; +using System.Linq; + +namespace osu.Game.Storyboards.Drawables +{ + public class StoryboardAnimation : TextureAnimation, IFlippable + { + public AnimationDefinition Definition { get; private set; } + + protected override bool ShouldBeAlive => Definition.HasCommands && base.ShouldBeAlive; + public override bool RemoveWhenNotAlive => !Definition.HasCommands || base.RemoveWhenNotAlive; + + public bool FlipH { get; set; } + public bool FlipV { get; set; } + protected override Vector2 DrawScale => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + + public StoryboardAnimation(AnimationDefinition definition) + { + Definition = definition; + Origin = definition.Origin; + Position = definition.InitialPosition; + Repeat = definition.LoopType == AnimationLoopType.LoopForever; + + if (definition.HasCommands) + { + LifetimeStart = definition.StartTime; + LifetimeEnd = definition.EndTime; + } + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase game, TextureStore textureStore) + { + for (var frame = 0; frame < Definition.FrameCount; frame++) + { + var framePath = Definition.Path.Replace(".", frame + "."); + + var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename == framePath)?.FileInfo.StoragePath; + if (path == null) + continue; + + var texture = textureStore.Get(path); + AddFrame(texture, Definition.FrameDelay); + } + Definition.ApplyTransforms(this); + } + } +} diff --git a/osu.Game/Storyboards/Drawables/StoryboardLayer.cs b/osu.Game/Storyboards/Drawables/StoryboardLayer.cs new file mode 100644 index 0000000000..48532e0418 --- /dev/null +++ b/osu.Game/Storyboards/Drawables/StoryboardLayer.cs @@ -0,0 +1,37 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Allocation; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; + +namespace osu.Game.Storyboards.Drawables +{ + public class StoryboardLayer : Container + { + public LayerDefinition Definition { get; private set; } + public bool Enabled; + + public override bool IsPresent => Enabled && base.IsPresent; + + public StoryboardLayer(LayerDefinition definition) + { + Definition = definition; + RelativeSizeAxes = Axes.Both; + Anchor = Anchor.Centre; + Origin = Anchor.Centre; + Enabled = definition.EnabledWhenPassing; + } + + [BackgroundDependencyLoader] + private void load() + { + foreach (var element in Definition.Elements) + { + var drawable = element.CreateDrawable(); + if (drawable != null) + Add(drawable); + } + } + } +} diff --git a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs new file mode 100644 index 0000000000..927996d750 --- /dev/null +++ b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs @@ -0,0 +1,49 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Allocation; +using osu.Framework.Graphics.Sprites; +using osu.Framework.Graphics.Textures; +using osu.Framework.IO.File; +using System.Linq; + +namespace osu.Game.Storyboards.Drawables +{ + public class StoryboardSprite : Sprite, IFlippable + { + public SpriteDefinition Definition { get; private set; } + + protected override bool ShouldBeAlive => Definition.HasCommands && base.ShouldBeAlive; + public override bool RemoveWhenNotAlive => !Definition.HasCommands || base.RemoveWhenNotAlive; + + public bool FlipH { get; set; } + public bool FlipV { get; set; } + protected override Vector2 DrawScale => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + + public StoryboardSprite(SpriteDefinition definition) + { + Definition = definition; + Origin = definition.Origin; + Position = definition.InitialPosition; + + if (definition.HasCommands) + { + LifetimeStart = definition.StartTime; + LifetimeEnd = definition.EndTime; + } + } + + [BackgroundDependencyLoader] + private void load(OsuGameBase game, TextureStore textureStore) + { + var spritePath = Definition.Path; + var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename == spritePath)?.FileInfo.StoragePath; + if (path == null) + return; + + Texture = textureStore.Get(path); + Definition.ApplyTransforms(this); + } + } +} diff --git a/osu.Game/Storyboards/ElementDefinition.cs b/osu.Game/Storyboards/ElementDefinition.cs new file mode 100644 index 0000000000..1a8de9a120 --- /dev/null +++ b/osu.Game/Storyboards/ElementDefinition.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; + +namespace osu.Game.Storyboards +{ + public interface ElementDefinition + { + string Path { get; } + Drawable CreateDrawable(); + } +} diff --git a/osu.Game/Storyboards/LayerDefinition.cs b/osu.Game/Storyboards/LayerDefinition.cs new file mode 100644 index 0000000000..e632a700f1 --- /dev/null +++ b/osu.Game/Storyboards/LayerDefinition.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Storyboards.Drawables; +using System.Collections.Generic; + +namespace osu.Game.Storyboards +{ + public class LayerDefinition + { + public string Name; + public int Depth; + public bool EnabledWhenPassing = true; + public bool ShowWhenFailing = true; + + private List elements = new List(); + public IEnumerable Elements => elements; + + public LayerDefinition(string name, int depth) + { + Name = name; + Depth = depth; + } + + public void Add(ElementDefinition element) + { + elements.Add(element); + } + + public StoryboardLayer CreateDrawable() + => new StoryboardLayer(this) { Depth = Depth, }; + } +} diff --git a/osu.Game/Storyboards/SampleDefinition.cs b/osu.Game/Storyboards/SampleDefinition.cs new file mode 100644 index 0000000000..26d2c4b029 --- /dev/null +++ b/osu.Game/Storyboards/SampleDefinition.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; + +namespace osu.Game.Storyboards +{ + public class SampleDefinition : ElementDefinition + { + public string Path { get; private set; } + public double Time; + public float Volume; + + public SampleDefinition(string path, double time, float volume) + { + Path = path; + Time = time; + Volume = volume; + } + + public Drawable CreateDrawable() + => null; + } +} diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs new file mode 100644 index 0000000000..2574e7adb6 --- /dev/null +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using OpenTK; +using osu.Framework.Graphics; +using osu.Game.Storyboards.Drawables; +using System.Collections.Generic; + +namespace osu.Game.Storyboards +{ + public class SpriteDefinition : CommandTimelineGroup, ElementDefinition + { + public string Path { get; private set; } + public Anchor Origin; + public Vector2 InitialPosition; + + private List loops = new List(); + private List triggers = new List(); + + public SpriteDefinition(string path, Anchor origin, Vector2 initialPosition) + { + Path = path; + Origin = origin; + InitialPosition = initialPosition; + } + + public CommandLoop AddLoop(double startTime, int loopCount) + { + var loop = new CommandLoop(startTime, loopCount); + loops.Add(loop); + return loop; + } + + public CommandTrigger AddTrigger(string triggerName, double startTime, double endTime, int groupNumber) + { + var trigger = new CommandTrigger(triggerName, startTime, endTime, groupNumber); + triggers.Add(trigger); + return trigger; + } + + public virtual Drawable CreateDrawable() + => new StoryboardSprite(this); + + public override void ApplyTransforms(Drawable target) + { + base.ApplyTransforms(target); + foreach (var loop in loops) + loop.ApplyTransforms(target); + + // TODO + return; + foreach (var trigger in triggers) + trigger.ApplyTransforms(target); + } + + public override string ToString() + => $"{Path}, {Origin}, {InitialPosition}"; + } +} diff --git a/osu.Game/Storyboards/StoryboardDefinition.cs b/osu.Game/Storyboards/StoryboardDefinition.cs new file mode 100644 index 0000000000..853ebe42dc --- /dev/null +++ b/osu.Game/Storyboards/StoryboardDefinition.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Storyboards.Drawables; +using System.Collections.Generic; +using System.Linq; +using System; + +namespace osu.Game.Storyboards +{ + public class StoryboardDefinition + { + private Dictionary layers = new Dictionary(); + public IEnumerable Layers => layers.Values; + + public StoryboardDefinition() + { + layers.Add("Background", new LayerDefinition("Background", 3)); + layers.Add("Fail", new LayerDefinition("Fail", 2) { EnabledWhenPassing = false, }); + layers.Add("Pass", new LayerDefinition("Pass", 1) { ShowWhenFailing = false, }); + layers.Add("Foreground", new LayerDefinition("Foreground", 0)); + } + + public LayerDefinition GetLayer(string name) + { + LayerDefinition layer; + if (!layers.TryGetValue(name, out layer)) + layers[name] = layer = new LayerDefinition(name, layers.Values.Min(l => l.Depth) - 1); + + return layer; + } + + public Storyboard CreateDrawable() + => new Storyboard(this); + } +} diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 05ba3e25ab..2703798a6c 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -80,6 +80,21 @@ + + + + + + + + + + + + + + + From 13322b4293ad27ed6a672f2492c21b2bf5f5a12e Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 12:09:45 +0200 Subject: [PATCH 02/64] Improve compatibility with older storyboards. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 08e1d06621..bcb2c6f666 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -248,7 +248,7 @@ namespace osu.Game.Beatmaps.Formats while (line.StartsWith(" ") || line.StartsWith("_")) { ++depth; - line = line.Substring(depth); + line = line.Substring(1); } decodeVariables(ref line); @@ -305,7 +305,7 @@ namespace osu.Game.Beatmaps.Formats var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); var frameCount = int.Parse(split[6]); var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo); - var loopType = (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]); + var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever; spriteDefinition = new AnimationDefinition(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); beatmap.Storyboard.GetLayer(layer).Add(spriteDefinition); } @@ -315,7 +315,7 @@ namespace osu.Game.Beatmaps.Formats var time = double.Parse(split[1], CultureInfo.InvariantCulture); var layer = split[2]; var path = cleanFilename(split[3]); - var volume = float.Parse(split[4], CultureInfo.InvariantCulture); + var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100; beatmap.Storyboard.GetLayer(layer).Add(new SampleDefinition(path, time, volume)); } break; @@ -326,13 +326,14 @@ namespace osu.Game.Beatmaps.Formats if (depth < 2) timelineGroup = spriteDefinition; - switch (split[0]) + var commandType = split[0]; + switch (commandType) { case "T": { var triggerName = split[1]; - var startTime = double.Parse(split[2], CultureInfo.InvariantCulture); - var endTime = double.Parse(split[3], CultureInfo.InvariantCulture); + var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue; + var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue; var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0; timelineGroup = spriteDefinition?.AddTrigger(triggerName, startTime, endTime, groupNumber); } @@ -349,7 +350,6 @@ namespace osu.Game.Beatmaps.Formats if (string.IsNullOrEmpty(split[3])) split[3] = split[2]; - var commandType = split[0]; var easing = (Easing)int.Parse(split[1]); var startTime = double.Parse(split[2], CultureInfo.InvariantCulture); var endTime = double.Parse(split[3], CultureInfo.InvariantCulture); @@ -434,6 +434,8 @@ namespace osu.Game.Beatmaps.Formats } } break; + default: + throw new InvalidDataException($@"Unknown command type: {commandType}"); } } break; From e02b481c6907e17526e53a3edfa9c296583d1934 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 12:11:57 +0200 Subject: [PATCH 03/64] An attempt at implementing storyboard loops. --- osu.Game/Storyboards/CommandLoop.cs | 20 ++++---- osu.Game/Storyboards/CommandTimeline.cs | 28 +++++++---- osu.Game/Storyboards/CommandTimelineGroup.cs | 50 ++++++++++++-------- osu.Game/Storyboards/Drawables/Storyboard.cs | 2 +- osu.Game/Storyboards/LayerDefinition.cs | 4 +- osu.Game/Storyboards/SpriteDefinition.cs | 16 +++---- osu.Game/Storyboards/StoryboardDefinition.cs | 5 +- 7 files changed, 71 insertions(+), 54 deletions(-) diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index b93a04cea1..d8d059aaed 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -2,26 +2,28 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; namespace osu.Game.Storyboards { public class CommandLoop : CommandTimelineGroup { - private double startTime; - private int loopCount; + public double LoopStartTime; + public int LoopCount; public CommandLoop(double startTime, int loopCount) { - this.startTime = startTime; - this.loopCount = loopCount; + LoopStartTime = startTime; + LoopCount = loopCount; } - public override void ApplyTransforms(Drawable drawable) - { - //base.ApplyTransforms(drawable); - } + public override void ApplyTransforms(Drawable drawable, double offset = 0) + => base.ApplyTransforms(drawable, offset + LoopStartTime); + + protected override void PostProcess(Command command, TransformSequence sequence) + => sequence.Loop(Duration - command.Duration, LoopCount); public override string ToString() - => $"{startTime} x{loopCount}"; + => $"{LoopStartTime} x{LoopCount}"; } } diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index 04e165aa38..a533f213fc 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -10,8 +10,8 @@ namespace osu.Game.Storyboards { public class CommandTimeline : CommandTimeline { - private readonly List commands = new List(); - public IEnumerable Commands => commands.OrderBy(c => c.StartTime); + private readonly List commands = new List(); + public IEnumerable Commands => commands.OrderBy(c => c.StartTime); public bool HasCommands => commands.Count > 0; private Cached startTimeBacking; @@ -19,7 +19,7 @@ namespace osu.Game.Storyboards private Cached endTimeBacking; public double EndTime => endTimeBacking.IsValid ? endTimeBacking : (endTimeBacking.Value = HasCommands ? commands.Max(c => c.EndTime) : double.MaxValue); - + public T StartValue => HasCommands ? commands.OrderBy(c => c.StartTime).First().StartValue : default(T); public T EndValue => HasCommands ? commands.OrderByDescending(c => c.EndTime).First().EndValue : default(T); @@ -28,7 +28,7 @@ namespace osu.Game.Storyboards if (endTime < startTime) return; - commands.Add(new Command { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue, }); + commands.Add(new TypedCommand { Easing = easing, StartTime = startTime, EndTime = endTime, StartValue = startValue, EndValue = endValue, }); startTimeBacking.Invalidate(); endTimeBacking.Invalidate(); @@ -37,16 +37,16 @@ namespace osu.Game.Storyboards public override string ToString() => $"{commands.Count} command(s)"; - public class Command + public class TypedCommand : Command { - public Easing Easing; - public double StartTime; - public double EndTime; + public Easing Easing { get; set; } + public double StartTime { get; set; } + public double EndTime { get; set; } + public double Duration => EndTime - StartTime; + public T StartValue; public T EndValue; - public double Duration => EndTime - StartTime; - public override string ToString() => $"{StartTime} -> {EndTime}, {StartValue} -> {EndValue} {Easing}"; } @@ -58,4 +58,12 @@ namespace osu.Game.Storyboards double EndTime { get; } bool HasCommands { get; } } + + public interface Command + { + Easing Easing { get; set; } + double StartTime { get; set; } + double EndTime { get; set; } + double Duration { get; } + } } diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index cc67c9dd68..109104b120 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -4,6 +4,7 @@ using OpenTK; using OpenTK.Graphics; using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; using osu.Game.Storyboards.Drawables; using System.Collections.Generic; using System.Linq; @@ -40,45 +41,52 @@ namespace osu.Game.Storyboards public double StartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime); public double EndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime); + public double Duration => EndTime - StartTime; public bool HasCommands => Timelines.Any(t => t.HasCommands); - public virtual void ApplyTransforms(Drawable drawable) + public virtual void ApplyTransforms(Drawable drawable, double offset = 0) { if (X.HasCommands) drawable.X = X.StartValue; foreach (var command in X.Commands) - using (drawable.BeginAbsoluteSequence(command.StartTime)) - drawable.MoveToX(command.StartValue) - .MoveToX(command.EndValue, command.Duration, command.Easing); + using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) + PostProcess(command, + drawable.MoveToX(command.StartValue) + .MoveToX(command.EndValue, command.Duration, command.Easing)); if (Y.HasCommands) drawable.Y = Y.StartValue; foreach (var command in Y.Commands) - using (drawable.BeginAbsoluteSequence(command.StartTime)) - drawable.MoveToY(command.StartValue) - .MoveToY(command.EndValue, command.Duration, command.Easing); + using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) + PostProcess(command, + drawable.MoveToY(command.StartValue) + .MoveToY(command.EndValue, command.Duration, command.Easing)); if (Scale.HasCommands) drawable.Scale = Scale.StartValue; foreach (var command in Scale.Commands) - using (drawable.BeginAbsoluteSequence(command.StartTime)) - drawable.ScaleTo(command.StartValue) - .ScaleTo(command.EndValue, command.Duration, command.Easing); + using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) + PostProcess(command, + drawable.ScaleTo(command.StartValue) + .ScaleTo(command.EndValue, command.Duration, command.Easing)); if (Rotation.HasCommands) drawable.Rotation = Rotation.StartValue; foreach (var command in Rotation.Commands) - using (drawable.BeginAbsoluteSequence(command.StartTime)) - drawable.RotateTo(command.StartValue) - .RotateTo(command.EndValue, command.Duration, command.Easing); + using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) + PostProcess(command, + drawable.RotateTo(command.StartValue) + .RotateTo(command.EndValue, command.Duration, command.Easing)); if (Colour.HasCommands) drawable.Colour = Colour.StartValue; foreach (var command in Colour.Commands) - using (drawable.BeginAbsoluteSequence(command.StartTime)) - drawable.FadeColour(command.StartValue) - .FadeColour(command.EndValue, command.Duration, command.Easing); + using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) + PostProcess(command, + drawable.FadeColour(command.StartValue) + .FadeColour(command.EndValue, command.Duration, command.Easing)); if (Alpha.HasCommands) drawable.Alpha = Alpha.StartValue; foreach (var command in Alpha.Commands) - using (drawable.BeginAbsoluteSequence(command.StartTime)) - drawable.FadeTo(command.StartValue) - .FadeTo(command.EndValue, command.Duration, command.Easing); + using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) + PostProcess(command, + drawable.FadeTo(command.StartValue) + .FadeTo(command.EndValue, command.Duration, command.Easing)); if (Additive.HasCommands) drawable.BlendingMode = BlendingMode.Additive; @@ -90,5 +98,9 @@ namespace osu.Game.Storyboards flippable.FlipV = FlipV.HasCommands; } } + + protected virtual void PostProcess(Command command, TransformSequence sequence) + { + } } } diff --git a/osu.Game/Storyboards/Drawables/Storyboard.cs b/osu.Game/Storyboards/Drawables/Storyboard.cs index a5b242357f..45aa063f79 100644 --- a/osu.Game/Storyboards/Drawables/Storyboard.cs +++ b/osu.Game/Storyboards/Drawables/Storyboard.cs @@ -53,7 +53,7 @@ namespace osu.Game.Storyboards.Drawables private void updateLayerVisibility() { foreach (var layer in Children) - layer.Enabled = passing ? layer.Definition.EnabledWhenPassing : layer.Definition.ShowWhenFailing; + layer.Enabled = passing ? layer.Definition.EnabledWhenPassing : layer.Definition.EnabledWhenFailing; } } } diff --git a/osu.Game/Storyboards/LayerDefinition.cs b/osu.Game/Storyboards/LayerDefinition.cs index e632a700f1..871462c3fd 100644 --- a/osu.Game/Storyboards/LayerDefinition.cs +++ b/osu.Game/Storyboards/LayerDefinition.cs @@ -11,11 +11,11 @@ namespace osu.Game.Storyboards public string Name; public int Depth; public bool EnabledWhenPassing = true; - public bool ShowWhenFailing = true; + public bool EnabledWhenFailing = true; private List elements = new List(); public IEnumerable Elements => elements; - + public LayerDefinition(string name, int depth) { Name = name; diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index 2574e7adb6..b47b6c935e 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -5,6 +5,7 @@ using OpenTK; using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; using System.Collections.Generic; +using System.Linq; namespace osu.Game.Storyboards { @@ -16,7 +17,7 @@ namespace osu.Game.Storyboards private List loops = new List(); private List triggers = new List(); - + public SpriteDefinition(string path, Anchor origin, Vector2 initialPosition) { Path = path; @@ -41,16 +42,11 @@ namespace osu.Game.Storyboards public virtual Drawable CreateDrawable() => new StoryboardSprite(this); - public override void ApplyTransforms(Drawable target) + public override void ApplyTransforms(Drawable target, double offset = 0) { - base.ApplyTransforms(target); - foreach (var loop in loops) - loop.ApplyTransforms(target); - - // TODO - return; - foreach (var trigger in triggers) - trigger.ApplyTransforms(target); + base.ApplyTransforms(target, offset); + foreach (var loop in loops.OrderBy(l => l.StartTime)) + loop.ApplyTransforms(target, offset); } public override string ToString() diff --git a/osu.Game/Storyboards/StoryboardDefinition.cs b/osu.Game/Storyboards/StoryboardDefinition.cs index 853ebe42dc..e357440bc9 100644 --- a/osu.Game/Storyboards/StoryboardDefinition.cs +++ b/osu.Game/Storyboards/StoryboardDefinition.cs @@ -4,7 +4,6 @@ using osu.Game.Storyboards.Drawables; using System.Collections.Generic; using System.Linq; -using System; namespace osu.Game.Storyboards { @@ -12,12 +11,12 @@ namespace osu.Game.Storyboards { private Dictionary layers = new Dictionary(); public IEnumerable Layers => layers.Values; - + public StoryboardDefinition() { layers.Add("Background", new LayerDefinition("Background", 3)); layers.Add("Fail", new LayerDefinition("Fail", 2) { EnabledWhenPassing = false, }); - layers.Add("Pass", new LayerDefinition("Pass", 1) { ShowWhenFailing = false, }); + layers.Add("Pass", new LayerDefinition("Pass", 1) { EnabledWhenFailing = false, }); layers.Add("Foreground", new LayerDefinition("Foreground", 0)); } From 6cde687d87fd27e16fc8754ad3d8d0bdd51cad25 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 12:36:13 +0200 Subject: [PATCH 04/64] Fix V commands parsing. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index bcb2c6f666..6fde7263da 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -376,7 +376,7 @@ namespace osu.Game.Beatmaps.Formats var startY = float.Parse(split[5], CultureInfo.InvariantCulture); var endX = split.Length > 6 ? float.Parse(split[6], CultureInfo.InvariantCulture) : startX; var endY = split.Length > 7 ? float.Parse(split[7], CultureInfo.InvariantCulture) : startY; - timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(startX, endY)); + timelineGroup?.Scale.Add(easing, startTime, endTime, new Vector2(startX, startY), new Vector2(endX, endY)); } break; case "R": From e63fb5720c219aafdeaac3f76c3d2f34a8ea3b71 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 13:04:53 +0200 Subject: [PATCH 05/64] Make CI happy. --- osu.Desktop.Tests/Visual/TestCaseStoryboard.cs | 5 ++--- osu.Game/Storyboards/CommandLoop.cs | 2 +- osu.Game/Storyboards/CommandTimeline.cs | 8 ++++---- osu.Game/Storyboards/CommandTimelineGroup.cs | 4 ++-- osu.Game/Storyboards/CommandTrigger.cs | 18 +++++++++--------- .../Drawables/StoryboardAnimation.cs | 1 - .../Storyboards/Drawables/StoryboardSprite.cs | 1 - ...mentDefinition.cs => IElementDefinition.cs} | 2 +- osu.Game/Storyboards/LayerDefinition.cs | 6 +++--- osu.Game/Storyboards/SampleDefinition.cs | 4 ++-- osu.Game/Storyboards/SpriteDefinition.cs | 8 ++++---- osu.Game/osu.Game.csproj | 2 +- 12 files changed, 29 insertions(+), 32 deletions(-) rename osu.Game/Storyboards/{ElementDefinition.cs => IElementDefinition.cs} (84%) diff --git a/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs index 1d7b3dffd2..10dd706f62 100644 --- a/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs @@ -21,8 +21,7 @@ namespace osu.Desktop.Tests.Visual private readonly Bindable beatmapBacking = new Bindable(); - private MusicController musicController; - private Container storyboardContainer; + private readonly Container storyboardContainer; private Storyboard storyboard; public TestCaseStoryboard() @@ -45,7 +44,7 @@ namespace osu.Desktop.Tests.Visual }, }, }); - Add(musicController = new MusicController + Add(new MusicController { Origin = Anchor.TopRight, Anchor = Anchor.TopRight, diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index d8d059aaed..d7eb041de1 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -20,7 +20,7 @@ namespace osu.Game.Storyboards public override void ApplyTransforms(Drawable drawable, double offset = 0) => base.ApplyTransforms(drawable, offset + LoopStartTime); - protected override void PostProcess(Command command, TransformSequence sequence) + protected override void PostProcess(ICommand command, TransformSequence sequence) => sequence.Loop(Duration - command.Duration, LoopCount); public override string ToString() diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index a533f213fc..909a629ad2 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -8,7 +8,7 @@ using System.Linq; namespace osu.Game.Storyboards { - public class CommandTimeline : CommandTimeline + public class CommandTimeline : ICommandTimeline { private readonly List commands = new List(); public IEnumerable Commands => commands.OrderBy(c => c.StartTime); @@ -37,7 +37,7 @@ namespace osu.Game.Storyboards public override string ToString() => $"{commands.Count} command(s)"; - public class TypedCommand : Command + public class TypedCommand : ICommand { public Easing Easing { get; set; } public double StartTime { get; set; } @@ -52,14 +52,14 @@ namespace osu.Game.Storyboards } } - public interface CommandTimeline + public interface ICommandTimeline { double StartTime { get; } double EndTime { get; } bool HasCommands { get; } } - public interface Command + public interface ICommand { Easing Easing { get; set; } double StartTime { get; set; } diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index 109104b120..cff8d54d29 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -23,7 +23,7 @@ namespace osu.Game.Storyboards public CommandTimeline FlipH = new CommandTimeline(); public CommandTimeline FlipV = new CommandTimeline(); - public IEnumerable Timelines + public IEnumerable Timelines { get { @@ -99,7 +99,7 @@ namespace osu.Game.Storyboards } } - protected virtual void PostProcess(Command command, TransformSequence sequence) + protected virtual void PostProcess(ICommand command, TransformSequence sequence) { } } diff --git a/osu.Game/Storyboards/CommandTrigger.cs b/osu.Game/Storyboards/CommandTrigger.cs index e7133e170f..e2731f9c45 100644 --- a/osu.Game/Storyboards/CommandTrigger.cs +++ b/osu.Game/Storyboards/CommandTrigger.cs @@ -5,20 +5,20 @@ namespace osu.Game.Storyboards { public class CommandTrigger : CommandTimelineGroup { - private string triggerName; - private double startTime; - private double endTime; - private int groupNumber; + public string TriggerName; + public double TriggerStartTime; + public double TriggerEndTime; + public int GroupNumber; public CommandTrigger(string triggerName, double startTime, double endTime, int groupNumber) { - this.triggerName = triggerName; - this.startTime = startTime; - this.endTime = endTime; - this.groupNumber = groupNumber; + TriggerName = triggerName; + TriggerStartTime = startTime; + TriggerEndTime = endTime; + GroupNumber = groupNumber; } public override string ToString() - => $"{triggerName} {startTime} -> {endTime} ({groupNumber})"; + => $"{TriggerName} {TriggerStartTime} -> {TriggerEndTime} ({GroupNumber})"; } } diff --git a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs index 583a0d13c3..c3a4e8b865 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs @@ -5,7 +5,6 @@ using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Textures; -using osu.Framework.IO.File; using System.Linq; namespace osu.Game.Storyboards.Drawables diff --git a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs index 927996d750..35cd19474e 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs @@ -5,7 +5,6 @@ using OpenTK; using osu.Framework.Allocation; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; -using osu.Framework.IO.File; using System.Linq; namespace osu.Game.Storyboards.Drawables diff --git a/osu.Game/Storyboards/ElementDefinition.cs b/osu.Game/Storyboards/IElementDefinition.cs similarity index 84% rename from osu.Game/Storyboards/ElementDefinition.cs rename to osu.Game/Storyboards/IElementDefinition.cs index 1a8de9a120..93c9a473f7 100644 --- a/osu.Game/Storyboards/ElementDefinition.cs +++ b/osu.Game/Storyboards/IElementDefinition.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics; namespace osu.Game.Storyboards { - public interface ElementDefinition + public interface IElementDefinition { string Path { get; } Drawable CreateDrawable(); diff --git a/osu.Game/Storyboards/LayerDefinition.cs b/osu.Game/Storyboards/LayerDefinition.cs index 871462c3fd..baefe1626a 100644 --- a/osu.Game/Storyboards/LayerDefinition.cs +++ b/osu.Game/Storyboards/LayerDefinition.cs @@ -13,8 +13,8 @@ namespace osu.Game.Storyboards public bool EnabledWhenPassing = true; public bool EnabledWhenFailing = true; - private List elements = new List(); - public IEnumerable Elements => elements; + private readonly List elements = new List(); + public IEnumerable Elements => elements; public LayerDefinition(string name, int depth) { @@ -22,7 +22,7 @@ namespace osu.Game.Storyboards Depth = depth; } - public void Add(ElementDefinition element) + public void Add(IElementDefinition element) { elements.Add(element); } diff --git a/osu.Game/Storyboards/SampleDefinition.cs b/osu.Game/Storyboards/SampleDefinition.cs index 26d2c4b029..5d5e8ef1e9 100644 --- a/osu.Game/Storyboards/SampleDefinition.cs +++ b/osu.Game/Storyboards/SampleDefinition.cs @@ -5,9 +5,9 @@ using osu.Framework.Graphics; namespace osu.Game.Storyboards { - public class SampleDefinition : ElementDefinition + public class SampleDefinition : IElementDefinition { - public string Path { get; private set; } + public string Path { get; set; } public double Time; public float Volume; diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index b47b6c935e..8529d66c7f 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -9,14 +9,14 @@ using System.Linq; namespace osu.Game.Storyboards { - public class SpriteDefinition : CommandTimelineGroup, ElementDefinition + public class SpriteDefinition : CommandTimelineGroup, IElementDefinition { - public string Path { get; private set; } + public string Path { get; set; } public Anchor Origin; public Vector2 InitialPosition; - private List loops = new List(); - private List triggers = new List(); + private readonly List loops = new List(); + private readonly List triggers = new List(); public SpriteDefinition(string path, Anchor origin, Vector2 initialPosition) { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 2703798a6c..8c91a9e80a 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -86,7 +86,7 @@ - + From 3f2598543c563fdb8765124088d7c7b03001173f Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 18:03:04 +0200 Subject: [PATCH 06/64] Fix CommandLoop start and end time. --- osu.Game/Storyboards/CommandLoop.cs | 5 ++++- osu.Game/Storyboards/CommandTimelineGroup.cs | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index d7eb041de1..a93903f4a9 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -11,6 +11,9 @@ namespace osu.Game.Storyboards public double LoopStartTime; public int LoopCount; + public override double StartTime => LoopStartTime; + public override double EndTime => LoopStartTime + CommandsDuration * LoopCount; + public CommandLoop(double startTime, int loopCount) { LoopStartTime = startTime; @@ -21,7 +24,7 @@ namespace osu.Game.Storyboards => base.ApplyTransforms(drawable, offset + LoopStartTime); protected override void PostProcess(ICommand command, TransformSequence sequence) - => sequence.Loop(Duration - command.Duration, LoopCount); + => sequence.Loop(CommandsDuration - command.Duration, LoopCount); public override string ToString() => $"{LoopStartTime} x{LoopCount}"; diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index cff8d54d29..badd9a810a 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -39,9 +39,14 @@ namespace osu.Game.Storyboards } } - public double StartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime); - public double EndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime); + public double CommandsStartTime => Timelines.Where(t => t.HasCommands).Min(t => t.StartTime); + public double CommandsEndTime => Timelines.Where(t => t.HasCommands).Max(t => t.EndTime); + public double CommandsDuration => CommandsEndTime - CommandsStartTime; + + public virtual double StartTime => CommandsStartTime; + public virtual double EndTime => CommandsEndTime; public double Duration => EndTime - StartTime; + public bool HasCommands => Timelines.Any(t => t.HasCommands); public virtual void ApplyTransforms(Drawable drawable, double offset = 0) From 15dd8d9071597c872e3d9296d2fcd3fe597a2e9f Mon Sep 17 00:00:00 2001 From: MrTheMake Date: Fri, 8 Sep 2017 18:21:42 +0200 Subject: [PATCH 07/64] Mind the minimum size of the channel selection overlay --- osu.Game/Overlays/ChatOverlay.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index b1deae8272..af5c6d9916 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -212,7 +212,13 @@ namespace osu.Game.Overlays { Trace.Assert(state.Mouse.PositionMouseDown != null); - chatHeight.Value = startDragChatHeight - (state.Mouse.Position.Y - state.Mouse.PositionMouseDown.Value.Y) / Parent.DrawSize.Y; + double targetChatHeight = startDragChatHeight - (state.Mouse.Position.Y - state.Mouse.PositionMouseDown.Value.Y) / Parent.DrawSize.Y; + + // If the channel selection screen is shown, mind its minimum height + if (channelSelection.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) + targetChatHeight = 1f - channel_selection_min_height; + + chatHeight.Value = targetChatHeight; } return true; From e4a2ad5eb5a31e41bc83e2db385f985ec1606497 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 20:39:17 +0200 Subject: [PATCH 08/64] Fix storyboard sprite flipping. --- .../Drawables/StoryboardAnimation.cs | 31 ++++++++++++++++++- .../Storyboards/Drawables/StoryboardSprite.cs | 31 ++++++++++++++++++- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs index c3a4e8b865..eb2ba59397 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs @@ -3,6 +3,7 @@ using OpenTK; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Textures; using System.Linq; @@ -18,7 +19,35 @@ namespace osu.Game.Storyboards.Drawables public bool FlipH { get; set; } public bool FlipV { get; set; } - protected override Vector2 DrawScale => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + + protected override Vector2 DrawScale + => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + + public override Anchor Origin + { + get + { + var origin = base.Origin; + + if (FlipH) + { + if (origin.HasFlag(Anchor.x0)) + origin = Anchor.x2 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2)); + else if (origin.HasFlag(Anchor.x2)) + origin = Anchor.x0 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2)); + } + + if (FlipV) + { + if (origin.HasFlag(Anchor.y0)) + origin = Anchor.y2 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2)); + else if (origin.HasFlag(Anchor.y2)) + origin = Anchor.y0 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2)); + } + + return origin; + } + } public StoryboardAnimation(AnimationDefinition definition) { diff --git a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs index 35cd19474e..565b5a5069 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs @@ -3,6 +3,7 @@ using OpenTK; using osu.Framework.Allocation; +using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Textures; using System.Linq; @@ -18,7 +19,35 @@ namespace osu.Game.Storyboards.Drawables public bool FlipH { get; set; } public bool FlipV { get; set; } - protected override Vector2 DrawScale => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + + protected override Vector2 DrawScale + => new Vector2(FlipH ? -base.DrawScale.X : base.DrawScale.X, FlipV ? -base.DrawScale.Y : base.DrawScale.Y); + + public override Anchor Origin + { + get + { + var origin = base.Origin; + + if (FlipH) + { + if (origin.HasFlag(Anchor.x0)) + origin = Anchor.x2 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2)); + else if (origin.HasFlag(Anchor.x2)) + origin = Anchor.x0 | (origin & (Anchor.y0 | Anchor.y1 | Anchor.y2)); + } + + if (FlipV) + { + if (origin.HasFlag(Anchor.y0)) + origin = Anchor.y2 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2)); + else if (origin.HasFlag(Anchor.y2)) + origin = Anchor.y0 | (origin & (Anchor.x0 | Anchor.x1 | Anchor.x2)); + } + + return origin; + } + } public StoryboardSprite(SpriteDefinition definition) { From e8ab853f6f4ec4c630dfdfa7caa0b722aa765f58 Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 18:00:17 +0200 Subject: [PATCH 09/64] Make storyboard loops work. --- osu.Game/Storyboards/CommandLoop.cs | 17 +++-- osu.Game/Storyboards/CommandTimelineGroup.cs | 72 ++++---------------- osu.Game/Storyboards/SpriteDefinition.cs | 61 +++++++++++++++-- 3 files changed, 81 insertions(+), 69 deletions(-) diff --git a/osu.Game/Storyboards/CommandLoop.cs b/osu.Game/Storyboards/CommandLoop.cs index a93903f4a9..02b5eb0122 100644 --- a/osu.Game/Storyboards/CommandLoop.cs +++ b/osu.Game/Storyboards/CommandLoop.cs @@ -1,8 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using osu.Framework.Graphics; -using osu.Framework.Graphics.Transforms; +using System.Collections.Generic; namespace osu.Game.Storyboards { @@ -20,11 +19,15 @@ namespace osu.Game.Storyboards LoopCount = loopCount; } - public override void ApplyTransforms(Drawable drawable, double offset = 0) - => base.ApplyTransforms(drawable, offset + LoopStartTime); - - protected override void PostProcess(ICommand command, TransformSequence sequence) - => sequence.Loop(CommandsDuration - command.Duration, LoopCount); + public override IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) + { + for (var loop = 0; loop < LoopCount; loop++) + { + var loopOffset = LoopStartTime + loop * CommandsDuration; + foreach (var command in base.GetCommands(timelineSelector, offset + loopOffset)) + yield return command; + } + } public override string ToString() => $"{LoopStartTime} x{LoopCount}"; diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index badd9a810a..a42aca7c28 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -3,14 +3,13 @@ using OpenTK; using OpenTK.Graphics; -using osu.Framework.Graphics; -using osu.Framework.Graphics.Transforms; -using osu.Game.Storyboards.Drawables; using System.Collections.Generic; using System.Linq; namespace osu.Game.Storyboards { + public delegate CommandTimeline CommandTimelineSelector(CommandTimelineGroup commandTimelineGroup); + public class CommandTimelineGroup { public CommandTimeline X = new CommandTimeline(); @@ -49,63 +48,20 @@ namespace osu.Game.Storyboards public bool HasCommands => Timelines.Any(t => t.HasCommands); - public virtual void ApplyTransforms(Drawable drawable, double offset = 0) + public virtual IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { - if (X.HasCommands) drawable.X = X.StartValue; - foreach (var command in X.Commands) - using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) - PostProcess(command, - drawable.MoveToX(command.StartValue) - .MoveToX(command.EndValue, command.Duration, command.Easing)); + if (offset != 0) + return timelineSelector(this).Commands.Select(command => + new CommandTimeline.TypedCommand + { + Easing = command.Easing, + StartTime = offset + command.StartTime, + EndTime = offset + command.EndTime, + StartValue = command.StartValue, + EndValue = command.EndValue, + }); - if (Y.HasCommands) drawable.Y = Y.StartValue; - foreach (var command in Y.Commands) - using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) - PostProcess(command, - drawable.MoveToY(command.StartValue) - .MoveToY(command.EndValue, command.Duration, command.Easing)); - - if (Scale.HasCommands) drawable.Scale = Scale.StartValue; - foreach (var command in Scale.Commands) - using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) - PostProcess(command, - drawable.ScaleTo(command.StartValue) - .ScaleTo(command.EndValue, command.Duration, command.Easing)); - - if (Rotation.HasCommands) drawable.Rotation = Rotation.StartValue; - foreach (var command in Rotation.Commands) - using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) - PostProcess(command, - drawable.RotateTo(command.StartValue) - .RotateTo(command.EndValue, command.Duration, command.Easing)); - - if (Colour.HasCommands) drawable.Colour = Colour.StartValue; - foreach (var command in Colour.Commands) - using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) - PostProcess(command, - drawable.FadeColour(command.StartValue) - .FadeColour(command.EndValue, command.Duration, command.Easing)); - - if (Alpha.HasCommands) drawable.Alpha = Alpha.StartValue; - foreach (var command in Alpha.Commands) - using (drawable.BeginAbsoluteSequence(offset + command.StartTime)) - PostProcess(command, - drawable.FadeTo(command.StartValue) - .FadeTo(command.EndValue, command.Duration, command.Easing)); - - if (Additive.HasCommands) - drawable.BlendingMode = BlendingMode.Additive; - - var flippable = drawable as IFlippable; - if (flippable != null) - { - flippable.FlipH = FlipH.HasCommands; - flippable.FlipV = FlipV.HasCommands; - } - } - - protected virtual void PostProcess(ICommand command, TransformSequence sequence) - { + return timelineSelector(this).Commands; } } } diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index 8529d66c7f..c1a3588960 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -4,6 +4,7 @@ using OpenTK; using osu.Framework.Graphics; using osu.Game.Storyboards.Drawables; +using System; using System.Collections.Generic; using System.Linq; @@ -18,6 +19,9 @@ namespace osu.Game.Storyboards private readonly List loops = new List(); private readonly List triggers = new List(); + private delegate void DrawablePropertyInitializer(Drawable drawable, T value); + private delegate void DrawableTransformer(Drawable drawable, T value, double duration, Easing easing); + public SpriteDefinition(string path, Anchor origin, Vector2 initialPosition) { Path = path; @@ -42,11 +46,60 @@ namespace osu.Game.Storyboards public virtual Drawable CreateDrawable() => new StoryboardSprite(this); - public override void ApplyTransforms(Drawable target, double offset = 0) + public override IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) { - base.ApplyTransforms(target, offset); - foreach (var loop in loops.OrderBy(l => l.StartTime)) - loop.ApplyTransforms(target, offset); + var result = base.GetCommands(timelineSelector, offset); + foreach (var loop in loops) + result = result.Concat(loop.GetCommands(timelineSelector, offset)); + return result; + } + + public void ApplyTransforms(Drawable drawable, IEnumerable> triggeredGroups = null) + { + applyCommands(drawable, triggeredGroups, g => g.X, (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing)); + applyCommands(drawable, triggeredGroups, g => g.Y, (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing)); + applyCommands(drawable, triggeredGroups, g => g.Scale, (d, value) => d.Scale = value, (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); + applyCommands(drawable, triggeredGroups, g => g.Rotation, (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); + applyCommands(drawable, triggeredGroups, g => g.Colour, (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); + applyCommands(drawable, triggeredGroups, g => g.Alpha, (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); + + if (getAggregatedCommands(g => g.Additive, triggeredGroups).Any()) + drawable.BlendingMode = BlendingMode.Additive; + + var flippable = drawable as IFlippable; + if (flippable != null) + { + flippable.FlipH = getAggregatedCommands(g => g.FlipH, triggeredGroups).Any(); + flippable.FlipV = getAggregatedCommands(g => g.FlipV, triggeredGroups).Any(); + } + } + + private void applyCommands(Drawable drawable, IEnumerable> triggeredGroups, + CommandTimelineSelector timelineSelector, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform) + { + var initialized = false; + foreach (var command in getAggregatedCommands(timelineSelector, triggeredGroups)) + { + if (!initialized) + { + initializeProperty(drawable, command.StartValue); + initialized = true; + } + using (drawable.BeginAbsoluteSequence(command.StartTime)) + { + transform(drawable, command.StartValue, 0, Easing.None); + transform(drawable, command.EndValue, command.Duration, command.Easing); + } + } + } + + private IEnumerable.TypedCommand> getAggregatedCommands(CommandTimelineSelector timelineSelector, IEnumerable> triggeredGroups) + { + var commands = GetCommands(timelineSelector); + if (triggeredGroups != null) + foreach (var pair in triggeredGroups) + commands = commands.Concat(pair.Item1.GetCommands(timelineSelector, pair.Item2)); + return commands.OrderBy(l => l.StartTime); } public override string ToString() From 4ab243d885f78dc0595c57318216b4cac1fea2db Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 21:23:24 +0200 Subject: [PATCH 10/64] CI fixes. --- osu.Game/Storyboards/SpriteDefinition.cs | 4 ++-- osu.Game/Storyboards/StoryboardDefinition.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index c1a3588960..4f161a34f4 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -19,8 +19,8 @@ namespace osu.Game.Storyboards private readonly List loops = new List(); private readonly List triggers = new List(); - private delegate void DrawablePropertyInitializer(Drawable drawable, T value); - private delegate void DrawableTransformer(Drawable drawable, T value, double duration, Easing easing); + private delegate void DrawablePropertyInitializer(Drawable drawable, T value); + private delegate void DrawableTransformer(Drawable drawable, T value, double duration, Easing easing); public SpriteDefinition(string path, Anchor origin, Vector2 initialPosition) { diff --git a/osu.Game/Storyboards/StoryboardDefinition.cs b/osu.Game/Storyboards/StoryboardDefinition.cs index e357440bc9..4ef24cda91 100644 --- a/osu.Game/Storyboards/StoryboardDefinition.cs +++ b/osu.Game/Storyboards/StoryboardDefinition.cs @@ -9,7 +9,7 @@ namespace osu.Game.Storyboards { public class StoryboardDefinition { - private Dictionary layers = new Dictionary(); + private readonly Dictionary layers = new Dictionary(); public IEnumerable Layers => layers.Values; public StoryboardDefinition() From 57e53ff03a7ca3d2b310eda2de4eec0d277209dc Mon Sep 17 00:00:00 2001 From: Damnae Date: Fri, 8 Sep 2017 21:36:30 +0200 Subject: [PATCH 11/64] Fix diff-specific storyboard content being lost after loading. --- osu.Game/Beatmaps/Beatmap.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index e4568a1919..9b32a65453 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -56,6 +56,7 @@ namespace osu.Game.Beatmaps ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo; Breaks = original?.Breaks ?? Breaks; ComboColors = original?.ComboColors ?? ComboColors; + Storyboard = original?.Storyboard ?? Storyboard; } } From 8d55cb7f922968761a17bf4748050ca93da053c9 Mon Sep 17 00:00:00 2001 From: Damnae Date: Sat, 9 Sep 2017 11:00:58 +0200 Subject: [PATCH 12/64] Improve command sorting. --- osu.Game/Storyboards/CommandTimeline.cs | 10 +++++++++- osu.Game/Storyboards/SpriteDefinition.cs | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/osu.Game/Storyboards/CommandTimeline.cs b/osu.Game/Storyboards/CommandTimeline.cs index 909a629ad2..b9bb6629d1 100644 --- a/osu.Game/Storyboards/CommandTimeline.cs +++ b/osu.Game/Storyboards/CommandTimeline.cs @@ -3,6 +3,7 @@ using osu.Framework.Caching; using osu.Framework.Graphics; +using System; using System.Collections.Generic; using System.Linq; @@ -47,6 +48,13 @@ namespace osu.Game.Storyboards public T StartValue; public T EndValue; + public int CompareTo(ICommand other) + { + var result = StartTime.CompareTo(other.StartTime); + if (result != 0) return result; + return EndTime.CompareTo(other.EndTime); + } + public override string ToString() => $"{StartTime} -> {EndTime}, {StartValue} -> {EndValue} {Easing}"; } @@ -59,7 +67,7 @@ namespace osu.Game.Storyboards bool HasCommands { get; } } - public interface ICommand + public interface ICommand : IComparable { Easing Easing { get; set; } double StartTime { get; set; } diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index 4f161a34f4..a4697aabfb 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -78,7 +78,7 @@ namespace osu.Game.Storyboards CommandTimelineSelector timelineSelector, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform) { var initialized = false; - foreach (var command in getAggregatedCommands(timelineSelector, triggeredGroups)) + foreach (var command in getAggregatedCommands(timelineSelector, triggeredGroups).OrderBy(l => l)) { if (!initialized) { @@ -99,7 +99,7 @@ namespace osu.Game.Storyboards if (triggeredGroups != null) foreach (var pair in triggeredGroups) commands = commands.Concat(pair.Item1.GetCommands(timelineSelector, pair.Item2)); - return commands.OrderBy(l => l.StartTime); + return commands; } public override string ToString() From bc01d9a1b04f5909eac2e9829c25243b79cbb7ea Mon Sep 17 00:00:00 2001 From: Damnae Date: Sat, 9 Sep 2017 15:34:26 +0200 Subject: [PATCH 13/64] Animate Additive / FlipH and FlipV. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 6 +-- osu.Game/Storyboards/CommandTimelineGroup.cs | 5 +- .../Drawables/DrawablesExtensions.cs | 27 +++++++++++ osu.Game/Storyboards/Drawables/IFlippable.cs | 46 ++++++++++++++++++- osu.Game/Storyboards/SpriteDefinition.cs | 14 +++--- osu.Game/osu.Game.csproj | 1 + 6 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 osu.Game/Storyboards/Drawables/DrawablesExtensions.cs diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index 6fde7263da..d538960a37 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -428,9 +428,9 @@ namespace osu.Game.Beatmaps.Formats var type = split[4]; switch (type) { - case "A": timelineGroup?.Additive.Add(easing, startTime, endTime, true, true); break; - case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, true); break; - case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, true); break; + case "A": timelineGroup?.BlendingMode.Add(easing, startTime, endTime, BlendingMode.Additive, startTime == endTime ? BlendingMode.Additive : BlendingMode.Inherit); break; + case "H": timelineGroup?.FlipH.Add(easing, startTime, endTime, true, startTime == endTime); break; + case "V": timelineGroup?.FlipV.Add(easing, startTime, endTime, true, startTime == endTime); break; } } break; diff --git a/osu.Game/Storyboards/CommandTimelineGroup.cs b/osu.Game/Storyboards/CommandTimelineGroup.cs index a42aca7c28..332a6f79cb 100644 --- a/osu.Game/Storyboards/CommandTimelineGroup.cs +++ b/osu.Game/Storyboards/CommandTimelineGroup.cs @@ -3,6 +3,7 @@ using OpenTK; using OpenTK.Graphics; +using osu.Framework.Graphics; using System.Collections.Generic; using System.Linq; @@ -18,7 +19,7 @@ namespace osu.Game.Storyboards public CommandTimeline Rotation = new CommandTimeline(); public CommandTimeline Colour = new CommandTimeline(); public CommandTimeline Alpha = new CommandTimeline(); - public CommandTimeline Additive = new CommandTimeline(); + public CommandTimeline BlendingMode = new CommandTimeline(); public CommandTimeline FlipH = new CommandTimeline(); public CommandTimeline FlipV = new CommandTimeline(); @@ -32,7 +33,7 @@ namespace osu.Game.Storyboards yield return Rotation; yield return Colour; yield return Alpha; - yield return Additive; + yield return BlendingMode; yield return FlipH; yield return FlipV; } diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs new file mode 100644 index 0000000000..436b4aafeb --- /dev/null +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs @@ -0,0 +1,27 @@ +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; + +namespace osu.Game.Storyboards.Drawables +{ + public static class DrawablesExtensions + { + /// + /// Adjusts after a delay. + /// + /// A to which further transforms can be added. + public static TransformSequence TransformBlendingMode(this T drawable, BlendingMode newValue, double delay = 0) + where T : Drawable + => drawable.TransformTo(drawable.PopulateTransform(new TransformBlendingMode(), newValue, delay)); + } + + public class TransformBlendingMode : Transform + { + private BlendingMode valueAt(double time) + => time < EndTime ? StartValue : EndValue; + + public override string TargetMember => nameof(Drawable.BlendingMode); + + protected override void Apply(Drawable d, double time) => d.BlendingMode = valueAt(time); + protected override void ReadIntoStartValue(Drawable d) => StartValue = d.BlendingMode; + } +} diff --git a/osu.Game/Storyboards/Drawables/IFlippable.cs b/osu.Game/Storyboards/Drawables/IFlippable.cs index a1899d1411..4d21c9d140 100644 --- a/osu.Game/Storyboards/Drawables/IFlippable.cs +++ b/osu.Game/Storyboards/Drawables/IFlippable.cs @@ -1,11 +1,55 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using osu.Framework.Graphics; +using osu.Framework.Graphics.Transforms; + namespace osu.Game.Storyboards.Drawables { - public interface IFlippable + public interface IFlippable : ITransformable { bool FlipH { get; set; } bool FlipV { get; set; } } + + public class TransformFlipH : Transform + { + private bool valueAt(double time) + => time < EndTime ? StartValue : EndValue; + + public override string TargetMember => nameof(IFlippable.FlipH); + + protected override void Apply(IFlippable d, double time) => d.FlipH = valueAt(time); + protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipH; + } + + public class TransformFlipV : Transform + { + private bool valueAt(double time) + => time < EndTime ? StartValue : EndValue; + + public override string TargetMember => nameof(IFlippable.FlipV); + + protected override void Apply(IFlippable d, double time) => d.FlipV = valueAt(time); + protected override void ReadIntoStartValue(IFlippable d) => StartValue = d.FlipV; + } + + public static class FlippableExtensions + { + /// + /// Adjusts after a delay. + /// + /// A to which further transforms can be added. + public static TransformSequence TransformFlipH(this T flippable, bool newValue, double delay = 0) + where T : IFlippable + => flippable.TransformTo(flippable.PopulateTransform(new TransformFlipH(), newValue, delay)); + + /// + /// Adjusts after a delay. + /// + /// A to which further transforms can be added. + public static TransformSequence TransformFlipV(this T flippable, bool newValue, double delay = 0) + where T : IFlippable + => flippable.TransformTo(flippable.PopulateTransform(new TransformFlipV(), newValue, delay)); + } } diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index a4697aabfb..c410fd8807 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -62,27 +62,27 @@ namespace osu.Game.Storyboards applyCommands(drawable, triggeredGroups, g => g.Rotation, (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); applyCommands(drawable, triggeredGroups, g => g.Colour, (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); applyCommands(drawable, triggeredGroups, g => g.Alpha, (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - - if (getAggregatedCommands(g => g.Additive, triggeredGroups).Any()) - drawable.BlendingMode = BlendingMode.Additive; + applyCommands(drawable, triggeredGroups, g => g.BlendingMode, (d, value) => d.BlendingMode = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); var flippable = drawable as IFlippable; if (flippable != null) { - flippable.FlipH = getAggregatedCommands(g => g.FlipH, triggeredGroups).Any(); - flippable.FlipV = getAggregatedCommands(g => g.FlipV, triggeredGroups).Any(); + applyCommands(drawable, triggeredGroups, g => g.FlipH, (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); + applyCommands(drawable, triggeredGroups, g => g.FlipV, (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); } } private void applyCommands(Drawable drawable, IEnumerable> triggeredGroups, - CommandTimelineSelector timelineSelector, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform) + CommandTimelineSelector timelineSelector, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, bool alwaysInitialize = true) + where T : struct { var initialized = false; foreach (var command in getAggregatedCommands(timelineSelector, triggeredGroups).OrderBy(l => l)) { if (!initialized) { - initializeProperty(drawable, command.StartValue); + if (alwaysInitialize || command.StartTime == command.EndTime) + initializeProperty.Invoke(drawable, command.StartValue); initialized = true; } using (drawable.BeginAbsoluteSequence(command.StartTime)) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 8c91a9e80a..7e068979bf 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -86,6 +86,7 @@ + From 59d9dc5ee74d7ab2988b7fa50cc516d08807b910 Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 10 Sep 2017 20:08:56 +0200 Subject: [PATCH 14/64] Ignore storyboard sprites with invalid positions. --- osu.Game/Storyboards/Drawables/StoryboardAnimation.cs | 3 +++ osu.Game/Storyboards/Drawables/StoryboardSprite.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs index eb2ba59397..2051b9c4af 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs @@ -49,6 +49,9 @@ namespace osu.Game.Storyboards.Drawables } } + public override bool IsPresent + => !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent; + public StoryboardAnimation(AnimationDefinition definition) { Definition = definition; diff --git a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs index 565b5a5069..ca055fe6d4 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs @@ -49,6 +49,9 @@ namespace osu.Game.Storyboards.Drawables } } + public override bool IsPresent + => !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent; + public StoryboardSprite(SpriteDefinition definition) { Definition = definition; From 9eaa1cb5cdeda76fcb943905baacab808bddffa2 Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 10 Sep 2017 21:25:23 +0200 Subject: [PATCH 15/64] Fix sprites not being visible when all their commands are inside loops. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 2 +- osu.Game/Storyboards/SpriteDefinition.cs | 55 ++++++++++--------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index d538960a37..e436a43989 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -324,7 +324,7 @@ namespace osu.Game.Beatmaps.Formats else { if (depth < 2) - timelineGroup = spriteDefinition; + timelineGroup = spriteDefinition?.TimelineGroup; var commandType = split[0]; switch (commandType) diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/SpriteDefinition.cs index c410fd8807..1e1718a255 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/SpriteDefinition.cs @@ -10,14 +10,26 @@ using System.Linq; namespace osu.Game.Storyboards { - public class SpriteDefinition : CommandTimelineGroup, IElementDefinition + public class SpriteDefinition : IElementDefinition { + private readonly List loops = new List(); + private readonly List triggers = new List(); + public string Path { get; set; } public Anchor Origin; public Vector2 InitialPosition; - private readonly List loops = new List(); - private readonly List triggers = new List(); + public readonly CommandTimelineGroup TimelineGroup = new CommandTimelineGroup(); + + public double StartTime => Math.Min( + TimelineGroup.HasCommands ? TimelineGroup.CommandsStartTime : double.MaxValue, + loops.Any(l => l.HasCommands) ? loops.Where(l => l.HasCommands).Min(l => l.StartTime) : double.MaxValue); + + public double EndTime => Math.Max( + TimelineGroup.HasCommands ? TimelineGroup.CommandsEndTime : double.MinValue, + loops.Any(l => l.HasCommands) ? loops.Where(l => l.HasCommands).Max(l => l.EndTime) : double.MinValue); + + public bool HasCommands => TimelineGroup.HasCommands || loops.Any(l => l.HasCommands); private delegate void DrawablePropertyInitializer(Drawable drawable, T value); private delegate void DrawableTransformer(Drawable drawable, T value, double duration, Easing easing); @@ -46,38 +58,29 @@ namespace osu.Game.Storyboards public virtual Drawable CreateDrawable() => new StoryboardSprite(this); - public override IEnumerable.TypedCommand> GetCommands(CommandTimelineSelector timelineSelector, double offset = 0) - { - var result = base.GetCommands(timelineSelector, offset); - foreach (var loop in loops) - result = result.Concat(loop.GetCommands(timelineSelector, offset)); - return result; - } - public void ApplyTransforms(Drawable drawable, IEnumerable> triggeredGroups = null) { - applyCommands(drawable, triggeredGroups, g => g.X, (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing)); - applyCommands(drawable, triggeredGroups, g => g.Y, (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing)); - applyCommands(drawable, triggeredGroups, g => g.Scale, (d, value) => d.Scale = value, (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); - applyCommands(drawable, triggeredGroups, g => g.Rotation, (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); - applyCommands(drawable, triggeredGroups, g => g.Colour, (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); - applyCommands(drawable, triggeredGroups, g => g.Alpha, (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); - applyCommands(drawable, triggeredGroups, g => g.BlendingMode, (d, value) => d.BlendingMode = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); + applyCommands(drawable, getCommands(g => g.X, triggeredGroups), (d, value) => d.X = value, (d, value, duration, easing) => d.MoveToX(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.Y, triggeredGroups), (d, value) => d.Y = value, (d, value, duration, easing) => d.MoveToY(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.Scale, triggeredGroups), (d, value) => d.Scale = value, (d, value, duration, easing) => d.ScaleTo(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.Rotation, triggeredGroups), (d, value) => d.Rotation = value, (d, value, duration, easing) => d.RotateTo(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.Colour, triggeredGroups), (d, value) => d.Colour = value, (d, value, duration, easing) => d.FadeColour(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.Alpha, triggeredGroups), (d, value) => d.Alpha = value, (d, value, duration, easing) => d.FadeTo(value, duration, easing)); + applyCommands(drawable, getCommands(g => g.BlendingMode, triggeredGroups), (d, value) => d.BlendingMode = value, (d, value, duration, easing) => d.TransformBlendingMode(value, duration), false); var flippable = drawable as IFlippable; if (flippable != null) { - applyCommands(drawable, triggeredGroups, g => g.FlipH, (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); - applyCommands(drawable, triggeredGroups, g => g.FlipV, (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); + applyCommands(drawable, getCommands(g => g.FlipH, triggeredGroups), (d, value) => flippable.FlipH = value, (d, value, duration, easing) => flippable.TransformFlipH(value, duration), false); + applyCommands(drawable, getCommands(g => g.FlipV, triggeredGroups), (d, value) => flippable.FlipV = value, (d, value, duration, easing) => flippable.TransformFlipV(value, duration), false); } } - private void applyCommands(Drawable drawable, IEnumerable> triggeredGroups, - CommandTimelineSelector timelineSelector, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, bool alwaysInitialize = true) + private void applyCommands(Drawable drawable, IEnumerable.TypedCommand> commands, DrawablePropertyInitializer initializeProperty, DrawableTransformer transform, bool alwaysInitialize = true) where T : struct { var initialized = false; - foreach (var command in getAggregatedCommands(timelineSelector, triggeredGroups).OrderBy(l => l)) + foreach (var command in commands.OrderBy(l => l)) { if (!initialized) { @@ -93,9 +96,11 @@ namespace osu.Game.Storyboards } } - private IEnumerable.TypedCommand> getAggregatedCommands(CommandTimelineSelector timelineSelector, IEnumerable> triggeredGroups) + private IEnumerable.TypedCommand> getCommands(CommandTimelineSelector timelineSelector, IEnumerable> triggeredGroups) { - var commands = GetCommands(timelineSelector); + var commands = TimelineGroup.GetCommands(timelineSelector); + foreach (var loop in loops) + commands = commands.Concat(loop.GetCommands(timelineSelector)); if (triggeredGroups != null) foreach (var pair in triggeredGroups) commands = commands.Concat(pair.Item1.GetCommands(timelineSelector, pair.Item2)); From cd15cfc864513228112d7209d526a97f7bbf9bd3 Mon Sep 17 00:00:00 2001 From: Damnae Date: Sun, 10 Sep 2017 22:02:55 +0200 Subject: [PATCH 16/64] Use case insensitive paths to find storyboard textures. --- osu.Game/Storyboards/Drawables/StoryboardAnimation.cs | 5 +++-- osu.Game/Storyboards/Drawables/StoryboardSprite.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs index 2051b9c4af..a28287fd40 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs @@ -69,11 +69,12 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(OsuGameBase game, TextureStore textureStore) { + var basePath = Definition.Path.ToLowerInvariant(); for (var frame = 0; frame < Definition.FrameCount; frame++) { - var framePath = Definition.Path.Replace(".", frame + "."); + var framePath = basePath.Replace(".", frame + "."); - var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename == framePath)?.FileInfo.StoragePath; + var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == framePath)?.FileInfo.StoragePath; if (path == null) continue; diff --git a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs index ca055fe6d4..3b1a431a4a 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/StoryboardSprite.cs @@ -68,8 +68,8 @@ namespace osu.Game.Storyboards.Drawables [BackgroundDependencyLoader] private void load(OsuGameBase game, TextureStore textureStore) { - var spritePath = Definition.Path; - var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename == spritePath)?.FileInfo.StoragePath; + var spritePath = Definition.Path.ToLowerInvariant(); + var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == spritePath)?.FileInfo.StoragePath; if (path == null) return; From 2fb203159f8a32fbc0b487b1268bf3ceeaf9bf9f Mon Sep 17 00:00:00 2001 From: Damnae Date: Mon, 11 Sep 2017 12:33:11 +0200 Subject: [PATCH 17/64] CI fixes. --- osu.Game/Storyboards/Drawables/DrawablesExtensions.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs index 0824ca2ed9..3b21c47b96 100644 --- a/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs +++ b/osu.Game/Storyboards/Drawables/DrawablesExtensions.cs @@ -1,4 +1,7 @@ -using osu.Framework.Graphics; +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Framework.Graphics; using osu.Framework.Graphics.Transforms; namespace osu.Game.Storyboards.Drawables @@ -6,7 +9,7 @@ namespace osu.Game.Storyboards.Drawables public static class DrawablesExtensions { /// - /// Adjusts after a delay. + /// Adjusts after a delay. /// /// A to which further transforms can be added. public static TransformSequence TransformBlendingMode(this T drawable, BlendingMode newValue, double delay = 0) From 58e65397b06b43973c52babef2e520520fc2e94e Mon Sep 17 00:00:00 2001 From: Damnae Date: Tue, 12 Sep 2017 10:13:55 +0200 Subject: [PATCH 18/64] Add support for storyboards using numerical values. --- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index e436a43989..adf366cdea 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -287,8 +287,8 @@ namespace osu.Game.Beatmaps.Formats break; case EventType.Sprite: { - var layer = split[1]; - var origin = (Anchor)Enum.Parse(typeof(Anchor), split[2]); + var layer = parseLayer(split[1]); + var origin = parseOrigin(split[2]); var path = cleanFilename(split[3]); var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); @@ -298,8 +298,8 @@ namespace osu.Game.Beatmaps.Formats break; case EventType.Animation: { - var layer = split[1]; - var origin = (Anchor)Enum.Parse(typeof(Anchor), split[2]); + var layer = parseLayer(split[1]); + var origin = parseOrigin(split[2]); var path = cleanFilename(split[3]); var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); @@ -313,7 +313,7 @@ namespace osu.Game.Beatmaps.Formats case EventType.Sample: { var time = double.Parse(split[1], CultureInfo.InvariantCulture); - var layer = split[2]; + var layer = parseLayer(split[2]); var path = cleanFilename(split[3]); var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100; beatmap.Storyboard.GetLayer(layer).Add(new SampleDefinition(path, time, volume)); @@ -446,6 +446,27 @@ namespace osu.Game.Beatmaps.Formats private static string cleanFilename(string path) => FileSafety.PathStandardise(path.Trim('\"')); + private static Anchor parseOrigin(string value) + { + var origin = (LegacyOrigins)Enum.Parse(typeof(LegacyOrigins), value); + switch (origin) + { + case LegacyOrigins.TopLeft: return Anchor.TopLeft; + case LegacyOrigins.TopCentre: return Anchor.TopCentre; + case LegacyOrigins.TopRight: return Anchor.TopRight; + case LegacyOrigins.CentreLeft: return Anchor.CentreLeft; + case LegacyOrigins.Centre: return Anchor.Centre; + case LegacyOrigins.CentreRight: return Anchor.CentreRight; + case LegacyOrigins.BottomLeft: return Anchor.BottomLeft; + case LegacyOrigins.BottomCentre: return Anchor.BottomCentre; + case LegacyOrigins.BottomRight: return Anchor.BottomRight; + } + throw new InvalidDataException($@"Unknown origin: {value}"); + } + + private static string parseLayer(string value) + => Enum.Parse(typeof(StoryLayer), value).ToString(); + private void handleTimingPoints(Beatmap beatmap, string line) { string[] split = line.Split(','); @@ -683,5 +704,27 @@ namespace osu.Game.Beatmaps.Formats Sample = 5, Animation = 6 } + + internal enum LegacyOrigins + { + TopLeft, + Centre, + CentreLeft, + TopRight, + BottomCentre, + TopCentre, + Custom, + CentreRight, + BottomLeft, + BottomRight + }; + + internal enum StoryLayer + { + Background = 0, + Fail = 1, + Pass = 2, + Foreground = 3 + } } } From 3af8345068f79d36910ea7c5a2a31f4d2b686c53 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 19:39:22 +0900 Subject: [PATCH 19/64] Add AffectsAccuracy to Judgement --- osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs | 1 + .../Judgements/TaikoDrumRollTickJudgement.cs | 1 + osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs | 3 +++ osu.Game/Rulesets/Judgements/Judgement.cs | 2 ++ 4 files changed, 7 insertions(+) diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index c00572edff..132856713a 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Mania.Judgements public class HoldNoteTickJudgement : ManiaJudgement { public override bool AffectsCombo => false; + public override bool AffectsAccuracy => false; protected override int NumericResultFor(HitResult result) => 20; protected override int NumericResultForAccuracy(HitResult result) => 0; // Don't count ticks into accuracy diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 0d61494add..0eb5370840 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoDrumRollTickJudgement : TaikoJudgement { public override bool AffectsCombo => false; + public override bool AffectsAccuracy => false; protected override int NumericResultFor(HitResult result) { diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs index bb67784ab1..2cc4c922e2 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs @@ -7,6 +7,9 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoStrongHitJudgement : TaikoJudgement { + public override bool AffectsCombo => false; + public override bool AffectsAccuracy => false; + public TaikoStrongHitJudgement() { base.Result = HitResult.Perfect; diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 29cd3ff384..40cc643f60 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Judgements /// public double TimeOffset { get; internal set; } + public virtual bool AffectsAccuracy => true; + public virtual bool AffectsCombo => true; /// From c07e831b1739ff0ebad70b6abc086419cd83c0cd Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 19:39:54 +0900 Subject: [PATCH 20/64] Move HasFailed override to base ScoreProcessor --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 2ca733d82a..c64737c875 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -53,7 +53,7 @@ namespace osu.Game.Rulesets.Scoring /// /// Whether the score is in a failed state. /// - public virtual bool HasFailed => false; + public virtual bool HasFailed => Health.Value == Health.MinValue; /// /// Whether this ScoreProcessor has already triggered the failed state. @@ -143,8 +143,6 @@ namespace osu.Game.Rulesets.Scoring /// protected readonly List Judgements = new List(); - public override bool HasFailed => Health.Value == Health.MinValue; - protected ScoreProcessor() { } @@ -156,7 +154,6 @@ namespace osu.Game.Rulesets.Scoring rulesetContainer.OnJudgement += AddJudgement; ComputeTargets(rulesetContainer.Beatmap); - Reset(); } From cba642f781d37bb1de3e097b6544fbd15c3b5f2f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 19:45:07 +0900 Subject: [PATCH 21/64] Reduce nesting, because we don't have partial judgements any more --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 35 +++++++++------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index c64737c875..54466315d6 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -169,31 +169,26 @@ namespace osu.Game.Rulesets.Scoring /// The judgement to add. protected void AddJudgement(Judgement judgement) { - bool exists = Judgements.Contains(judgement); - - if (!exists) + if (judgement.AffectsCombo) { - if (judgement.AffectsCombo) + switch (judgement.Result) { - switch (judgement.Result) - { - case HitResult.None: - break; - case HitResult.Miss: - Combo.Value = 0; - break; - default: - Combo.Value++; - break; - } + case HitResult.None: + break; + case HitResult.Miss: + Combo.Value = 0; + break; + default: + Combo.Value++; + break; } - - Judgements.Add(judgement); - OnNewJudgement(judgement); - - NotifyNewJudgement(judgement); } + Judgements.Add(judgement); + OnNewJudgement(judgement); + + NotifyNewJudgement(judgement); + UpdateFailed(); } From c7677d896a0432a11c3810c09e18761f2b98b843 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 19:47:44 +0900 Subject: [PATCH 22/64] Remove SliderTickJudgement --- osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 3d19d19546..3ccf1cd60c 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -8,10 +8,6 @@ using osu.Game.Rulesets.Objects.Drawables; namespace osu.Game.Rulesets.Osu.Judgements { - public class SliderTickJudgement : OsuJudgement - { - } - public class OsuJudgement : Judgement { /// From 195c2d7a31ffcab7f397ccc63deeb2a5ec519a07 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 19:48:17 +0900 Subject: [PATCH 23/64] Keep track of maximum hits + combo at base ScoreProcessor level --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 54466315d6..7760c6f489 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -143,6 +143,11 @@ namespace osu.Game.Rulesets.Scoring /// protected readonly List Judgements = new List(); + private int maxHits; + private int maxCombo; + + private int hits; + protected ScoreProcessor() { } @@ -154,6 +159,10 @@ namespace osu.Game.Rulesets.Scoring rulesetContainer.OnJudgement += AddJudgement; ComputeTargets(rulesetContainer.Beatmap); + + maxCombo = HighestCombo; + maxHits = hits; + Reset(); } @@ -173,8 +182,6 @@ namespace osu.Game.Rulesets.Scoring { switch (judgement.Result) { - case HitResult.None: - break; case HitResult.Miss: Combo.Value = 0; break; @@ -184,6 +191,9 @@ namespace osu.Game.Rulesets.Scoring } } + if (judgement.AffectsCombo && judgement.IsHit) + hits++; + Judgements.Add(judgement); OnNewJudgement(judgement); From d070fb80639f57ab1ba22ea231935d1b6c976620 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 19:48:35 +0900 Subject: [PATCH 24/64] Actually make DrawableSliderTick return an OsuJudgement now --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index 0938f78843..b088359fbf 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (timeOffset >= 0) - AddJudgement(new SliderTickJudgement { Result = Tracking ? HitResult.Perfect : HitResult.Miss }); + AddJudgement(new OsuJudgement { Result = Tracking ? HitResult.Perfect : HitResult.Miss }); } protected override void UpdatePreemptState() From 0b949394741a647c6379075cb7a43a2dc79799d8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 20:53:26 +0900 Subject: [PATCH 25/64] Make Accuracy = 1, Health = 1 the default for ScoreProcessor --- osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs | 8 -------- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 5 ----- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 3 --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 1 - osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 6 +++--- 5 files changed, 3 insertions(+), 20 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 2637a98fe2..7608be5762 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -19,14 +19,6 @@ namespace osu.Game.Rulesets.Catch.Scoring { } - protected override void Reset() - { - base.Reset(); - - Health.Value = 1; - Accuracy.Value = 1; - } - protected override void OnNewJudgement(Judgement judgement) { } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 946caf71cf..e256e9bd72 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -265,13 +265,8 @@ namespace osu.Game.Rulesets.Mania.Scoring TotalScore.Value = comboScore + accuracyScore + bonusScore; } - protected override void Reset() - { base.Reset(); - Health.Value = 1; - Accuracy.Value = 1; - bonusScore = 0; comboPortion = 0; totalHits = 0; diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 59d4492480..362038baba 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -54,9 +54,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { base.Reset(); - Health.Value = 1; - Accuracy.Value = 1; - scoreResultCounts.Clear(); comboResultCounts.Clear(); } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 6b99b23a12..21d790169c 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -242,7 +242,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring base.Reset(); Health.Value = 0; - Accuracy.Value = 1; bonusScore = 0; comboPortion = 0; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 7760c6f489..2e76f9a135 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Scoring /// /// The current accuracy. /// - public readonly BindableDouble Accuracy = new BindableDouble { MinValue = 0, MaxValue = 1 }; + public readonly BindableDouble Accuracy = new BindableDouble(1) { MinValue = 0, MaxValue = 1 }; /// /// The current health. @@ -88,8 +88,8 @@ namespace osu.Game.Rulesets.Scoring protected virtual void Reset() { TotalScore.Value = 0; - Accuracy.Value = 0; - Health.Value = 0; + Accuracy.Value = 1; + Health.Value = 1; Combo.Value = 0; HighestCombo.Value = 0; From abab2a4878654917f4cf11970e1a3e63e834daed Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 21:05:50 +0900 Subject: [PATCH 26/64] Revamp score processing to once more unify scoring methods --- .../Scoring/CatchScoreProcessor.cs | 1 + .../Scoring/ManiaScoreProcessor.cs | 101 +--------------- .../Scoring/OsuScoreProcessor.cs | 51 +------- .../Judgements/TaikoDrumRollTickJudgement.cs | 5 - .../Judgements/TaikoJudgement.cs | 30 ----- .../Scoring/TaikoScoreProcessor.cs | 112 +----------------- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 61 +++++++--- 7 files changed, 61 insertions(+), 300 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index 7608be5762..cd2a81038a 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -21,6 +21,7 @@ namespace osu.Game.Rulesets.Catch.Scoring protected override void OnNewJudgement(Judgement judgement) { + base.OnNewJudgement(judgement); } } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index e256e9bd72..06ba82205d 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -15,32 +15,6 @@ namespace osu.Game.Rulesets.Mania.Scoring { internal class ManiaScoreProcessor : ScoreProcessor { - /// - /// The maximum score achievable. - /// Does _not_ include bonus score - for bonus score see . - /// - private const int max_score = 1000000; - - /// - /// The amount of the score attributed to combo. - /// - private const double combo_portion_max = max_score * 0.2; - - /// - /// The amount of the score attributed to accuracy. - /// - private const double accuracy_portion_max = max_score * 0.8; - - /// - /// The factor used to determine relevance of combos. - /// - private const double combo_base = 4; - - /// - /// The combo value at which hit objects result in the max score possible. - /// - private const int combo_relevance_cap = 400; - /// /// The hit HP multiplier at OD = 0. /// @@ -116,41 +90,8 @@ namespace osu.Game.Rulesets.Mania.Scoring /// private double hpMultiplier = 1; - /// - /// The cumulative combo portion of the score. - /// - private double comboScore => combo_portion_max * comboPortion / maxComboPortion; - - /// - /// The cumulative accuracy portion of the score. - /// - private double accuracyScore => accuracy_portion_max * Math.Pow(Accuracy, 4) * totalHits / maxTotalHits; - - /// - /// The cumulative bonus score. - /// This is added on top of , thus the total score can exceed . - /// - private double bonusScore; - - /// - /// The achieved by a perfect playthrough. - /// - private double maxComboPortion; - - /// - /// The portion of the score dedicated to combo. - /// - private double comboPortion; - - /// - /// The achieved by a perfect playthrough. - /// - private int maxTotalHits; - - /// - /// The total hits. - /// - private int totalHits; + protected override double ComboPortion => 0.2f; + protected override double AccuracyPortion => 0.8f; public ManiaScoreProcessor() { @@ -199,27 +140,21 @@ namespace osu.Game.Rulesets.Mania.Scoring Reset(); } - - maxTotalHits = totalHits; - maxComboPortion = comboPortion; } protected override void OnNewJudgement(Judgement judgement) { + base.OnNewJudgement(judgement); + bool isTick = judgement is HoldNoteTickJudgement; if (isTick) { if (judgement.IsHit) - { Health.Value += hpMultiplier * hp_increase_tick; - bonusScore += judgement.NumericResult; - } } else { - totalHits++; - switch (judgement.Result) { case HitResult.Miss: @@ -241,35 +176,7 @@ namespace osu.Game.Rulesets.Mania.Scoring Health.Value += hpMultiplier * hp_increase_perfect; break; } - - if (judgement.IsHit) - { - // A factor that is applied to make higher combos more relevant - double comboRelevance = Math.Min(Math.Max(0.5, Math.Log(Combo.Value, combo_base)), Math.Log(combo_relevance_cap, combo_base)); - comboPortion += judgement.NumericResult * comboRelevance; - } } - - int scoreForAccuracy = 0; - int maxScoreForAccuracy = 0; - - foreach (var j in Judgements) - { - var maniaJudgement = (ManiaJudgement)j; - - scoreForAccuracy += maniaJudgement.NumericAccuracyResult; - maxScoreForAccuracy += maniaJudgement.MaxNumericAccuracyResult; - } - - Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy; - TotalScore.Value = comboScore + accuracyScore + bonusScore; - } - - base.Reset(); - - bonusScore = 0; - comboPortion = 0; - totalHits = 0; } } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 362038baba..dcfa0aa28e 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Collections.Generic; using osu.Framework.Configuration; using osu.Framework.Extensions; @@ -20,6 +19,9 @@ namespace osu.Game.Rulesets.Osu.Scoring { public readonly Bindable Mode = new Bindable(ScoringMode.Exponential); + protected override double ComboPortion => 0.7; + protected override double AccuracyPortion => 0.3; + public OsuScoreProcessor() { } @@ -31,17 +33,12 @@ namespace osu.Game.Rulesets.Osu.Scoring private float hpDrainRate; - private int totalAccurateJudgements; - private readonly Dictionary scoreResultCounts = new Dictionary(); private readonly Dictionary comboResultCounts = new Dictionary(); - private double comboMaxScore; - protected override void ComputeTargets(Beatmap beatmap) { hpDrainRate = beatmap.BeatmapInfo.Difficulty.DrainRate; - totalAccurateJudgements = beatmap.HitObjects.Count; foreach (var unused in beatmap.HitObjects) { @@ -70,6 +67,8 @@ namespace osu.Game.Rulesets.Osu.Scoring protected override void OnNewJudgement(Judgement judgement) { + base.OnNewJudgement(judgement); + var osuJudgement = (OsuJudgement)judgement; if (judgement.Result != HitResult.None) @@ -100,46 +99,6 @@ namespace osu.Game.Rulesets.Osu.Scoring Health.Value -= hpDrainRate * 0.04; break; } - - calculateScore(); - } - - private void calculateScore() - { - int baseScore = 0; - double comboScore = 0; - - int baseMaxScore = 0; - - foreach (var j in Judgements) - { - baseScore += j.NumericResult; - baseMaxScore += j.MaxNumericResult; - - comboScore += j.NumericResult * (1 + Combo.Value / 10d); - } - - Accuracy.Value = (double)baseScore / baseMaxScore; - - if (comboScore > comboMaxScore) - comboMaxScore = comboScore; - - if (baseScore == 0) - TotalScore.Value = 0; - else - { - // temporary to make scoring feel more like score v1 without being score v1. - float exponentialFactor = Mode.Value == ScoringMode.Exponential ? (float)Judgements.Count / 100 : 1; - - TotalScore.Value = - (int) - ( - exponentialFactor * - 700000 * comboScore / comboMaxScore + - 300000 * Math.Pow(Accuracy.Value, 10) * ((double)Judgements.Count / totalAccurateJudgements) + - 0 /* bonusScore */ - ); - } } public enum ScoringMode diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index 0eb5370840..bd021a1560 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -20,10 +20,5 @@ namespace osu.Game.Rulesets.Taiko.Judgements return 200; } } - - protected override int NumericResultForAccuracy(HitResult result) - { - return 0; - } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index 9d6b5ca535..a3cc228c20 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -8,19 +8,8 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoJudgement : Judgement { - /// - /// The result value for the accuracy portion of the score. - /// - public int ResultNumericForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(Result); - - /// - /// The maximum result value for the accuracy portion of the score. - /// - public int MaxResultValueForAccuracy => NumericResultForAccuracy(HitResult.Great); - /// /// Computes the numeric result value for the combo portion of the score. - /// For the accuracy portion of the score (including accuracy percentage), see . /// /// The result to compute the value for. /// The numeric result value. @@ -36,24 +25,5 @@ namespace osu.Game.Rulesets.Taiko.Judgements return 300; } } - - /// - /// Computes the numeric result value for the accuracy portion of the score. - /// For the combo portion of the score, see . - /// - /// The result to compute the value for. - /// The numeric result value. - protected virtual int NumericResultForAccuracy(HitResult result) - { - switch (result) - { - default: - return 0; - case HitResult.Good: - return 150; - case HitResult.Great: - return 300; - } - } } } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 21d790169c..18625df508 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -15,27 +15,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring { internal class TaikoScoreProcessor : ScoreProcessor { - /// - /// The maximum score achievable. - /// Does _not_ include bonus score - for bonus score see . - /// - private const int max_score = 1000000; - - /// - /// The amount of the score attributed to combo. - /// - private const double combo_portion_max = max_score * 0.2; - - /// - /// The amount of the score attributed to accuracy. - /// - private const double accuracy_portion_max = max_score * 0.8; - - /// - /// The factor used to determine relevance of combos. - /// - private const double combo_base = 4; - /// /// The HP awarded by a hit. /// @@ -76,40 +55,16 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// /// Taiko fails at the end of the map if the player has not half-filled their HP bar. /// - public override bool HasFailed => totalHits == maxTotalHits && Health.Value <= 0.5; + public override bool HasFailed => Hits == MaxHits && Health.Value <= 0.5; - /// - /// The cumulative combo portion of the score. - /// - private double comboScore => combo_portion_max * comboPortion / maxComboPortion; - - /// - /// The cumulative accuracy portion of the score. - /// - private double accuracyScore => accuracy_portion_max * Math.Pow(Accuracy, 3.6) * totalHits / maxTotalHits; - - /// - /// The cumulative bonus score. - /// This is added on top of , thus the total score can exceed . - /// - private double bonusScore; - - /// - /// The multiple of the original score added to the combo portion of the score - /// for correctly hitting a strong hit object with both keys. - /// - private double strongHitScale; + protected override double ComboPortion => 0.2; + protected override double AccuracyPortion => 0.8; private double hpIncreaseTick; private double hpIncreaseGreat; private double hpIncreaseGood; private double hpIncreaseMiss; - private double maxComboPortion; - private double comboPortion; - private int maxTotalHits; - private int totalHits; - public TaikoScoreProcessor() { } @@ -128,13 +83,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring hpIncreaseGood = hpMultiplierNormal * hp_hit_good; hpIncreaseMiss = BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, hp_miss_min, hp_miss_mid, hp_miss_max); - var strongHits = beatmap.HitObjects.FindAll(o => o is Hit && o.IsStrong); - - // This is a linear function that awards: - // 10 times bonus points for hitting a strong hit object with both keys with 30 strong hit objects in the map - // 3 times bonus points for hitting a strong hit object with both keys with 120 strong hit objects in the map - strongHitScale = -7d / 90d * MathHelper.Clamp(strongHits.Count, 30, 120) + 111d / 9d; - foreach (var obj in beatmap.HitObjects) { if (obj is Hit) @@ -163,46 +111,14 @@ namespace osu.Game.Rulesets.Taiko.Scoring AddJudgement(new TaikoJudgement { Result = HitResult.Great }); } } - - maxTotalHits = totalHits; - maxComboPortion = comboPortion; } protected override void OnNewJudgement(Judgement judgement) { - bool isStrong = judgement is TaikoStrongHitJudgement; + base.OnNewJudgement(judgement); + bool isTick = judgement is TaikoDrumRollTickJudgement; - // Don't consider ticks and strong hits as a type of hit that counts towards map completion - if (!isTick && !isStrong) - totalHits++; - - // Apply score changes - if (judgement.IsHit) - { - double baseValue = judgement.NumericResult; - - if (isStrong) - { - // Add increased score for the previous judgement by hitting a strong hit object with the second key - var prevJudgement = Judgements[Judgements.Count - 1]; - baseValue = prevJudgement.NumericResult * strongHitScale; - - } - - // Add score to portions - if (judgement is TaikoDrumRollTickJudgement) - bonusScore += baseValue; - else - { - // A relevance factor that needs to be applied to make higher combos more relevant - // Value is capped at 400 combo - double comboRelevance = Math.Min(Math.Log(400, combo_base), Math.Max(0.5, Math.Log(Combo.Value, combo_base))); - - comboPortion += baseValue * comboRelevance; - } - } - // Apply HP changes switch (judgement.Result) { @@ -221,20 +137,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring Health.Value += hpIncreaseGreat; break; } - - int scoreForAccuracy = 0; - int maxScoreForAccuracy = 0; - - foreach (var j in Judgements) - { - var taikoJudgement = (TaikoJudgement)j; - - scoreForAccuracy += taikoJudgement.ResultNumericForAccuracy; - maxScoreForAccuracy += taikoJudgement.MaxResultValueForAccuracy; - } - - Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy; - TotalScore.Value = comboScore + accuracyScore + bonusScore; } protected override void Reset() @@ -242,10 +144,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring base.Reset(); Health.Value = 0; - - bonusScore = 0; - comboPortion = 0; - totalHits = 0; } } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 2e76f9a135..213b92486a 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -138,15 +138,21 @@ namespace osu.Game.Rulesets.Scoring public abstract class ScoreProcessor : ScoreProcessor where TObject : HitObject { + private const double max_score = 1000000; + /// /// All judgements held by this ScoreProcessor. /// protected readonly List Judgements = new List(); - private int maxHits; - private int maxCombo; + protected virtual double ComboPortion => 0.5f; + protected virtual double AccuracyPortion => 0.5f; - private int hits; + protected int MaxHits { get; private set; } + protected int Hits { get; private set; } + + private double maxComboScore; + private double comboScore; protected ScoreProcessor() { @@ -160,8 +166,8 @@ namespace osu.Game.Rulesets.Scoring ComputeTargets(rulesetContainer.Beatmap); - maxCombo = HighestCombo; - maxHits = hits; + maxComboScore = comboScore; + MaxHits = Hits; Reset(); } @@ -191,28 +197,53 @@ namespace osu.Game.Rulesets.Scoring } } - if (judgement.AffectsCombo && judgement.IsHit) - hits++; - Judgements.Add(judgement); OnNewJudgement(judgement); - NotifyNewJudgement(judgement); UpdateFailed(); } + protected virtual void OnNewJudgement(Judgement judgement) + { + double bonusScore = 0; + + if (judgement.AffectsCombo) + { + switch (judgement.Result) + { + case HitResult.None: + break; + case HitResult.Miss: + Combo.Value = 0; + break; + default: + Combo.Value++; + break; + } + + comboScore += judgement.NumericResult; + } + else if (judgement.IsHit) + bonusScore += judgement.NumericResult; + + if (judgement.AffectsAccuracy && judgement.IsHit) + Hits++; + + TotalScore.Value = + max_score * (ComboPortion * comboScore / maxComboScore + + AccuracyPortion * Hits / MaxHits) + + bonusScore; + } + protected override void Reset() { base.Reset(); Judgements.Clear(); - } - /// - /// Updates any values that need post-processing. Invoked when a new judgement has occurred. - /// - /// The judgement that triggered this calculation. - protected abstract void OnNewJudgement(Judgement judgement); + Hits = 0; + comboScore = 0; + } } } From 3e3618d7242a4f7f859efe8a1242d593332e067f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 21:12:57 +0900 Subject: [PATCH 27/64] More cleanups --- .../Scoring/CatchScoreProcessor.cs | 6 ------ .../Scoring/ManiaScoreProcessor.cs | 1 - .../Scoring/TaikoScoreProcessor.cs | 2 -- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 15 ++------------- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs index cd2a81038a..11e95622ca 100644 --- a/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs +++ b/osu.Game.Rulesets.Catch/Scoring/CatchScoreProcessor.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using osu.Game.Rulesets.Catch.Objects; -using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; @@ -18,10 +17,5 @@ namespace osu.Game.Rulesets.Catch.Scoring : base(rulesetContainer) { } - - protected override void OnNewJudgement(Judgement judgement) - { - base.OnNewJudgement(judgement); - } } } diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 06ba82205d..92e661203d 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 18625df508..a629dae9fa 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects.Drawables; @@ -9,7 +8,6 @@ using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Taiko.Judgements; using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.UI; -using OpenTK; namespace osu.Game.Rulesets.Taiko.Scoring { diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 213b92486a..43fdd99fa5 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; -using System.Collections.Generic; using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -140,18 +139,13 @@ namespace osu.Game.Rulesets.Scoring { private const double max_score = 1000000; - /// - /// All judgements held by this ScoreProcessor. - /// - protected readonly List Judgements = new List(); - protected virtual double ComboPortion => 0.5f; protected virtual double AccuracyPortion => 0.5f; - protected int MaxHits { get; private set; } + protected readonly int MaxHits; protected int Hits { get; private set; } - private double maxComboScore; + private readonly double maxComboScore; private double comboScore; protected ScoreProcessor() @@ -160,8 +154,6 @@ namespace osu.Game.Rulesets.Scoring protected ScoreProcessor(RulesetContainer rulesetContainer) { - Judgements.Capacity = rulesetContainer.Beatmap.HitObjects.Count; - rulesetContainer.OnJudgement += AddJudgement; ComputeTargets(rulesetContainer.Beatmap); @@ -197,7 +189,6 @@ namespace osu.Game.Rulesets.Scoring } } - Judgements.Add(judgement); OnNewJudgement(judgement); NotifyNewJudgement(judgement); @@ -240,8 +231,6 @@ namespace osu.Game.Rulesets.Scoring { base.Reset(); - Judgements.Clear(); - Hits = 0; comboScore = 0; } From d0774c7bc657090fa60b142680b43dd7478efbac Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 21:16:47 +0900 Subject: [PATCH 28/64] ComputeTargets -> SimulateAutoplay + improve xmldoc --- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 2 +- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 2 +- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 9 +++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 92e661203d..41e2de5f39 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Mania.Scoring { } - protected override void ComputeTargets(Beatmap beatmap) + protected override void SimulateAutoplay(Beatmap beatmap) { BeatmapDifficulty difficulty = beatmap.BeatmapInfo.Difficulty; hpMultiplier = BeatmapDifficulty.DifficultyRange(difficulty.DrainRate, hp_multiplier_min, hp_multiplier_mid, hp_multiplier_max); diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index dcfa0aa28e..84c8c50dd4 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Scoring private readonly Dictionary scoreResultCounts = new Dictionary(); private readonly Dictionary comboResultCounts = new Dictionary(); - protected override void ComputeTargets(Beatmap beatmap) + protected override void SimulateAutoplay(Beatmap beatmap) { hpDrainRate = beatmap.BeatmapInfo.Difficulty.DrainRate; diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index a629dae9fa..7b0bdeea13 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -72,7 +72,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring { } - protected override void ComputeTargets(Beatmap beatmap) + protected override void SimulateAutoplay(Beatmap beatmap) { double hpMultiplierNormal = 1 / (hp_hit_great * beatmap.HitObjects.FindAll(o => o is Hit).Count * BeatmapDifficulty.DifficultyRange(beatmap.BeatmapInfo.Difficulty.DrainRate, 0.5, 0.75, 0.98)); diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 43fdd99fa5..b1859195ef 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -156,7 +156,7 @@ namespace osu.Game.Rulesets.Scoring { rulesetContainer.OnJudgement += AddJudgement; - ComputeTargets(rulesetContainer.Beatmap); + SimulateAutoplay(rulesetContainer.Beatmap); maxComboScore = comboScore; MaxHits = Hits; @@ -165,10 +165,11 @@ namespace osu.Game.Rulesets.Scoring } /// - /// Computes target scoring values for this ScoreProcessor. This is equivalent to performing an auto-play of the score to find the values. + /// Simulates an autoplay of s that will be judged by this + /// by adding s for each in the . /// - /// The Beatmap containing the objects that will be judged by this ScoreProcessor. - protected virtual void ComputeTargets(Beatmap beatmap) { } + /// The containing the s that will be judged by this . + protected virtual void SimulateAutoplay(Beatmap beatmap) { } /// /// Adds a judgement to this ScoreProcessor. From cc6bb81a73dee2bcfa448a634897635694ab10c7 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 21:46:54 +0900 Subject: [PATCH 29/64] Reimplement Exponential scoring with a simpler and more intuitive calculation Default for all rulesets for now. --- .../Scoring/OsuScoreProcessor.cs | 8 ------- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 22 +++++++++++++++---- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 84c8c50dd4..2c941bf13a 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { internal class OsuScoreProcessor : ScoreProcessor { - public readonly Bindable Mode = new Bindable(ScoringMode.Exponential); - protected override double ComboPortion => 0.7; protected override double AccuracyPortion => 0.3; @@ -100,11 +98,5 @@ namespace osu.Game.Rulesets.Osu.Scoring break; } } - - public enum ScoringMode - { - Standardised, - Exponential - } } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b1859195ef..b12f730511 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -139,6 +139,8 @@ namespace osu.Game.Rulesets.Scoring { private const double max_score = 1000000; + public readonly Bindable Mode = new Bindable(ScoringMode.Exponential); + protected virtual double ComboPortion => 0.5f; protected virtual double AccuracyPortion => 0.5f; @@ -222,10 +224,16 @@ namespace osu.Game.Rulesets.Scoring if (judgement.AffectsAccuracy && judgement.IsHit) Hits++; - TotalScore.Value = - max_score * (ComboPortion * comboScore / maxComboScore - + AccuracyPortion * Hits / MaxHits) - + bonusScore; + switch (Mode.Value) + { + case ScoringMode.Standardised: + TotalScore.Value = + max_score * (ComboPortion * comboScore / maxComboScore + AccuracyPortion * Hits / MaxHits) + bonusScore; + break; + case ScoringMode.Exponential: + TotalScore.Value = (comboScore + bonusScore) * Math.Log(HighestCombo + 1, 2); + break; + } } protected override void Reset() @@ -236,4 +244,10 @@ namespace osu.Game.Rulesets.Scoring comboScore = 0; } } + + public enum ScoringMode + { + Standardised, + Exponential + } } From 2e0218f388c14f9083a9afbc6bdb8bee218f9921 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 22:01:08 +0900 Subject: [PATCH 30/64] Move AllObjectsJudged into ScoreProcessor as AllJudged Changes to OsuScoreProcessor were required to make sure that ticks and slider heads weren't ignored. --- .../Scoring/OsuScoreProcessor.cs | 15 ++++++++++++--- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 18 +++++++++++++++++- osu.Game/Rulesets/UI/RulesetContainer.cs | 15 --------------- osu.Game/Screens/Play/Player.cs | 6 ++---- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 2c941bf13a..32cd53f3a2 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -2,7 +2,6 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; -using osu.Framework.Configuration; using osu.Framework.Extensions; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -38,9 +37,19 @@ namespace osu.Game.Rulesets.Osu.Scoring { hpDrainRate = beatmap.BeatmapInfo.Difficulty.DrainRate; - foreach (var unused in beatmap.HitObjects) + foreach (var obj in beatmap.HitObjects) { - // TODO: add support for other object types. + var slider = obj as Slider; + if (slider != null) + { + // Head + AddJudgement(new OsuJudgement { Result = HitResult.Great }); + + // Ticks + foreach (var tick in slider.Ticks) + AddJudgement(new OsuJudgement { Result = HitResult.Great }); + } + AddJudgement(new OsuJudgement { Result = HitResult.Great }); } } diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index b12f730511..be468f84b4 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -14,11 +14,17 @@ namespace osu.Game.Rulesets.Scoring public abstract class ScoreProcessor { /// - /// Invoked when the ScoreProcessor is in a failed state. + /// Invoked when the is in a failed state. + /// This may occur regardless of whether an event is invoked. /// Return true if the fail was permitted. /// public event Func Failed; + /// + /// Invoked when all s have been judged. + /// + public event Action AllJudged; + /// /// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the . /// @@ -49,6 +55,11 @@ namespace osu.Game.Rulesets.Scoring /// public readonly BindableInt HighestCombo = new BindableInt(); + /// + /// Whether all s have been processed. + /// + protected virtual bool HasCompleted => false; + /// /// Whether the score is in a failed state. /// @@ -117,6 +128,9 @@ namespace osu.Game.Rulesets.Scoring protected void NotifyNewJudgement(Judgement judgement) { NewJudgement?.Invoke(judgement); + + if (HasCompleted) + AllJudged?.Invoke(); } /// @@ -141,6 +155,8 @@ namespace osu.Game.Rulesets.Scoring public readonly Bindable Mode = new Bindable(ScoringMode.Exponential); + protected sealed override bool HasCompleted => Hits == MaxHits; + protected virtual double ComboPortion => 0.5f; protected virtual double AccuracyPortion => 0.5f; diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index f7ece531c3..767bb94f8d 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -29,11 +29,6 @@ namespace osu.Game.Rulesets.UI /// public abstract class RulesetContainer : Container { - /// - /// Invoked when all the judgeable HitObjects have been judged. - /// - public event Action OnAllJudged; - /// /// Whether to apply adjustments to the child based on our own size. /// @@ -77,15 +72,6 @@ namespace osu.Game.Rulesets.UI Ruleset = ruleset; } - /// - /// Checks whether all HitObjects have been judged, and invokes OnAllJudged. - /// - protected void CheckAllJudged() - { - if (AllObjectsJudged) - OnAllJudged?.Invoke(); - } - public abstract ScoreProcessor CreateScoreProcessor(); /// @@ -263,7 +249,6 @@ namespace osu.Game.Rulesets.UI { Playfield.OnJudgement(d, j); OnJudgement?.Invoke(j); - CheckAllJudged(); }; drawableObjects.Add(drawableObject); diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 615e04d6c2..593abb7d26 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -206,10 +206,8 @@ namespace osu.Game.Screens.Play hudOverlay.ModDisplay.Current.BindTo(working.Mods); - //bind RulesetContainer to ScoreProcessor and ourselves (for a pass situation) - RulesetContainer.OnAllJudged += onCompletion; - - //bind ScoreProcessor to ourselves (for a fail situation) + // Bind ScoreProcessor to ourselves + scoreProcessor.AllJudged += onCompletion; scoreProcessor.Failed += onFail; } From b5f48c2368091420df894168b68af1311fbef8e0 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 22:27:27 +0900 Subject: [PATCH 31/64] Add storeResults as a parameter to Reset Whether to store the current state of the ScoreProcessor for future use. --- .../Scoring/ManiaScoreProcessor.cs | 12 +++------ .../Scoring/OsuScoreProcessor.cs | 6 ++--- .../Scoring/TaikoScoreProcessor.cs | 4 +-- osu.Game/Rulesets/Judgements/Judgement.cs | 7 +++++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 27 ++++++++++--------- 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 41e2de5f39..ff9dcdc682 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -113,11 +113,7 @@ namespace osu.Game.Rulesets.Mania.Scoring { var holdNote = obj as HoldNote; - if (obj is Note) - { - AddJudgement(new ManiaJudgement { Result = HitResult.Perfect }); - } - else if (holdNote != null) + if (holdNote != null) { // Head AddJudgement(new ManiaJudgement { Result = HitResult.Perfect }); @@ -126,9 +122,9 @@ namespace osu.Game.Rulesets.Mania.Scoring int tickCount = holdNote.Ticks.Count(); for (int i = 0; i < tickCount; i++) AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect }); - - AddJudgement(new HoldNoteTailJudgement { Result = HitResult.Perfect }); } + + AddJudgement(new ManiaJudgement { Result = HitResult.Perfect }); } if (!HasFailed) @@ -137,7 +133,7 @@ namespace osu.Game.Rulesets.Mania.Scoring hpMultiplier *= 1.01; hpMissMultiplier *= 0.98; - Reset(); + Reset(false); } } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 32cd53f3a2..da474dac65 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -46,7 +46,7 @@ namespace osu.Game.Rulesets.Osu.Scoring AddJudgement(new OsuJudgement { Result = HitResult.Great }); // Ticks - foreach (var tick in slider.Ticks) + foreach (var unused in slider.Ticks) AddJudgement(new OsuJudgement { Result = HitResult.Great }); } @@ -54,9 +54,9 @@ namespace osu.Game.Rulesets.Osu.Scoring } } - protected override void Reset() + protected override void Reset(bool storeResults) { - base.Reset(); + base.Reset(storeResults); scoreResultCounts.Clear(); comboResultCounts.Clear(); diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 7b0bdeea13..f31cd2d634 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -137,9 +137,9 @@ namespace osu.Game.Rulesets.Taiko.Scoring } } - protected override void Reset() + protected override void Reset(bool storeResults) { - base.Reset(); + base.Reset(storeResults); Health.Value = 0; } diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 40cc643f60..71743b9988 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -25,8 +25,15 @@ namespace osu.Game.Rulesets.Judgements /// public double TimeOffset { get; internal set; } + /// + /// Whether the should be considered as a factor in the accuracy percentage and portion. + /// public virtual bool AffectsAccuracy => true; + /// + /// Whether the should affect the combo portion of the score. + /// If false, the will be considered for the bonus portion of the score. + /// public virtual bool AffectsCombo => true; /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index be468f84b4..9f46d7da8f 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -73,8 +73,6 @@ namespace osu.Game.Rulesets.Scoring protected ScoreProcessor() { Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); }; - - Reset(); } private ScoreRank rankFrom(double acc) @@ -95,7 +93,8 @@ namespace osu.Game.Rulesets.Scoring /// /// Resets this ScoreProcessor to a default state. /// - protected virtual void Reset() + /// Whether to store the current state of the for future use. + protected virtual void Reset(bool storeResults) { TotalScore.Value = 0; Accuracy.Value = 1; @@ -160,10 +159,11 @@ namespace osu.Game.Rulesets.Scoring protected virtual double ComboPortion => 0.5f; protected virtual double AccuracyPortion => 0.5f; - protected readonly int MaxHits; + protected int MaxHits { get; private set; } protected int Hits { get; private set; } - private readonly double maxComboScore; + private double maxHighestCombo; + private double maxComboScore; private double comboScore; protected ScoreProcessor() @@ -175,11 +175,7 @@ namespace osu.Game.Rulesets.Scoring rulesetContainer.OnJudgement += AddJudgement; SimulateAutoplay(rulesetContainer.Beatmap); - - maxComboScore = comboScore; - MaxHits = Hits; - - Reset(); + Reset(true); } /// @@ -252,9 +248,16 @@ namespace osu.Game.Rulesets.Scoring } } - protected override void Reset() + protected override void Reset(bool storeResults) { - base.Reset(); + if (storeResults) + { + maxHighestCombo = HighestCombo; + maxComboScore = comboScore; + MaxHits = Hits; + } + + base.Reset(storeResults); Hits = 0; comboScore = 0; From dc9b47559af46d5480fcf1a069da5978a51209c0 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 22:28:10 +0900 Subject: [PATCH 32/64] Multiply standardised combos by the HighestCombo to make higher combos matter more --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 9f46d7da8f..4b11435e23 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -240,7 +240,10 @@ namespace osu.Game.Rulesets.Scoring { case ScoringMode.Standardised: TotalScore.Value = - max_score * (ComboPortion * comboScore / maxComboScore + AccuracyPortion * Hits / MaxHits) + bonusScore; + max_score * + (ComboPortion * (comboScore * Math.Log(HighestCombo + 1, 2)) / (maxComboScore * Math.Log(maxHighestCombo + 1, 2)) + + AccuracyPortion * Hits / MaxHits) + + bonusScore; break; case ScoringMode.Exponential: TotalScore.Value = (comboScore + bonusScore) * Math.Log(HighestCombo + 1, 2); From 89cb38386c6414478f08522411f6bf4bb03d6d7f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 22:28:16 +0900 Subject: [PATCH 33/64] Set accuracy --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 4b11435e23..412f778f7b 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -249,6 +249,8 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = (comboScore + bonusScore) * Math.Log(HighestCombo + 1, 2); break; } + + Accuracy.Value = (double)Hits / MaxHits; } protected override void Reset(bool storeResults) From 4269533babfe1384f1a08da28d938a8c01029bbb Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 22:29:44 +0900 Subject: [PATCH 34/64] Remove remaining AllObjectsJudged in RulesetContainer --- osu.Game/Rulesets/UI/RulesetContainer.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 767bb94f8d..207ae647b9 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -56,11 +56,6 @@ namespace osu.Game.Rulesets.UI public abstract IEnumerable Objects { get; } - /// - /// Whether all the HitObjects have been judged. - /// - protected abstract bool AllObjectsJudged { get; } - protected readonly Ruleset Ruleset; /// @@ -138,8 +133,6 @@ namespace osu.Game.Rulesets.UI public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor; - protected override bool AllObjectsJudged => drawableObjects.All(h => h.AllJudged); - /// /// The playfield. /// @@ -148,8 +141,6 @@ namespace osu.Game.Rulesets.UI protected override Container Content => content; private Container content; - private readonly List> drawableObjects = new List>(); - /// /// Whether to assume the beatmap passed into this is for the current ruleset. /// Creates a hit renderer for a beatmap. @@ -236,8 +227,6 @@ namespace osu.Game.Rulesets.UI /// private void loadObjects() { - drawableObjects.Capacity = Beatmap.HitObjects.Count; - foreach (TObject h in Beatmap.HitObjects) { var drawableObject = GetVisualRepresentation(h); @@ -251,8 +240,6 @@ namespace osu.Game.Rulesets.UI OnJudgement?.Invoke(j); }; - drawableObjects.Add(drawableObject); - Playfield.Add(drawableObject); } Playfield.PostProcess(); From 756d7527dafbf41b350b45934e298d8c890421da Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 22:33:39 +0900 Subject: [PATCH 35/64] Remove NumericAccuracyResult from ManiaJudgement --- .../Judgements/HoldNoteTailJudgement.cs | 12 -------- .../Judgements/HoldNoteTickJudgement.cs | 1 - .../Judgements/ManiaJudgement.cs | 29 ------------------- 3 files changed, 42 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs index cc7aa63f7e..a8d1b079eb 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTailJudgement.cs @@ -23,17 +23,5 @@ namespace osu.Game.Rulesets.Mania.Judgements return base.NumericResultFor(HasBroken ? HitResult.Good : result); } } - - protected override int NumericResultForAccuracy(HitResult result) - { - switch (result) - { - default: - return base.NumericResultForAccuracy(result); - case HitResult.Great: - case HitResult.Perfect: - return base.NumericResultForAccuracy(HasBroken ? HitResult.Good : result); - } - } } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 132856713a..46e6f0feec 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -11,6 +11,5 @@ namespace osu.Game.Rulesets.Mania.Judgements public override bool AffectsAccuracy => false; protected override int NumericResultFor(HitResult result) => 20; - protected override int NumericResultForAccuracy(HitResult result) => 0; // Don't count ticks into accuracy } } \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs index e36146aa71..1f3b352da4 100644 --- a/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/ManiaJudgement.cs @@ -8,11 +8,6 @@ namespace osu.Game.Rulesets.Mania.Judgements { public class ManiaJudgement : Judgement { - /// - /// The maximum result value for the accuracy portion of the score. - /// - public int MaxNumericAccuracyResult => NumericResultForAccuracy(HitResult.Perfect); - protected override int NumericResultFor(HitResult result) { switch (result) @@ -30,29 +25,5 @@ namespace osu.Game.Rulesets.Mania.Judgements return 300; } } - - public int NumericAccuracyResult => NumericResultForAccuracy(Result); - - /// - /// The result value for the accuracy portion of the score. - /// - protected virtual int NumericResultForAccuracy(HitResult result) - { - switch (result) - { - default: - return 0; - case HitResult.Meh: - return 50; - case HitResult.Ok: - return 100; - case HitResult.Good: - return 200; - case HitResult.Great: - return 300; - case HitResult.Perfect: - return 305; - } - } } } From ba4f81d022ebff3836f5594d97b2715dfaa6175d Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 23:30:15 +0900 Subject: [PATCH 36/64] Woops, fix incorrectly deleted line --- osu.Game/Rulesets/UI/RulesetContainer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index 207ae647b9..cff3365788 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -240,6 +240,7 @@ namespace osu.Game.Rulesets.UI OnJudgement?.Invoke(j); }; + Playfield.Add(drawableObject); } Playfield.PostProcess(); From 12641edb4dbbfa0cbb4b6aa6a3808f472a68f751 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 23:36:51 +0900 Subject: [PATCH 37/64] Fix incorrect mania hold note tick judgements --- .../Objects/Drawables/DrawableHoldNoteTick.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs index 49bca6d1d7..324f4e4e99 100644 --- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs +++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteTick.cs @@ -78,8 +78,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables } } - protected ManiaJudgement CreateJudgement() => new HoldNoteTickJudgement(); - protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (!userTriggered) @@ -91,7 +89,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables if (HoldStartTime?.Invoke() > HitObject.StartTime) return; - AddJudgement(new ManiaJudgement { Result = HitResult.Perfect }); + AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect }); } protected override void UpdateState(ArmedState state) From 7dd79f5a0beebd0995f53ebc8fc35618bc131977 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Tue, 12 Sep 2017 23:42:58 +0900 Subject: [PATCH 38/64] Fix incorrect accuracy calculation --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 412f778f7b..ed0b0bfdd0 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -162,6 +162,9 @@ namespace osu.Game.Rulesets.Scoring protected int MaxHits { get; private set; } protected int Hits { get; private set; } + private int maxAccurateHits; + private int accurateHits; + private double maxHighestCombo; private double maxComboScore; private double comboScore; @@ -233,8 +236,12 @@ namespace osu.Game.Rulesets.Scoring else if (judgement.IsHit) bonusScore += judgement.NumericResult; - if (judgement.AffectsAccuracy && judgement.IsHit) + if (judgement.AffectsAccuracy) + { Hits++; + if (judgement.IsHit) + accurateHits++; + } switch (Mode.Value) { @@ -242,7 +249,7 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = max_score * (ComboPortion * (comboScore * Math.Log(HighestCombo + 1, 2)) / (maxComboScore * Math.Log(maxHighestCombo + 1, 2)) - + AccuracyPortion * Hits / MaxHits) + + AccuracyPortion * accurateHits / maxAccurateHits) + bonusScore; break; case ScoringMode.Exponential: @@ -250,21 +257,23 @@ namespace osu.Game.Rulesets.Scoring break; } - Accuracy.Value = (double)Hits / MaxHits; + Accuracy.Value = (double)accurateHits / Hits; } protected override void Reset(bool storeResults) { if (storeResults) { + MaxHits = Hits; + maxAccurateHits = accurateHits; maxHighestCombo = HighestCombo; maxComboScore = comboScore; - MaxHits = Hits; } base.Reset(storeResults); Hits = 0; + accurateHits = 0; comboScore = 0; } } From 2a45451308b67be0c44d1b470b5b5971aced8433 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 00:19:17 +0900 Subject: [PATCH 39/64] Fix combo duplication. --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ed0b0bfdd0..2f8459b527 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -194,19 +194,6 @@ namespace osu.Game.Rulesets.Scoring /// The judgement to add. protected void AddJudgement(Judgement judgement) { - if (judgement.AffectsCombo) - { - switch (judgement.Result) - { - case HitResult.Miss: - Combo.Value = 0; - break; - default: - Combo.Value++; - break; - } - } - OnNewJudgement(judgement); NotifyNewJudgement(judgement); From 7b44ad300fc7d34500b26330d508eb019e8f9166 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 00:33:01 +0900 Subject: [PATCH 40/64] Remove accurateHits, make Accuracy once again tied to comboScore --- .../Judgements/OsuJudgement.cs | 2 ++ .../Judgements/TaikoJudgement.cs | 2 ++ osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 18 ++++++------------ 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs index 3ccf1cd60c..28b6a04376 100644 --- a/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs +++ b/osu.Game.Rulesets.Osu/Judgements/OsuJudgement.cs @@ -10,6 +10,8 @@ namespace osu.Game.Rulesets.Osu.Judgements { public class OsuJudgement : Judgement { + public override HitResult MaxResult => HitResult.Great; + /// /// The positional hit offset. /// diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs index a3cc228c20..3cd134f3f7 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoJudgement.cs @@ -8,6 +8,8 @@ namespace osu.Game.Rulesets.Taiko.Judgements { public class TaikoJudgement : Judgement { + public override HitResult MaxResult => HitResult.Great; + /// /// Computes the numeric result value for the combo portion of the score. /// diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 2f8459b527..5d31ee9729 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -162,11 +162,9 @@ namespace osu.Game.Rulesets.Scoring protected int MaxHits { get; private set; } protected int Hits { get; private set; } - private int maxAccurateHits; - private int accurateHits; - private double maxHighestCombo; private double maxComboScore; + private double rollingMaxComboScore; private double comboScore; protected ScoreProcessor() @@ -219,16 +217,15 @@ namespace osu.Game.Rulesets.Scoring } comboScore += judgement.NumericResult; + rollingMaxComboScore += judgement.MaxNumericResult; } else if (judgement.IsHit) bonusScore += judgement.NumericResult; if (judgement.AffectsAccuracy) - { Hits++; - if (judgement.IsHit) - accurateHits++; - } + + Accuracy.Value = comboScore / rollingMaxComboScore; switch (Mode.Value) { @@ -236,15 +233,13 @@ namespace osu.Game.Rulesets.Scoring TotalScore.Value = max_score * (ComboPortion * (comboScore * Math.Log(HighestCombo + 1, 2)) / (maxComboScore * Math.Log(maxHighestCombo + 1, 2)) - + AccuracyPortion * accurateHits / maxAccurateHits) + + AccuracyPortion * Accuracy) + bonusScore; break; case ScoringMode.Exponential: TotalScore.Value = (comboScore + bonusScore) * Math.Log(HighestCombo + 1, 2); break; } - - Accuracy.Value = (double)accurateHits / Hits; } protected override void Reset(bool storeResults) @@ -252,7 +247,6 @@ namespace osu.Game.Rulesets.Scoring if (storeResults) { MaxHits = Hits; - maxAccurateHits = accurateHits; maxHighestCombo = HighestCombo; maxComboScore = comboScore; } @@ -260,8 +254,8 @@ namespace osu.Game.Rulesets.Scoring base.Reset(storeResults); Hits = 0; - accurateHits = 0; comboScore = 0; + rollingMaxComboScore = 0; } } From 3386dbb243425e1ee02bf42acf6bf6e03f5495b5 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 00:37:18 +0900 Subject: [PATCH 41/64] Fix incorrect HitResult for slider ticks. --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs index b088359fbf..53b3427fc4 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSliderTick.cs @@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables protected override void CheckForJudgements(bool userTriggered, double timeOffset) { if (timeOffset >= 0) - AddJudgement(new OsuJudgement { Result = Tracking ? HitResult.Perfect : HitResult.Miss }); + AddJudgement(new OsuJudgement { Result = Tracking ? HitResult.Great : HitResult.Miss }); } protected override void UpdatePreemptState() From 3619f7c1ebc926f9b59fc79607aa46cb2c980106 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 00:38:52 +0900 Subject: [PATCH 42/64] Fix possible NaN accuracy --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 5d31ee9729..448cb56e0c 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -225,7 +225,8 @@ namespace osu.Game.Rulesets.Scoring if (judgement.AffectsAccuracy) Hits++; - Accuracy.Value = comboScore / rollingMaxComboScore; + if (rollingMaxComboScore != 0) + Accuracy.Value = comboScore / rollingMaxComboScore; switch (Mode.Value) { From 7b30fc8a09470611d7d60f17873ae4eae1f5b940 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 00:43:30 +0900 Subject: [PATCH 43/64] Fix osu! slider initial circles being placed at the wrong depth. --- osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 7cb06df679..8cef7de948 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Scale = s.Scale, ComboColour = s.ComboColour, Samples = s.Samples, - }), + }) { Depth = 0 }, }; components.Add(body); From c78695cfe099eeba646df22f9b22eb6440238f86 Mon Sep 17 00:00:00 2001 From: MrTheMake Date: Tue, 12 Sep 2017 18:26:52 +0200 Subject: [PATCH 44/64] Removed redundant call --- osu.Game/Overlays/ChatOverlay.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index af5c6d9916..c682724d35 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -181,7 +181,6 @@ namespace osu.Game.Overlays { chatContainer.ResizeHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint); channelSelectionContainer.ResizeHeightTo(channel_selection_min_height, 800, Easing.OutQuint); - channelSelection.Show(); chatHeight.Value = 1f - channel_selection_min_height; } } From 9839a3b937e17dbe041b5acc878b0f84d8713eeb Mon Sep 17 00:00:00 2001 From: MrTheMake Date: Tue, 12 Sep 2017 18:47:21 +0200 Subject: [PATCH 45/64] Smoothly transform the chat height when opening the channel selection --- osu.Game/Overlays/ChatOverlay.cs | 45 ++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/osu.Game/Overlays/ChatOverlay.cs b/osu.Game/Overlays/ChatOverlay.cs index c682724d35..7c28bdea4d 100644 --- a/osu.Game/Overlays/ChatOverlay.cs +++ b/osu.Game/Overlays/ChatOverlay.cs @@ -12,8 +12,10 @@ using osu.Framework.Configuration; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; +using osu.Framework.Graphics.Transforms; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; +using osu.Framework.MathUtils; using osu.Framework.Threading; using osu.Game.Configuration; using osu.Game.Graphics; @@ -56,7 +58,7 @@ namespace osu.Game.Overlays private readonly Box chatBackground; private readonly Box tabBackground; - private Bindable chatHeight; + public Bindable ChatHeight { get; internal set; } private readonly Container channelSelectionContainer; private readonly ChannelSelectionOverlay channelSelection; @@ -177,17 +179,11 @@ namespace osu.Game.Overlays if (state == Visibility.Visible) { textbox.HoldFocus = false; - if (1f - chatHeight.Value < channel_selection_min_height) - { - chatContainer.ResizeHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint); - channelSelectionContainer.ResizeHeightTo(channel_selection_min_height, 800, Easing.OutQuint); - chatHeight.Value = 1f - channel_selection_min_height; - } + if (1f - ChatHeight.Value < channel_selection_min_height) + transformChatHeightTo(1f - channel_selection_min_height, 800, Easing.OutQuint); } else - { textbox.HoldFocus = true; - } }; } @@ -201,7 +197,7 @@ namespace osu.Game.Overlays if (!isDragging) return base.OnDragStart(state); - startDragChatHeight = chatHeight.Value; + startDragChatHeight = ChatHeight.Value; return true; } @@ -217,7 +213,7 @@ namespace osu.Game.Overlays if (channelSelection.State == Visibility.Visible && targetChatHeight > 1f - channel_selection_min_height) targetChatHeight = 1f - channel_selection_min_height; - chatHeight.Value = targetChatHeight; + ChatHeight.Value = targetChatHeight; } return true; @@ -277,14 +273,14 @@ namespace osu.Game.Overlays this.api = api; api.Register(this); - chatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); - chatHeight.ValueChanged += h => + ChatHeight = config.GetBindable(OsuSetting.ChatDisplayHeight); + ChatHeight.ValueChanged += h => { chatContainer.Height = (float)h; channelSelectionContainer.Height = 1f - (float)h; tabBackground.FadeTo(h == 1 ? 1 : 0.8f, 200); }; - chatHeight.TriggerChange(); + ChatHeight.TriggerChange(); chatBackground.Colour = colours.ChatBlue; } @@ -506,5 +502,26 @@ namespace osu.Game.Overlays api.Queue(req); } + + private void transformChatHeightTo(double newChatHeight, double duration = 0, Easing easing = Easing.None) + { + this.TransformTo(this.PopulateTransform(new TransformChatHeight(), newChatHeight, duration, easing)); + } + + private class TransformChatHeight : Transform + { + private double valueAt(double time) + { + if (time < StartTime) return StartValue; + if (time >= EndTime) return EndValue; + + return Interpolation.ValueAt(time, StartValue, EndValue, StartTime, EndTime, Easing); + } + + public override string TargetMember => "ChatHeight.Value"; + + protected override void Apply(ChatOverlay d, double time) => d.ChatHeight.Value = valueAt(time); + protected override void ReadIntoStartValue(ChatOverlay d) => StartValue = d.ChatHeight.Value; + } } } From ba3e44cd71f6e6a7d1f5600537ed8b74299ccf90 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 15:17:32 +0900 Subject: [PATCH 46/64] Simplify standardized scoring to BasePortion (raw scoring) + ComboPortion (highest combo) --- .../Scoring/ManiaScoreProcessor.cs | 4 +-- .../Scoring/OsuScoreProcessor.cs | 2 +- .../Scoring/TaikoScoreProcessor.cs | 2 +- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 31 +++++++++---------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index ff9dcdc682..857616ad9a 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -89,8 +89,8 @@ namespace osu.Game.Rulesets.Mania.Scoring /// private double hpMultiplier = 1; - protected override double ComboPortion => 0.2f; - protected override double AccuracyPortion => 0.8f; + protected override double BasePortion => 0.8; + protected override double ComboPortion => 0.2; public ManiaScoreProcessor() { diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index da474dac65..3d30293d4b 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -16,8 +16,8 @@ namespace osu.Game.Rulesets.Osu.Scoring { internal class OsuScoreProcessor : ScoreProcessor { + protected override double BasePortion => 0.3; protected override double ComboPortion => 0.7; - protected override double AccuracyPortion => 0.3; public OsuScoreProcessor() { diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index f31cd2d634..31e3c435b4 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -55,8 +55,8 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// public override bool HasFailed => Hits == MaxHits && Health.Value <= 0.5; + protected override double BasePortion => 0.8; protected override double ComboPortion => 0.2; - protected override double AccuracyPortion => 0.8; private double hpIncreaseTick; private double hpIncreaseGreat; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 448cb56e0c..a0b24c52df 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -156,16 +156,17 @@ namespace osu.Game.Rulesets.Scoring protected sealed override bool HasCompleted => Hits == MaxHits; + protected virtual double BasePortion => 0.5f; protected virtual double ComboPortion => 0.5f; - protected virtual double AccuracyPortion => 0.5f; protected int MaxHits { get; private set; } protected int Hits { get; private set; } private double maxHighestCombo; - private double maxComboScore; - private double rollingMaxComboScore; - private double comboScore; + + private double maxBaseScore; + private double rollingMaxBaseScore; + private double baseScore; protected ScoreProcessor() { @@ -216,8 +217,8 @@ namespace osu.Game.Rulesets.Scoring break; } - comboScore += judgement.NumericResult; - rollingMaxComboScore += judgement.MaxNumericResult; + baseScore += judgement.NumericResult; + rollingMaxBaseScore += judgement.MaxNumericResult; } else if (judgement.IsHit) bonusScore += judgement.NumericResult; @@ -225,20 +226,16 @@ namespace osu.Game.Rulesets.Scoring if (judgement.AffectsAccuracy) Hits++; - if (rollingMaxComboScore != 0) - Accuracy.Value = comboScore / rollingMaxComboScore; + if (rollingMaxBaseScore != 0) + Accuracy.Value = baseScore / rollingMaxBaseScore; switch (Mode.Value) { case ScoringMode.Standardised: - TotalScore.Value = - max_score * - (ComboPortion * (comboScore * Math.Log(HighestCombo + 1, 2)) / (maxComboScore * Math.Log(maxHighestCombo + 1, 2)) - + AccuracyPortion * Accuracy) - + bonusScore; + TotalScore.Value = max_score * (BasePortion * baseScore / maxBaseScore + ComboPortion * HighestCombo / maxHighestCombo) + bonusScore; break; case ScoringMode.Exponential: - TotalScore.Value = (comboScore + bonusScore) * Math.Log(HighestCombo + 1, 2); + TotalScore.Value = (baseScore + bonusScore) * Math.Log(HighestCombo + 1, 2); break; } } @@ -249,14 +246,14 @@ namespace osu.Game.Rulesets.Scoring { MaxHits = Hits; maxHighestCombo = HighestCombo; - maxComboScore = comboScore; + maxBaseScore = baseScore; } base.Reset(storeResults); Hits = 0; - comboScore = 0; - rollingMaxComboScore = 0; + baseScore = 0; + rollingMaxBaseScore = 0; } } From 7681d97f1002506b39722404d4bb880da9533661 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Sep 2017 15:20:49 +0900 Subject: [PATCH 47/64] Fix typo in user profile header Replays watched, not replay watched. --- osu.Game/Overlays/Profile/ProfileHeader.cs | 4 ++-- osu.Game/Users/UserStatistics.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Profile/ProfileHeader.cs b/osu.Game/Overlays/Profile/ProfileHeader.cs index 77a3449b9c..d6a86fe714 100644 --- a/osu.Game/Overlays/Profile/ProfileHeader.cs +++ b/osu.Game/Overlays/Profile/ProfileHeader.cs @@ -414,8 +414,8 @@ namespace osu.Game.Overlays.Profile scoreNumberText.Add(createScoreNumberText(user.Statistics.TotalHits.ToString(@"#,0"))); scoreText.Add(createScoreText("Max Combo")); scoreNumberText.Add(createScoreNumberText(user.Statistics.MaxCombo.ToString(@"#,0"))); - scoreText.Add(createScoreText("Replay Watched by Others")); - scoreNumberText.Add(createScoreNumberText(user.Statistics.ReplayWatched.ToString(@"#,0"))); + scoreText.Add(createScoreText("Replays Watched by Others")); + scoreNumberText.Add(createScoreNumberText(user.Statistics.ReplaysWatched.ToString(@"#,0"))); gradeSS.DisplayCount = user.Statistics.GradesCount.SS; gradeSS.Show(); diff --git a/osu.Game/Users/UserStatistics.cs b/osu.Game/Users/UserStatistics.cs index 05f3d65f30..15b57553a6 100644 --- a/osu.Game/Users/UserStatistics.cs +++ b/osu.Game/Users/UserStatistics.cs @@ -44,7 +44,7 @@ namespace osu.Game.Users public int MaxCombo; [JsonProperty(@"replays_watched_by_others")] - public int ReplayWatched; + public int ReplaysWatched; [JsonProperty(@"grade_counts")] public Grades GradesCount; From 05ac23f99a880f034949f88aecb5060cc16b8ccc Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 15:42:47 +0900 Subject: [PATCH 48/64] Remove AffectsAccuracy for now --- .../Judgements/HoldNoteTickJudgement.cs | 1 - .../Judgements/TaikoDrumRollTickJudgement.cs | 1 - .../Judgements/TaikoStrongHitJudgement.cs | 1 - osu.Game/Rulesets/Judgements/Judgement.cs | 5 ----- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 7 +++---- 5 files changed, 3 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs index 46e6f0feec..d326c6fc0a 100644 --- a/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs +++ b/osu.Game.Rulesets.Mania/Judgements/HoldNoteTickJudgement.cs @@ -8,7 +8,6 @@ namespace osu.Game.Rulesets.Mania.Judgements public class HoldNoteTickJudgement : ManiaJudgement { public override bool AffectsCombo => false; - public override bool AffectsAccuracy => false; protected override int NumericResultFor(HitResult result) => 20; } diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs index bd021a1560..c9daef8c99 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoDrumRollTickJudgement.cs @@ -8,7 +8,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoDrumRollTickJudgement : TaikoJudgement { public override bool AffectsCombo => false; - public override bool AffectsAccuracy => false; protected override int NumericResultFor(HitResult result) { diff --git a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs index 2cc4c922e2..f0b57e5c09 100644 --- a/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs +++ b/osu.Game.Rulesets.Taiko/Judgements/TaikoStrongHitJudgement.cs @@ -8,7 +8,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements public class TaikoStrongHitJudgement : TaikoJudgement { public override bool AffectsCombo => false; - public override bool AffectsAccuracy => false; public TaikoStrongHitJudgement() { diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs index 71743b9988..0ae33272a7 100644 --- a/osu.Game/Rulesets/Judgements/Judgement.cs +++ b/osu.Game/Rulesets/Judgements/Judgement.cs @@ -25,11 +25,6 @@ namespace osu.Game.Rulesets.Judgements /// public double TimeOffset { get; internal set; } - /// - /// Whether the should be considered as a factor in the accuracy percentage and portion. - /// - public virtual bool AffectsAccuracy => true; - /// /// Whether the should affect the combo portion of the score. /// If false, the will be considered for the bonus portion of the score. diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a0b24c52df..7f3d5e2501 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -152,7 +152,7 @@ namespace osu.Game.Rulesets.Scoring { private const double max_score = 1000000; - public readonly Bindable Mode = new Bindable(ScoringMode.Exponential); + public readonly Bindable Mode = new Bindable(ScoringMode.Standardised); protected sealed override bool HasCompleted => Hits == MaxHits; @@ -219,13 +219,12 @@ namespace osu.Game.Rulesets.Scoring baseScore += judgement.NumericResult; rollingMaxBaseScore += judgement.MaxNumericResult; + + Hits++; } else if (judgement.IsHit) bonusScore += judgement.NumericResult; - if (judgement.AffectsAccuracy) - Hits++; - if (rollingMaxBaseScore != 0) Accuracy.Value = baseScore / rollingMaxBaseScore; From d83a2d4dc6e7084bff7a337af6d0adc3836fc1db Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 15:56:49 +0900 Subject: [PATCH 49/64] Disable masking optimisations for scrolling hit objects Lifetime is very tightly controlled here, so all should be okay. --- .../Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs | 1 + osu.Game/Rulesets/Timing/ScrollingContainer.cs | 1 + osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs index 5ba9c2ff4d..538bb826ad 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableScrollingHitObject.cs @@ -31,6 +31,7 @@ namespace osu.Game.Rulesets.Objects.Drawables } public override bool RemoveWhenNotAlive => false; + protected override bool RequiresChildrenUpdate => true; protected DrawableScrollingHitObject(TObject hitObject) : base(hitObject) diff --git a/osu.Game/Rulesets/Timing/ScrollingContainer.cs b/osu.Game/Rulesets/Timing/ScrollingContainer.cs index 6e77c49e3d..eac596297a 100644 --- a/osu.Game/Rulesets/Timing/ScrollingContainer.cs +++ b/osu.Game/Rulesets/Timing/ScrollingContainer.cs @@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Timing internal Axes ScrollingAxes; public override bool RemoveWhenNotAlive => false; + protected override bool RequiresChildrenUpdate => true; /// /// The control point that defines the speed adjustments for this container. This is set by the . diff --git a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs index d3bd7685da..81e3a5c70e 100644 --- a/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs +++ b/osu.Game/Rulesets/Timing/SpeedAdjustmentContainer.cs @@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Timing } public override bool RemoveWhenNotAlive => false; + protected override bool RequiresChildrenUpdate => true; /// /// The that defines the speed adjustments. From e472518e4f9892c26f1335e2c95b14c30869ef65 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 15:58:50 +0900 Subject: [PATCH 50/64] Standardized is default for now --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index 7f3d5e2501..ced1a5d06b 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -152,7 +152,7 @@ namespace osu.Game.Rulesets.Scoring { private const double max_score = 1000000; - public readonly Bindable Mode = new Bindable(ScoringMode.Standardised); + public readonly Bindable Mode = new Bindable(); protected sealed override bool HasCompleted => Hits == MaxHits; From e146bcacf1119534c23a63bf941bae72fc2be33f Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 16:13:27 +0900 Subject: [PATCH 51/64] Make BasePortion and ComboPortion constants --- osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs | 3 --- osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs | 3 --- osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs | 3 --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 10 ++++++---- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs index 857616ad9a..a200ba31e2 100644 --- a/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs +++ b/osu.Game.Rulesets.Mania/Scoring/ManiaScoreProcessor.cs @@ -89,9 +89,6 @@ namespace osu.Game.Rulesets.Mania.Scoring /// private double hpMultiplier = 1; - protected override double BasePortion => 0.8; - protected override double ComboPortion => 0.2; - public ManiaScoreProcessor() { } diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs index 3d30293d4b..d299faaae2 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuScoreProcessor.cs @@ -16,9 +16,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { internal class OsuScoreProcessor : ScoreProcessor { - protected override double BasePortion => 0.3; - protected override double ComboPortion => 0.7; - public OsuScoreProcessor() { } diff --git a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs index 31e3c435b4..abdda9676f 100644 --- a/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs +++ b/osu.Game.Rulesets.Taiko/Scoring/TaikoScoreProcessor.cs @@ -55,9 +55,6 @@ namespace osu.Game.Rulesets.Taiko.Scoring /// public override bool HasFailed => Hits == MaxHits && Health.Value <= 0.5; - protected override double BasePortion => 0.8; - protected override double ComboPortion => 0.2; - private double hpIncreaseTick; private double hpIncreaseGreat; private double hpIncreaseGood; diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index ced1a5d06b..a40a7c2849 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Diagnostics; using osu.Framework.Configuration; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; @@ -150,15 +151,14 @@ namespace osu.Game.Rulesets.Scoring public abstract class ScoreProcessor : ScoreProcessor where TObject : HitObject { + private const double base_portion = 0.3; + private const double combo_portion = 0.7; private const double max_score = 1000000; public readonly Bindable Mode = new Bindable(); protected sealed override bool HasCompleted => Hits == MaxHits; - protected virtual double BasePortion => 0.5f; - protected virtual double ComboPortion => 0.5f; - protected int MaxHits { get; private set; } protected int Hits { get; private set; } @@ -174,6 +174,8 @@ namespace osu.Game.Rulesets.Scoring protected ScoreProcessor(RulesetContainer rulesetContainer) { + Debug.Assert(base_portion + combo_portion == 1.0); + rulesetContainer.OnJudgement += AddJudgement; SimulateAutoplay(rulesetContainer.Beatmap); @@ -231,7 +233,7 @@ namespace osu.Game.Rulesets.Scoring switch (Mode.Value) { case ScoringMode.Standardised: - TotalScore.Value = max_score * (BasePortion * baseScore / maxBaseScore + ComboPortion * HighestCombo / maxHighestCombo) + bonusScore; + TotalScore.Value = max_score * (base_portion * baseScore / maxBaseScore + combo_portion * HighestCombo / maxHighestCombo) + bonusScore; break; case ScoringMode.Exponential: TotalScore.Value = (baseScore + bonusScore) * Math.Log(HighestCombo + 1, 2); From 6682c3a73696300925b50296eb68acb39ad79ca8 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 16:15:11 +0900 Subject: [PATCH 52/64] Override instead of re-binding event --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index 0dac3ec41c..d946b45372 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -49,10 +49,9 @@ namespace osu.Game.Rulesets.Catch.UI var fruit = (DrawableFruit)h; fruit.CheckPosition = catcherArea.CheckIfWeCanCatch; - fruit.OnJudgement += Fruit_OnJudgement; } - private void Fruit_OnJudgement(DrawableHitObject judgedObject, Judgement judgement) + public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) { if (judgement.IsHit) { From 093d82ac45c245da6ab6b0b39eed292eb9d4a027 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 16:17:01 +0900 Subject: [PATCH 53/64] Set depths from playfield add methods instead of DrawableHitObject --- osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs | 2 ++ osu.Game.Rulesets.Mania/UI/Column.cs | 2 ++ osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs | 2 +- osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs | 2 ++ osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs | 2 ++ osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs | 2 -- 6 files changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs index d946b45372..2b6f9bbf5a 100644 --- a/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs +++ b/osu.Game.Rulesets.Catch/UI/CatchPlayfield.cs @@ -45,6 +45,8 @@ namespace osu.Game.Rulesets.Catch.UI public override void Add(DrawableHitObject h) { + h.Depth = (float)h.HitObject.StartTime; + base.Add(h); var fruit = (DrawableFruit)h; diff --git a/osu.Game.Rulesets.Mania/UI/Column.cs b/osu.Game.Rulesets.Mania/UI/Column.cs index 1133c9f2ee..2d553f8639 100644 --- a/osu.Game.Rulesets.Mania/UI/Column.cs +++ b/osu.Game.Rulesets.Mania/UI/Column.cs @@ -203,6 +203,8 @@ namespace osu.Game.Rulesets.Mania.UI /// The DrawableHitObject to add. public override void Add(DrawableHitObject hitObject) { + hitObject.Depth = (float)hitObject.HitObject.StartTime; + hitObject.AccentColour = AccentColour; HitObjects.Add(hitObject); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs index 8cef7de948..c5155d1e10 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs @@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables Scale = s.Scale, ComboColour = s.ComboColour, Samples = s.Samples, - }) { Depth = 0 }, + }) }; components.Add(body); diff --git a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs index 17f4f9f541..1bb4e8493b 100644 --- a/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs +++ b/osu.Game.Rulesets.Osu/UI/OsuPlayfield.cs @@ -70,6 +70,8 @@ namespace osu.Game.Rulesets.Osu.UI public override void Add(DrawableHitObject h) { + h.Depth = (float)h.HitObject.StartTime; + var c = h as IDrawableHitObjectWithProxiedApproach; if (c != null) approachCircles.Add(c.ProxiedLayer.CreateProxy()); diff --git a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs index 2dd06f7179..d9a216bbfc 100644 --- a/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs +++ b/osu.Game.Rulesets.Taiko/UI/TaikoPlayfield.cs @@ -205,6 +205,8 @@ namespace osu.Game.Rulesets.Taiko.UI public override void Add(DrawableHitObject h) { + h.Depth = (float)h.HitObject.StartTime; + base.Add(h); var barline = h as DrawableBarLine; diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 7cf098c3fa..7a26a53c2a 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -55,8 +55,6 @@ namespace osu.Game.Rulesets.Objects.Drawables : base(hitObject) { HitObject = hitObject; - - Depth = (float)hitObject.StartTime; } private ArmedState state; From f1130eb899dda8d1d8e15f680aed9773485501dd Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 16:35:13 +0900 Subject: [PATCH 54/64] Add default implementation for ScoreProcessor using Exponential scoring --- osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 13 +++++++++++-- osu.Game/Rulesets/UI/RulesetContainer.cs | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs index a40a7c2849..deb87e92d8 100644 --- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs +++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs @@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Scoring } } - public abstract class ScoreProcessor : ScoreProcessor + public class ScoreProcessor : ScoreProcessor where TObject : HitObject { private const double base_portion = 0.3; @@ -172,7 +172,7 @@ namespace osu.Game.Rulesets.Scoring { } - protected ScoreProcessor(RulesetContainer rulesetContainer) + public ScoreProcessor(RulesetContainer rulesetContainer) { Debug.Assert(base_portion + combo_portion == 1.0); @@ -180,11 +180,20 @@ namespace osu.Game.Rulesets.Scoring SimulateAutoplay(rulesetContainer.Beatmap); Reset(true); + + if (maxBaseScore == 0 || maxHighestCombo == 0) + { + Mode.Value = ScoringMode.Exponential; + Mode.Disabled = true; + } } /// /// Simulates an autoplay of s that will be judged by this /// by adding s for each in the . + /// + /// This is required for to work, otherwise will be used. + /// /// /// The containing the s that will be judged by this . protected virtual void SimulateAutoplay(Beatmap beatmap) { } diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs index cff3365788..86ab9a0199 100644 --- a/osu.Game/Rulesets/UI/RulesetContainer.cs +++ b/osu.Game/Rulesets/UI/RulesetContainer.cs @@ -133,6 +133,8 @@ namespace osu.Game.Rulesets.UI public sealed override bool ProvidingUserCursor => !HasReplayLoaded && Playfield.ProvidingUserCursor; + public override ScoreProcessor CreateScoreProcessor() => new ScoreProcessor(this); + /// /// The playfield. /// From 5e32d95ad2dbebaed81841593ec7d9384b9efd42 Mon Sep 17 00:00:00 2001 From: smoogipooo Date: Wed, 13 Sep 2017 16:37:05 +0900 Subject: [PATCH 55/64] Remove Ruleset's CreateScoreProcessor method --- osu.Game.Rulesets.Catch/CatchRuleset.cs | 4 ---- osu.Game.Rulesets.Mania/ManiaRuleset.cs | 4 ---- osu.Game.Rulesets.Osu/OsuRuleset.cs | 4 ---- osu.Game.Rulesets.Taiko/TaikoRuleset.cs | 4 ---- osu.Game/Beatmaps/DummyWorkingBeatmap.cs | 6 ------ osu.Game/Rulesets/Ruleset.cs | 3 --- 6 files changed, 25 deletions(-) diff --git a/osu.Game.Rulesets.Catch/CatchRuleset.cs b/osu.Game.Rulesets.Catch/CatchRuleset.cs index 214cbc7f50..1a9b034cf2 100644 --- a/osu.Game.Rulesets.Catch/CatchRuleset.cs +++ b/osu.Game.Rulesets.Catch/CatchRuleset.cs @@ -9,8 +9,6 @@ using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.UI; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Game.Rulesets.Catch.Scoring; -using osu.Game.Rulesets.Scoring; using osu.Framework.Input.Bindings; namespace osu.Game.Rulesets.Catch @@ -99,8 +97,6 @@ namespace osu.Game.Rulesets.Catch public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap); - public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(); - public override int LegacyID => 2; public CatchRuleset(RulesetInfo rulesetInfo) diff --git a/osu.Game.Rulesets.Mania/ManiaRuleset.cs b/osu.Game.Rulesets.Mania/ManiaRuleset.cs index 0011d2837f..c0996cadf9 100644 --- a/osu.Game.Rulesets.Mania/ManiaRuleset.cs +++ b/osu.Game.Rulesets.Mania/ManiaRuleset.cs @@ -10,8 +10,6 @@ using System.Collections.Generic; using osu.Framework.Graphics; using osu.Framework.Input.Bindings; using osu.Game.Graphics; -using osu.Game.Rulesets.Mania.Scoring; -using osu.Game.Rulesets.Scoring; namespace osu.Game.Rulesets.Mania { @@ -111,8 +109,6 @@ namespace osu.Game.Rulesets.Mania public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap); - public override ScoreProcessor CreateScoreProcessor() => new ManiaScoreProcessor(); - public override int LegacyID => 3; public ManiaRuleset(RulesetInfo rulesetInfo) diff --git a/osu.Game.Rulesets.Osu/OsuRuleset.cs b/osu.Game.Rulesets.Osu/OsuRuleset.cs index c943518b0b..7650a91d7a 100644 --- a/osu.Game.Rulesets.Osu/OsuRuleset.cs +++ b/osu.Game.Rulesets.Osu/OsuRuleset.cs @@ -12,8 +12,6 @@ using osu.Game.Rulesets.UI; using System.Collections.Generic; using System.Linq; using osu.Framework.Graphics; -using osu.Game.Rulesets.Osu.Scoring; -using osu.Game.Rulesets.Scoring; using osu.Game.Overlays.Settings; using osu.Framework.Input.Bindings; @@ -118,8 +116,6 @@ namespace osu.Game.Rulesets.Osu public override string Description => "osu!"; - public override ScoreProcessor CreateScoreProcessor() => new OsuScoreProcessor(); - public override SettingsSubsection CreateSettings() => new OsuSettings(); public override int LegacyID => 0; diff --git a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs index 7b1452766e..ea0f0eae1a 100644 --- a/osu.Game.Rulesets.Taiko/TaikoRuleset.cs +++ b/osu.Game.Rulesets.Taiko/TaikoRuleset.cs @@ -9,8 +9,6 @@ using osu.Game.Rulesets.Taiko.UI; using osu.Game.Rulesets.UI; using System.Collections.Generic; using osu.Framework.Graphics; -using osu.Game.Rulesets.Scoring; -using osu.Game.Rulesets.Taiko.Scoring; using osu.Framework.Input.Bindings; namespace osu.Game.Rulesets.Taiko @@ -101,8 +99,6 @@ namespace osu.Game.Rulesets.Taiko public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap); - public override ScoreProcessor CreateScoreProcessor() => new TaikoScoreProcessor(); - public override int LegacyID => 1; public TaikoRuleset(RulesetInfo rulesetInfo) diff --git a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs index ad0b110e48..d8cd58d939 100644 --- a/osu.Game/Beatmaps/DummyWorkingBeatmap.cs +++ b/osu.Game/Beatmaps/DummyWorkingBeatmap.cs @@ -7,7 +7,6 @@ using osu.Framework.Audio.Track; using osu.Framework.Graphics.Textures; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; namespace osu.Game.Beatmaps @@ -62,11 +61,6 @@ namespace osu.Game.Beatmaps public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => null; - public override ScoreProcessor CreateScoreProcessor() - { - throw new NotImplementedException(); - } - public override string Description => "dummy"; public DummyRuleset(RulesetInfo rulesetInfo) diff --git a/osu.Game/Rulesets/Ruleset.cs b/osu.Game/Rulesets/Ruleset.cs index 33621662af..587c2fc659 100644 --- a/osu.Game/Rulesets/Ruleset.cs +++ b/osu.Game/Rulesets/Ruleset.cs @@ -10,7 +10,6 @@ using osu.Game.Beatmaps; using osu.Game.Graphics; using osu.Game.Overlays.Settings; using osu.Game.Rulesets.Mods; -using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.UI; namespace osu.Game.Rulesets @@ -50,8 +49,6 @@ namespace osu.Game.Rulesets public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap); - public abstract ScoreProcessor CreateScoreProcessor(); - public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_question_circle }; public abstract string Description { get; } From bab3ef0669de179351956504e7096d85e5a18900 Mon Sep 17 00:00:00 2001 From: Damnae Date: Wed, 13 Sep 2017 11:22:24 +0200 Subject: [PATCH 56/64] Rename storyboard classes. --- .../Visual/TestCaseStoryboard.cs | 6 ++-- osu.Game/Beatmaps/Beatmap.cs | 2 +- osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs | 24 ++++++------- .../{Storyboard.cs => DrawableStoryboard.cs} | 14 ++++---- ...tion.cs => DrawableStoryboardAnimation.cs} | 32 ++++++++--------- ...ardLayer.cs => DrawableStoryboardLayer.cs} | 12 +++---- ...dSprite.cs => DrawableStoryboardSprite.cs} | 26 +++++++------- ...entDefinition.cs => IStoryboardElement.cs} | 2 +- osu.Game/Storyboards/Storyboard.cs | 35 +++++++++++++++++++ ...onDefinition.cs => StoryboardAnimation.cs} | 6 ++-- osu.Game/Storyboards/StoryboardDefinition.cs | 35 ------------------- ...{LayerDefinition.cs => StoryboardLayer.cs} | 14 ++++---- ...ampleDefinition.cs => StoryboardSample.cs} | 4 +-- ...priteDefinition.cs => StoryboardSprite.cs} | 6 ++-- osu.Game/osu.Game.csproj | 20 +++++------ 15 files changed, 119 insertions(+), 119 deletions(-) rename osu.Game/Storyboards/Drawables/{Storyboard.cs => DrawableStoryboard.cs} (74%) rename osu.Game/Storyboards/Drawables/{StoryboardAnimation.cs => DrawableStoryboardAnimation.cs} (67%) rename osu.Game/Storyboards/Drawables/{StoryboardLayer.cs => DrawableStoryboardLayer.cs} (69%) rename osu.Game/Storyboards/Drawables/{StoryboardSprite.cs => DrawableStoryboardSprite.cs} (71%) rename osu.Game/Storyboards/{IElementDefinition.cs => IStoryboardElement.cs} (84%) create mode 100644 osu.Game/Storyboards/Storyboard.cs rename osu.Game/Storyboards/{AnimationDefinition.cs => StoryboardAnimation.cs} (79%) delete mode 100644 osu.Game/Storyboards/StoryboardDefinition.cs rename osu.Game/Storyboards/{LayerDefinition.cs => StoryboardLayer.cs} (55%) rename osu.Game/Storyboards/{SampleDefinition.cs => StoryboardSample.cs} (77%) rename osu.Game/Storyboards/{SpriteDefinition.cs => StoryboardSprite.cs} (95%) diff --git a/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs index 10dd706f62..878198e8d2 100644 --- a/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs +++ b/osu.Desktop.Tests/Visual/TestCaseStoryboard.cs @@ -21,8 +21,8 @@ namespace osu.Desktop.Tests.Visual private readonly Bindable beatmapBacking = new Bindable(); - private readonly Container storyboardContainer; - private Storyboard storyboard; + private readonly Container storyboardContainer; + private DrawableStoryboard storyboard; public TestCaseStoryboard() { @@ -38,7 +38,7 @@ namespace osu.Desktop.Tests.Visual RelativeSizeAxes = Axes.Both, Colour = Color4.Black, }, - storyboardContainer = new Container + storyboardContainer = new Container { RelativeSizeAxes = Axes.Both, }, diff --git a/osu.Game/Beatmaps/Beatmap.cs b/osu.Game/Beatmaps/Beatmap.cs index a28f7832b7..458c2304f2 100644 --- a/osu.Game/Beatmaps/Beatmap.cs +++ b/osu.Game/Beatmaps/Beatmap.cs @@ -44,7 +44,7 @@ namespace osu.Game.Beatmaps /// /// The Beatmap's Storyboard. /// - public StoryboardDefinition Storyboard = new StoryboardDefinition(); + public Storyboard Storyboard = new Storyboard(); /// /// Constructs a new beatmap. diff --git a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs index adf366cdea..21fee0f465 100644 --- a/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/OsuLegacyDecoder.cs @@ -242,7 +242,7 @@ namespace osu.Game.Beatmaps.Formats } } - private void handleEvents(Beatmap beatmap, string line, ref SpriteDefinition spriteDefinition, ref CommandTimelineGroup timelineGroup) + private void handleEvents(Beatmap beatmap, string line, ref StoryboardSprite storyboardSprite, ref CommandTimelineGroup timelineGroup) { var depth = 0; while (line.StartsWith(" ") || line.StartsWith("_")) @@ -257,7 +257,7 @@ namespace osu.Game.Beatmaps.Formats if (depth == 0) { - spriteDefinition = null; + storyboardSprite = null; EventType type; if (!Enum.TryParse(split[0], out type)) @@ -292,8 +292,8 @@ namespace osu.Game.Beatmaps.Formats var path = cleanFilename(split[3]); var x = float.Parse(split[4], NumberFormatInfo.InvariantInfo); var y = float.Parse(split[5], NumberFormatInfo.InvariantInfo); - spriteDefinition = new SpriteDefinition(path, origin, new Vector2(x, y)); - beatmap.Storyboard.GetLayer(layer).Add(spriteDefinition); + storyboardSprite = new StoryboardSprite(path, origin, new Vector2(x, y)); + beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite); } break; case EventType.Animation: @@ -306,8 +306,8 @@ namespace osu.Game.Beatmaps.Formats var frameCount = int.Parse(split[6]); var frameDelay = double.Parse(split[7], NumberFormatInfo.InvariantInfo); var loopType = split.Length > 8 ? (AnimationLoopType)Enum.Parse(typeof(AnimationLoopType), split[8]) : AnimationLoopType.LoopForever; - spriteDefinition = new AnimationDefinition(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); - beatmap.Storyboard.GetLayer(layer).Add(spriteDefinition); + storyboardSprite = new StoryboardAnimation(path, origin, new Vector2(x, y), frameCount, frameDelay, loopType); + beatmap.Storyboard.GetLayer(layer).Add(storyboardSprite); } break; case EventType.Sample: @@ -316,7 +316,7 @@ namespace osu.Game.Beatmaps.Formats var layer = parseLayer(split[2]); var path = cleanFilename(split[3]); var volume = split.Length > 4 ? float.Parse(split[4], CultureInfo.InvariantCulture) : 100; - beatmap.Storyboard.GetLayer(layer).Add(new SampleDefinition(path, time, volume)); + beatmap.Storyboard.GetLayer(layer).Add(new StoryboardSample(path, time, volume)); } break; } @@ -324,7 +324,7 @@ namespace osu.Game.Beatmaps.Formats else { if (depth < 2) - timelineGroup = spriteDefinition?.TimelineGroup; + timelineGroup = storyboardSprite?.TimelineGroup; var commandType = split[0]; switch (commandType) @@ -335,14 +335,14 @@ namespace osu.Game.Beatmaps.Formats var startTime = split.Length > 2 ? double.Parse(split[2], CultureInfo.InvariantCulture) : double.MinValue; var endTime = split.Length > 3 ? double.Parse(split[3], CultureInfo.InvariantCulture) : double.MaxValue; var groupNumber = split.Length > 4 ? int.Parse(split[4]) : 0; - timelineGroup = spriteDefinition?.AddTrigger(triggerName, startTime, endTime, groupNumber); + timelineGroup = storyboardSprite?.AddTrigger(triggerName, startTime, endTime, groupNumber); } break; case "L": { var startTime = double.Parse(split[1], CultureInfo.InvariantCulture); var loopCount = int.Parse(split[2]); - timelineGroup = spriteDefinition?.AddLoop(startTime, loopCount); + timelineGroup = storyboardSprite?.AddLoop(startTime, loopCount); } break; default: @@ -607,7 +607,7 @@ namespace osu.Game.Beatmaps.Formats Section section = Section.None; bool hasCustomColours = false; - SpriteDefinition spriteDefinition = null; + StoryboardSprite storyboardSprite = null; CommandTimelineGroup timelineGroup = null; string line; @@ -647,7 +647,7 @@ namespace osu.Game.Beatmaps.Formats handleDifficulty(beatmap, line); break; case Section.Events: - handleEvents(beatmap, line, ref spriteDefinition, ref timelineGroup); + handleEvents(beatmap, line, ref storyboardSprite, ref timelineGroup); break; case Section.TimingPoints: handleTimingPoints(beatmap, line); diff --git a/osu.Game/Storyboards/Drawables/Storyboard.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs similarity index 74% rename from osu.Game/Storyboards/Drawables/Storyboard.cs rename to osu.Game/Storyboards/Drawables/DrawableStoryboard.cs index 45aa063f79..f88e5d118f 100644 --- a/osu.Game/Storyboards/Drawables/Storyboard.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboard.cs @@ -10,9 +10,9 @@ using osu.Game.IO; namespace osu.Game.Storyboards.Drawables { - public class Storyboard : Container + public class DrawableStoryboard : Container { - public StoryboardDefinition Definition { get; private set; } + public Storyboard Storyboard { get; private set; } protected override Vector2 DrawScale => new Vector2(Parent.DrawHeight / 480); public override bool HandleInput => false; @@ -33,9 +33,9 @@ namespace osu.Game.Storyboards.Drawables protected override IReadOnlyDependencyContainer CreateLocalDependencies(IReadOnlyDependencyContainer parent) => dependencies = new DependencyContainer(base.CreateLocalDependencies(parent)); - public Storyboard(StoryboardDefinition definition) + public DrawableStoryboard(Storyboard storyboard) { - Definition = definition; + Storyboard = storyboard; Size = new Vector2(640, 480); Anchor = Anchor.Centre; Origin = Anchor.Centre; @@ -46,14 +46,14 @@ namespace osu.Game.Storyboards.Drawables { dependencies.Cache(new TextureStore(new RawTextureLoaderStore(fileStore.Store), false) { ScaleAdjust = 1, }); - foreach (var layerDefinition in Definition.Layers) - Add(layerDefinition.CreateDrawable()); + foreach (var layer in Storyboard.Layers) + Add(layer.CreateDrawable()); } private void updateLayerVisibility() { foreach (var layer in Children) - layer.Enabled = passing ? layer.Definition.EnabledWhenPassing : layer.Definition.EnabledWhenFailing; + layer.Enabled = passing ? layer.Layer.EnabledWhenPassing : layer.Layer.EnabledWhenFailing; } } } diff --git a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs similarity index 67% rename from osu.Game/Storyboards/Drawables/StoryboardAnimation.cs rename to osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs index a28287fd40..d8b7d05ee9 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardAnimation.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardAnimation.cs @@ -10,12 +10,12 @@ using System.Linq; namespace osu.Game.Storyboards.Drawables { - public class StoryboardAnimation : TextureAnimation, IFlippable + public class DrawableStoryboardAnimation : TextureAnimation, IFlippable { - public AnimationDefinition Definition { get; private set; } + public StoryboardAnimation Animation { get; private set; } - protected override bool ShouldBeAlive => Definition.HasCommands && base.ShouldBeAlive; - public override bool RemoveWhenNotAlive => !Definition.HasCommands || base.RemoveWhenNotAlive; + protected override bool ShouldBeAlive => Animation.HasCommands && base.ShouldBeAlive; + public override bool RemoveWhenNotAlive => !Animation.HasCommands || base.RemoveWhenNotAlive; public bool FlipH { get; set; } public bool FlipV { get; set; } @@ -52,25 +52,25 @@ namespace osu.Game.Storyboards.Drawables public override bool IsPresent => !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent; - public StoryboardAnimation(AnimationDefinition definition) + public DrawableStoryboardAnimation(StoryboardAnimation animation) { - Definition = definition; - Origin = definition.Origin; - Position = definition.InitialPosition; - Repeat = definition.LoopType == AnimationLoopType.LoopForever; + Animation = animation; + Origin = animation.Origin; + Position = animation.InitialPosition; + Repeat = animation.LoopType == AnimationLoopType.LoopForever; - if (definition.HasCommands) + if (animation.HasCommands) { - LifetimeStart = definition.StartTime; - LifetimeEnd = definition.EndTime; + LifetimeStart = animation.StartTime; + LifetimeEnd = animation.EndTime; } } [BackgroundDependencyLoader] private void load(OsuGameBase game, TextureStore textureStore) { - var basePath = Definition.Path.ToLowerInvariant(); - for (var frame = 0; frame < Definition.FrameCount; frame++) + var basePath = Animation.Path.ToLowerInvariant(); + for (var frame = 0; frame < Animation.FrameCount; frame++) { var framePath = basePath.Replace(".", frame + "."); @@ -79,9 +79,9 @@ namespace osu.Game.Storyboards.Drawables continue; var texture = textureStore.Get(path); - AddFrame(texture, Definition.FrameDelay); + AddFrame(texture, Animation.FrameDelay); } - Definition.ApplyTransforms(this); + Animation.ApplyTransforms(this); } } } diff --git a/osu.Game/Storyboards/Drawables/StoryboardLayer.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs similarity index 69% rename from osu.Game/Storyboards/Drawables/StoryboardLayer.cs rename to osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs index 48532e0418..2b5db5b6fa 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardLayer.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardLayer.cs @@ -7,26 +7,26 @@ using osu.Framework.Graphics.Containers; namespace osu.Game.Storyboards.Drawables { - public class StoryboardLayer : Container + public class DrawableStoryboardLayer : Container { - public LayerDefinition Definition { get; private set; } + public StoryboardLayer Layer { get; private set; } public bool Enabled; public override bool IsPresent => Enabled && base.IsPresent; - public StoryboardLayer(LayerDefinition definition) + public DrawableStoryboardLayer(StoryboardLayer layer) { - Definition = definition; + Layer = layer; RelativeSizeAxes = Axes.Both; Anchor = Anchor.Centre; Origin = Anchor.Centre; - Enabled = definition.EnabledWhenPassing; + Enabled = layer.EnabledWhenPassing; } [BackgroundDependencyLoader] private void load() { - foreach (var element in Definition.Elements) + foreach (var element in Layer.Elements) { var drawable = element.CreateDrawable(); if (drawable != null) diff --git a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs similarity index 71% rename from osu.Game/Storyboards/Drawables/StoryboardSprite.cs rename to osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs index 3b1a431a4a..4b491fa008 100644 --- a/osu.Game/Storyboards/Drawables/StoryboardSprite.cs +++ b/osu.Game/Storyboards/Drawables/DrawableStoryboardSprite.cs @@ -10,12 +10,12 @@ using System.Linq; namespace osu.Game.Storyboards.Drawables { - public class StoryboardSprite : Sprite, IFlippable + public class DrawableStoryboardSprite : Sprite, IFlippable { - public SpriteDefinition Definition { get; private set; } + public StoryboardSprite Sprite { get; private set; } - protected override bool ShouldBeAlive => Definition.HasCommands && base.ShouldBeAlive; - public override bool RemoveWhenNotAlive => !Definition.HasCommands || base.RemoveWhenNotAlive; + protected override bool ShouldBeAlive => Sprite.HasCommands && base.ShouldBeAlive; + public override bool RemoveWhenNotAlive => !Sprite.HasCommands || base.RemoveWhenNotAlive; public bool FlipH { get; set; } public bool FlipV { get; set; } @@ -52,29 +52,29 @@ namespace osu.Game.Storyboards.Drawables public override bool IsPresent => !float.IsNaN(DrawPosition.X) && !float.IsNaN(DrawPosition.Y) && base.IsPresent; - public StoryboardSprite(SpriteDefinition definition) + public DrawableStoryboardSprite(StoryboardSprite sprite) { - Definition = definition; - Origin = definition.Origin; - Position = definition.InitialPosition; + Sprite = sprite; + Origin = sprite.Origin; + Position = sprite.InitialPosition; - if (definition.HasCommands) + if (sprite.HasCommands) { - LifetimeStart = definition.StartTime; - LifetimeEnd = definition.EndTime; + LifetimeStart = sprite.StartTime; + LifetimeEnd = sprite.EndTime; } } [BackgroundDependencyLoader] private void load(OsuGameBase game, TextureStore textureStore) { - var spritePath = Definition.Path.ToLowerInvariant(); + var spritePath = Sprite.Path.ToLowerInvariant(); var path = game.Beatmap.Value.BeatmapSetInfo.Files.FirstOrDefault(f => f.Filename.ToLowerInvariant() == spritePath)?.FileInfo.StoragePath; if (path == null) return; Texture = textureStore.Get(path); - Definition.ApplyTransforms(this); + Sprite.ApplyTransforms(this); } } } diff --git a/osu.Game/Storyboards/IElementDefinition.cs b/osu.Game/Storyboards/IStoryboardElement.cs similarity index 84% rename from osu.Game/Storyboards/IElementDefinition.cs rename to osu.Game/Storyboards/IStoryboardElement.cs index 93c9a473f7..d5fc86b0f7 100644 --- a/osu.Game/Storyboards/IElementDefinition.cs +++ b/osu.Game/Storyboards/IStoryboardElement.cs @@ -5,7 +5,7 @@ using osu.Framework.Graphics; namespace osu.Game.Storyboards { - public interface IElementDefinition + public interface IStoryboardElement { string Path { get; } Drawable CreateDrawable(); diff --git a/osu.Game/Storyboards/Storyboard.cs b/osu.Game/Storyboards/Storyboard.cs new file mode 100644 index 0000000000..111cdd5d41 --- /dev/null +++ b/osu.Game/Storyboards/Storyboard.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2007-2017 ppy Pty Ltd . +// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE + +using osu.Game.Storyboards.Drawables; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Storyboards +{ + public class Storyboard + { + private readonly Dictionary layers = new Dictionary(); + public IEnumerable Layers => layers.Values; + + public Storyboard() + { + layers.Add("Background", new StoryboardLayer("Background", 3)); + layers.Add("Fail", new StoryboardLayer("Fail", 2) { EnabledWhenPassing = false, }); + layers.Add("Pass", new StoryboardLayer("Pass", 1) { EnabledWhenFailing = false, }); + layers.Add("Foreground", new StoryboardLayer("Foreground", 0)); + } + + public StoryboardLayer GetLayer(string name) + { + StoryboardLayer layer; + if (!layers.TryGetValue(name, out layer)) + layers[name] = layer = new StoryboardLayer(name, layers.Values.Min(l => l.Depth) - 1); + + return layer; + } + + public DrawableStoryboard CreateDrawable() + => new DrawableStoryboard(this); + } +} diff --git a/osu.Game/Storyboards/AnimationDefinition.cs b/osu.Game/Storyboards/StoryboardAnimation.cs similarity index 79% rename from osu.Game/Storyboards/AnimationDefinition.cs rename to osu.Game/Storyboards/StoryboardAnimation.cs index 3ac9cbfe0e..98936df9e5 100644 --- a/osu.Game/Storyboards/AnimationDefinition.cs +++ b/osu.Game/Storyboards/StoryboardAnimation.cs @@ -7,13 +7,13 @@ using osu.Game.Storyboards.Drawables; namespace osu.Game.Storyboards { - public class AnimationDefinition : SpriteDefinition + public class StoryboardAnimation : StoryboardSprite { public int FrameCount; public double FrameDelay; public AnimationLoopType LoopType; - public AnimationDefinition(string path, Anchor origin, Vector2 initialPosition, int frameCount, double frameDelay, AnimationLoopType loopType) + public StoryboardAnimation(string path, Anchor origin, Vector2 initialPosition, int frameCount, double frameDelay, AnimationLoopType loopType) : base(path, origin, initialPosition) { FrameCount = frameCount; @@ -22,7 +22,7 @@ namespace osu.Game.Storyboards } public override Drawable CreateDrawable() - => new StoryboardAnimation(this); + => new DrawableStoryboardAnimation(this); } public enum AnimationLoopType diff --git a/osu.Game/Storyboards/StoryboardDefinition.cs b/osu.Game/Storyboards/StoryboardDefinition.cs deleted file mode 100644 index 4ef24cda91..0000000000 --- a/osu.Game/Storyboards/StoryboardDefinition.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2007-2017 ppy Pty Ltd . -// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE - -using osu.Game.Storyboards.Drawables; -using System.Collections.Generic; -using System.Linq; - -namespace osu.Game.Storyboards -{ - public class StoryboardDefinition - { - private readonly Dictionary layers = new Dictionary(); - public IEnumerable Layers => layers.Values; - - public StoryboardDefinition() - { - layers.Add("Background", new LayerDefinition("Background", 3)); - layers.Add("Fail", new LayerDefinition("Fail", 2) { EnabledWhenPassing = false, }); - layers.Add("Pass", new LayerDefinition("Pass", 1) { EnabledWhenFailing = false, }); - layers.Add("Foreground", new LayerDefinition("Foreground", 0)); - } - - public LayerDefinition GetLayer(string name) - { - LayerDefinition layer; - if (!layers.TryGetValue(name, out layer)) - layers[name] = layer = new LayerDefinition(name, layers.Values.Min(l => l.Depth) - 1); - - return layer; - } - - public Storyboard CreateDrawable() - => new Storyboard(this); - } -} diff --git a/osu.Game/Storyboards/LayerDefinition.cs b/osu.Game/Storyboards/StoryboardLayer.cs similarity index 55% rename from osu.Game/Storyboards/LayerDefinition.cs rename to osu.Game/Storyboards/StoryboardLayer.cs index baefe1626a..f565b13eb5 100644 --- a/osu.Game/Storyboards/LayerDefinition.cs +++ b/osu.Game/Storyboards/StoryboardLayer.cs @@ -6,28 +6,28 @@ using System.Collections.Generic; namespace osu.Game.Storyboards { - public class LayerDefinition + public class StoryboardLayer { public string Name; public int Depth; public bool EnabledWhenPassing = true; public bool EnabledWhenFailing = true; - private readonly List elements = new List(); - public IEnumerable Elements => elements; + private readonly List elements = new List(); + public IEnumerable Elements => elements; - public LayerDefinition(string name, int depth) + public StoryboardLayer(string name, int depth) { Name = name; Depth = depth; } - public void Add(IElementDefinition element) + public void Add(IStoryboardElement element) { elements.Add(element); } - public StoryboardLayer CreateDrawable() - => new StoryboardLayer(this) { Depth = Depth, }; + public DrawableStoryboardLayer CreateDrawable() + => new DrawableStoryboardLayer(this) { Depth = Depth, }; } } diff --git a/osu.Game/Storyboards/SampleDefinition.cs b/osu.Game/Storyboards/StoryboardSample.cs similarity index 77% rename from osu.Game/Storyboards/SampleDefinition.cs rename to osu.Game/Storyboards/StoryboardSample.cs index 5d5e8ef1e9..bcf6a4329d 100644 --- a/osu.Game/Storyboards/SampleDefinition.cs +++ b/osu.Game/Storyboards/StoryboardSample.cs @@ -5,13 +5,13 @@ using osu.Framework.Graphics; namespace osu.Game.Storyboards { - public class SampleDefinition : IElementDefinition + public class StoryboardSample : IStoryboardElement { public string Path { get; set; } public double Time; public float Volume; - public SampleDefinition(string path, double time, float volume) + public StoryboardSample(string path, double time, float volume) { Path = path; Time = time; diff --git a/osu.Game/Storyboards/SpriteDefinition.cs b/osu.Game/Storyboards/StoryboardSprite.cs similarity index 95% rename from osu.Game/Storyboards/SpriteDefinition.cs rename to osu.Game/Storyboards/StoryboardSprite.cs index 4e5c8f8903..598167d720 100644 --- a/osu.Game/Storyboards/SpriteDefinition.cs +++ b/osu.Game/Storyboards/StoryboardSprite.cs @@ -10,7 +10,7 @@ using System.Linq; namespace osu.Game.Storyboards { - public class SpriteDefinition : IElementDefinition + public class StoryboardSprite : IStoryboardElement { private readonly List loops = new List(); private readonly List triggers = new List(); @@ -34,7 +34,7 @@ namespace osu.Game.Storyboards private delegate void DrawablePropertyInitializer(Drawable drawable, T value); private delegate void DrawableTransformer(Drawable drawable, T value, double duration, Easing easing); - public SpriteDefinition(string path, Anchor origin, Vector2 initialPosition) + public StoryboardSprite(string path, Anchor origin, Vector2 initialPosition) { Path = path; Origin = origin; @@ -56,7 +56,7 @@ namespace osu.Game.Storyboards } public virtual Drawable CreateDrawable() - => new StoryboardSprite(this); + => new DrawableStoryboardSprite(this); public void ApplyTransforms(Drawable drawable, IEnumerable> triggeredGroups = null) { diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index f9980b0b58..737d0cc334 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -81,21 +81,21 @@ - - - - - + + + + + - + - - - - + + + + From fb7740a3ab7abeccf02c1ff574cf4c1a60a2ce1a Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Sep 2017 20:25:40 +0900 Subject: [PATCH 57/64] Update all dependencies in line with framework --- NuGet.config | 6 +++++ osu-framework | 2 +- osu.Desktop.Deploy/App.config | 2 +- osu.Desktop.Deploy/osu.Desktop.Deploy.csproj | 17 +++++++------ osu.Desktop.Deploy/packages.config | 8 +++--- osu.Desktop.Tests/OpenTK.dll.config | 25 +++++++++++++++++++ osu.Desktop.Tests/osu.Desktop.Tests.csproj | 10 +++++--- osu.Desktop.Tests/packages.config | 6 ++--- osu.Desktop/OpenTK.dll.config | 4 --- osu.Desktop/app.config | 15 +++++++++++ osu.Desktop/osu.Desktop.csproj | 13 +++++----- osu.Desktop/packages.config | 6 ++--- osu.Game.Rulesets.Catch/OpenTK.dll.config | 4 --- osu.Game.Rulesets.Catch/UI/CatcherArea.cs | 2 +- osu.Game.Rulesets.Catch/app.config | 11 ++++++++ .../osu.Game.Rulesets.Catch.csproj | 3 ++- osu.Game.Rulesets.Catch/packages.config | 7 +----- osu.Game.Rulesets.Mania/OpenTK.dll.config | 4 --- osu.Game.Rulesets.Mania/app.config | 11 ++++++++ .../osu.Game.Rulesets.Mania.csproj | 3 ++- osu.Game.Rulesets.Mania/packages.config | 6 +---- .../Beatmaps/OsuBeatmapProcessor.cs | 13 +++++----- osu.Game.Rulesets.Osu/OpenTK.dll.config | 4 --- osu.Game.Rulesets.Osu/app.config | 11 ++++++++ .../osu.Game.Rulesets.Osu.csproj | 3 ++- osu.Game.Rulesets.Osu/packages.config | 7 +----- osu.Game.Rulesets.Taiko/OpenTK.dll.config | 4 --- osu.Game.Rulesets.Taiko/app.config | 11 ++++++++ .../osu.Game.Rulesets.Taiko.csproj | 3 ++- osu.Game.Rulesets.Taiko/packages.config | 6 +---- osu.Game.Tests/OpenTK.dll.config | 4 --- osu.Game.Tests/app.config | 11 ++++++++ osu.Game.Tests/osu.Game.Tests.csproj | 7 +++--- osu.Game.Tests/packages.config | 4 +-- osu.Game/Graphics/Backgrounds/Triangles.cs | 6 ++--- osu.Game/Graphics/Cursor/MenuCursor.cs | 2 +- osu.Game/OpenTK.dll.config | 25 +++++++++++++++++++ osu.Game/Screens/Menu/LogoVisualisation.cs | 8 +++--- osu.Game/app.config | 11 ++++++++ osu.Game/osu.Game.csproj | 11 +++++--- osu.Game/packages.config | 6 ++--- 41 files changed, 215 insertions(+), 107 deletions(-) create mode 100644 NuGet.config create mode 100644 osu.Desktop.Tests/OpenTK.dll.config create mode 100644 osu.Desktop/app.config create mode 100644 osu.Game.Rulesets.Catch/app.config create mode 100644 osu.Game.Rulesets.Mania/app.config create mode 100644 osu.Game.Rulesets.Osu/app.config create mode 100644 osu.Game.Rulesets.Taiko/app.config create mode 100644 osu.Game.Tests/app.config create mode 100644 osu.Game/OpenTK.dll.config create mode 100644 osu.Game/app.config diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000000..95f993e510 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/osu-framework b/osu-framework index 1a259925b8..f039a8cb70 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit 1a259925b82c31ddcebf7b330a6ef9d3a9daf089 +Subproject commit f039a8cb707296238d22b6c382af862725c05928 diff --git a/osu.Desktop.Deploy/App.config b/osu.Desktop.Deploy/App.config index 6711f9c54e..2fae7a5e1c 100644 --- a/osu.Desktop.Deploy/App.config +++ b/osu.Desktop.Deploy/App.config @@ -33,7 +33,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste - + diff --git a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj index c090342a4b..a66c9c8993 100644 --- a/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj +++ b/osu.Desktop.Deploy/osu.Desktop.Deploy.csproj @@ -66,22 +66,23 @@ True - $(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll - - - $(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll + $(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll True - - $(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll + + $(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll + True + + + $(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll True $(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll True - - $(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll + + $(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll True diff --git a/osu.Desktop.Deploy/packages.config b/osu.Desktop.Deploy/packages.config index 3c5ca9f9a3..7725be5f5e 100644 --- a/osu.Desktop.Deploy/packages.config +++ b/osu.Desktop.Deploy/packages.config @@ -6,9 +6,9 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste - - - + + + - + \ No newline at end of file diff --git a/osu.Desktop.Tests/OpenTK.dll.config b/osu.Desktop.Tests/OpenTK.dll.config new file mode 100644 index 0000000000..5620e3d9e2 --- /dev/null +++ b/osu.Desktop.Tests/OpenTK.dll.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.Desktop.Tests/osu.Desktop.Tests.csproj b/osu.Desktop.Tests/osu.Desktop.Tests.csproj index 975af1a782..e40ee5b049 100644 --- a/osu.Desktop.Tests/osu.Desktop.Tests.csproj +++ b/osu.Desktop.Tests/osu.Desktop.Tests.csproj @@ -35,14 +35,15 @@ - $(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll + $(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + True - - $(SolutionDir)\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll + + $(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll True - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True @@ -156,6 +157,7 @@ osu.licenseheader + diff --git a/osu.Desktop.Tests/packages.config b/osu.Desktop.Tests/packages.config index ed487e5cd5..ea33822638 100644 --- a/osu.Desktop.Tests/packages.config +++ b/osu.Desktop.Tests/packages.config @@ -4,9 +4,9 @@ Copyright (c) 2007-2017 ppy Pty Ltd . Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE --> - - - + + + diff --git a/osu.Desktop/OpenTK.dll.config b/osu.Desktop/OpenTK.dll.config index 627e9f6009..5620e3d9e2 100644 --- a/osu.Desktop/OpenTK.dll.config +++ b/osu.Desktop/OpenTK.dll.config @@ -1,7 +1,3 @@ - diff --git a/osu.Desktop/app.config b/osu.Desktop/app.config new file mode 100644 index 0000000000..a704cc3750 --- /dev/null +++ b/osu.Desktop/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Desktop/osu.Desktop.csproj b/osu.Desktop/osu.Desktop.csproj index 661c17699b..5eebad47ef 100644 --- a/osu.Desktop/osu.Desktop.csproj +++ b/osu.Desktop/osu.Desktop.csproj @@ -136,23 +136,23 @@ - $(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\NuGet.Squirrel.dll + $(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\NuGet.Squirrel.dll True - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True - - $(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll + + $(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll True $(SolutionDir)\packages\Splat.2.0.0\lib\Net45\Splat.dll True - - $(SolutionDir)\packages\squirrel.windows.1.7.5\lib\Net45\Squirrel.dll + + $(SolutionDir)\packages\squirrel.windows.1.7.8\lib\Net45\Squirrel.dll True @@ -173,6 +173,7 @@ osu.licenseheader + diff --git a/osu.Desktop/packages.config b/osu.Desktop/packages.config index 3ad2106d2b..269b901a97 100644 --- a/osu.Desktop/packages.config +++ b/osu.Desktop/packages.config @@ -7,8 +7,8 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste - - + + - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/OpenTK.dll.config b/osu.Game.Rulesets.Catch/OpenTK.dll.config index 627e9f6009..5620e3d9e2 100644 --- a/osu.Game.Rulesets.Catch/OpenTK.dll.config +++ b/osu.Game.Rulesets.Catch/OpenTK.dll.config @@ -1,7 +1,3 @@ - diff --git a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs index 64dbe04ba4..5fc2cf9ef7 100644 --- a/osu.Game.Rulesets.Catch/UI/CatcherArea.cs +++ b/osu.Game.Rulesets.Catch/UI/CatcherArea.cs @@ -163,7 +163,7 @@ namespace osu.Game.Rulesets.Catch.UI float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; - while (Children.OfType().Any(f => Vector2.DistanceSquared(f.Position, fruit.Position) < distance * distance)) + while (Children.OfType().Any(f => Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) { fruit.X += RNG.Next(-5, 5); fruit.Y -= RNG.Next(0, 5); diff --git a/osu.Game.Rulesets.Catch/app.config b/osu.Game.Rulesets.Catch/app.config new file mode 100644 index 0000000000..faeaf001de --- /dev/null +++ b/osu.Game.Rulesets.Catch/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj index 2ae2262ac7..18e1ee29ca 100644 --- a/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj +++ b/osu.Game.Rulesets.Catch/osu.Game.Rulesets.Catch.csproj @@ -34,7 +34,7 @@ - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True @@ -69,6 +69,7 @@ osu.licenseheader + diff --git a/osu.Game.Rulesets.Catch/packages.config b/osu.Game.Rulesets.Catch/packages.config index fa6edb9c8f..0b1838ceee 100644 --- a/osu.Game.Rulesets.Catch/packages.config +++ b/osu.Game.Rulesets.Catch/packages.config @@ -1,9 +1,4 @@  - - - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/OpenTK.dll.config b/osu.Game.Rulesets.Mania/OpenTK.dll.config index 627e9f6009..5620e3d9e2 100644 --- a/osu.Game.Rulesets.Mania/OpenTK.dll.config +++ b/osu.Game.Rulesets.Mania/OpenTK.dll.config @@ -1,7 +1,3 @@ - diff --git a/osu.Game.Rulesets.Mania/app.config b/osu.Game.Rulesets.Mania/app.config new file mode 100644 index 0000000000..faeaf001de --- /dev/null +++ b/osu.Game.Rulesets.Mania/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj index bd540f72c0..739f1cf48c 100644 --- a/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj +++ b/osu.Game.Rulesets.Mania/osu.Game.Rulesets.Mania.csproj @@ -34,7 +34,7 @@ - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True @@ -110,6 +110,7 @@ osu.licenseheader + diff --git a/osu.Game.Rulesets.Mania/packages.config b/osu.Game.Rulesets.Mania/packages.config index 8add43d5d5..0b1838ceee 100644 --- a/osu.Game.Rulesets.Mania/packages.config +++ b/osu.Game.Rulesets.Mania/packages.config @@ -1,8 +1,4 @@  - - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index fce0188cda..9379ec22c8 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using OpenTK; +using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Beatmaps; using osu.Game.Rulesets.Objects.Types; @@ -64,8 +65,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps //We are no longer within stacking range of the next object. break; - if (Vector2.Distance(stackBaseObject.Position, objectN.Position) < stack_distance || - stackBaseObject is Slider && Vector2.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance) + if (Vector2Extensions.Distance(stackBaseObject.Position, objectN.Position) < stack_distance || + stackBaseObject is Slider && Vector2Extensions.Distance(stackBaseObject.EndPosition, objectN.Position) < stack_distance) { stackBaseIndex = n; @@ -130,14 +131,14 @@ namespace osu.Game.Rulesets.Osu.Beatmaps * o <- hitCircle has stack of -1 * o <- hitCircle has stack of -2 */ - if (objectN is Slider && Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance) + if (objectN is Slider && Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance) { int offset = objectI.StackHeight - objectN.StackHeight + 1; for (int j = n + 1; j <= i; j++) { //For each object which was declared under this slider, we will offset it to appear *below* the slider end (rather than above). OsuHitObject objectJ = beatmap.HitObjects[j]; - if (Vector2.Distance(objectN.EndPosition, objectJ.Position) < stack_distance) + if (Vector2Extensions.Distance(objectN.EndPosition, objectJ.Position) < stack_distance) objectJ.StackHeight -= offset; } @@ -146,7 +147,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps break; } - if (Vector2.Distance(objectN.Position, objectI.Position) < stack_distance) + if (Vector2Extensions.Distance(objectN.Position, objectI.Position) < stack_distance) { //Keep processing as if there are no sliders. If we come across a slider, this gets cancelled out. //NOTE: Sliders with start positions stacking are a special case that is also handled here. @@ -170,7 +171,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps //We are no longer within stacking range of the previous object. break; - if (Vector2.Distance(objectN.EndPosition, objectI.Position) < stack_distance) + if (Vector2Extensions.Distance(objectN.EndPosition, objectI.Position) < stack_distance) { objectN.StackHeight = objectI.StackHeight + 1; objectI = objectN; diff --git a/osu.Game.Rulesets.Osu/OpenTK.dll.config b/osu.Game.Rulesets.Osu/OpenTK.dll.config index 627e9f6009..5620e3d9e2 100644 --- a/osu.Game.Rulesets.Osu/OpenTK.dll.config +++ b/osu.Game.Rulesets.Osu/OpenTK.dll.config @@ -1,7 +1,3 @@ - diff --git a/osu.Game.Rulesets.Osu/app.config b/osu.Game.Rulesets.Osu/app.config new file mode 100644 index 0000000000..faeaf001de --- /dev/null +++ b/osu.Game.Rulesets.Osu/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj index 857f47f9b9..0963b0ad1b 100644 --- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj +++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj @@ -35,7 +35,7 @@ - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True @@ -110,6 +110,7 @@ osu.licenseheader + diff --git a/osu.Game.Rulesets.Osu/packages.config b/osu.Game.Rulesets.Osu/packages.config index fa6edb9c8f..0b1838ceee 100644 --- a/osu.Game.Rulesets.Osu/packages.config +++ b/osu.Game.Rulesets.Osu/packages.config @@ -1,9 +1,4 @@  - - - + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/OpenTK.dll.config b/osu.Game.Rulesets.Taiko/OpenTK.dll.config index 627e9f6009..5620e3d9e2 100644 --- a/osu.Game.Rulesets.Taiko/OpenTK.dll.config +++ b/osu.Game.Rulesets.Taiko/OpenTK.dll.config @@ -1,7 +1,3 @@ - diff --git a/osu.Game.Rulesets.Taiko/app.config b/osu.Game.Rulesets.Taiko/app.config new file mode 100644 index 0000000000..faeaf001de --- /dev/null +++ b/osu.Game.Rulesets.Taiko/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj index a840997214..c8915d233e 100644 --- a/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj +++ b/osu.Game.Rulesets.Taiko/osu.Game.Rulesets.Taiko.csproj @@ -34,7 +34,7 @@ - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True @@ -100,6 +100,7 @@ osu.licenseheader + diff --git a/osu.Game.Rulesets.Taiko/packages.config b/osu.Game.Rulesets.Taiko/packages.config index 8add43d5d5..0b1838ceee 100644 --- a/osu.Game.Rulesets.Taiko/packages.config +++ b/osu.Game.Rulesets.Taiko/packages.config @@ -1,8 +1,4 @@  - - + \ No newline at end of file diff --git a/osu.Game.Tests/OpenTK.dll.config b/osu.Game.Tests/OpenTK.dll.config index 627e9f6009..5620e3d9e2 100644 --- a/osu.Game.Tests/OpenTK.dll.config +++ b/osu.Game.Tests/OpenTK.dll.config @@ -1,7 +1,3 @@ - diff --git a/osu.Game.Tests/app.config b/osu.Game.Tests/app.config new file mode 100644 index 0000000000..faeaf001de --- /dev/null +++ b/osu.Game.Tests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 220b1aac7f..07190bedb0 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -30,12 +30,12 @@ false - - $(SolutionDir)\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll + + $(SolutionDir)\packages\NUnit.3.8.1\lib\net45\nunit.framework.dll True - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True @@ -53,6 +53,7 @@ osu.licenseheader + diff --git a/osu.Game.Tests/packages.config b/osu.Game.Tests/packages.config index 9ad76308d7..af47f642e3 100644 --- a/osu.Game.Tests/packages.config +++ b/osu.Game.Tests/packages.config @@ -4,8 +4,8 @@ Copyright (c) 2007-2017 ppy Pty Ltd . Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE --> - - + + \ No newline at end of file diff --git a/osu.Game/Graphics/Backgrounds/Triangles.cs b/osu.Game/Graphics/Backgrounds/Triangles.cs index 08745ce6ba..6312db3ad6 100644 --- a/osu.Game/Graphics/Backgrounds/Triangles.cs +++ b/osu.Game/Graphics/Backgrounds/Triangles.cs @@ -228,9 +228,9 @@ namespace osu.Game.Graphics.Backgrounds var size = new Vector2(2 * offset.X, offset.Y); var triangle = new Triangle( - particle.Position * Size * DrawInfo.Matrix, - (particle.Position * Size + offset) * DrawInfo.Matrix, - (particle.Position * Size + new Vector2(-offset.X, offset.Y)) * DrawInfo.Matrix + Vector2Extensions.Transform(particle.Position * Size, DrawInfo.Matrix), + Vector2Extensions.Transform(particle.Position * Size + offset, DrawInfo.Matrix), + Vector2Extensions.Transform(particle.Position * Size + new Vector2(-offset.X, offset.Y), DrawInfo.Matrix) ); ColourInfo colourInfo = DrawInfo.Colour; diff --git a/osu.Game/Graphics/Cursor/MenuCursor.cs b/osu.Game/Graphics/Cursor/MenuCursor.cs index 053ed9c191..36f23d1ae9 100644 --- a/osu.Game/Graphics/Cursor/MenuCursor.cs +++ b/osu.Game/Graphics/Cursor/MenuCursor.cs @@ -32,7 +32,7 @@ namespace osu.Game.Graphics.Cursor // don't start rotating until we're moved a minimum distance away from the mouse down location, // else it can have an annoying effect. - startRotation |= Vector2.Distance(state.Mouse.Position, state.Mouse.PositionMouseDown.Value) > 30; + startRotation |= Vector2Extensions.Distance(state.Mouse.Position, state.Mouse.PositionMouseDown.Value) > 30; if (startRotation) { diff --git a/osu.Game/OpenTK.dll.config b/osu.Game/OpenTK.dll.config new file mode 100644 index 0000000000..5620e3d9e2 --- /dev/null +++ b/osu.Game/OpenTK.dll.config @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index bc94f88866..4b8942349d 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -201,10 +201,10 @@ namespace osu.Game.Screens.Menu var amplitudeOffset = new Vector2(rotationCos * barSize.Y, rotationSin * barSize.Y); var rectangle = new Quad( - (barPosition - bottomOffset) * DrawInfo.Matrix, - (barPosition - bottomOffset + amplitudeOffset) * DrawInfo.Matrix, - (barPosition + bottomOffset) * DrawInfo.Matrix, - (barPosition + bottomOffset + amplitudeOffset) * DrawInfo.Matrix + Vector2Extensions.Transform(barPosition - bottomOffset, DrawInfo.Matrix), + Vector2Extensions.Transform(barPosition - bottomOffset + amplitudeOffset, DrawInfo.Matrix), + Vector2Extensions.Transform(barPosition + bottomOffset, DrawInfo.Matrix), + Vector2Extensions.Transform(barPosition + bottomOffset + amplitudeOffset, DrawInfo.Matrix) ); Texture.DrawQuad( diff --git a/osu.Game/app.config b/osu.Game/app.config new file mode 100644 index 0000000000..faeaf001de --- /dev/null +++ b/osu.Game/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index e0eafe8422..65ec7d31b3 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -37,15 +37,16 @@ - $(SolutionDir)\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll + $(SolutionDir)\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll + True - $(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll + $(SolutionDir)\packages\OpenTK.3.0.0-git00009\lib\net20\OpenTK.dll True - + + $(SolutionDir)\packages\SharpCompress.0.18.1\lib\net45\SharpCompress.dll True - $(SolutionDir)\packages\SharpCompress.0.17.1\lib\net45\SharpCompress.dll $(SolutionDir)\packages\SQLite.Net.Core-PCL.3.1.1\lib\portable-win8+net45+wp8+wpa81+MonoAndroid1+MonoTouch1\SQLite.Net.dll @@ -556,6 +557,8 @@ osu.licenseheader + + diff --git a/osu.Game/packages.config b/osu.Game/packages.config index 434f9328ea..292ba22c06 100644 --- a/osu.Game/packages.config +++ b/osu.Game/packages.config @@ -5,9 +5,9 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/maste --> - - - + + + From 25f2a102f467966655d6c824afd2c810537b2694 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 13 Sep 2017 20:35:44 +0900 Subject: [PATCH 58/64] Fix CI issue --- osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 9379ec22c8..621584ce05 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using OpenTK; using osu.Framework.Graphics; using osu.Game.Beatmaps; using osu.Game.Rulesets.Beatmaps; From 89b5a6670eb535e8b7fcc96e7d092a15ba053c95 Mon Sep 17 00:00:00 2001 From: MrTheMake Date: Wed, 13 Sep 2017 16:18:02 +0200 Subject: [PATCH 59/64] Changed type of IHasFilterTerms.FilterTerms according to framework update --- osu.Game/Graphics/UserInterface/OsuButton.cs | 3 ++- osu.Game/Overlays/Chat/ChannelListItem.cs | 3 ++- osu.Game/Overlays/Chat/ChannelSection.cs | 2 +- osu.Game/Overlays/KeyBinding/KeyBindingRow.cs | 4 ++-- osu.Game/Overlays/Music/PlaylistItem.cs | 2 +- osu.Game/Overlays/Music/PlaylistList.cs | 2 +- osu.Game/Overlays/Settings/SettingsItem.cs | 3 ++- osu.Game/Overlays/Settings/SettingsSection.cs | 2 +- osu.Game/Overlays/Settings/SettingsSubsection.cs | 2 +- 9 files changed, 13 insertions(+), 10 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuButton.cs b/osu.Game/Graphics/UserInterface/OsuButton.cs index 32a37a4910..ccc23e3ff6 100644 --- a/osu.Game/Graphics/UserInterface/OsuButton.cs +++ b/osu.Game/Graphics/UserInterface/OsuButton.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using OpenTK.Graphics; using osu.Framework.Allocation; using osu.Framework.Audio; @@ -112,7 +113,7 @@ namespace osu.Game.Graphics.UserInterface return base.OnMouseUp(state, args); } - public string[] FilterTerms => new[] { Text }; + public IEnumerable FilterTerms => new[] { Text }; public bool MatchingFilter { diff --git a/osu.Game/Overlays/Chat/ChannelListItem.cs b/osu.Game/Overlays/Chat/ChannelListItem.cs index 8360e793d8..f4cf806044 100644 --- a/osu.Game/Overlays/Chat/ChannelListItem.cs +++ b/osu.Game/Overlays/Chat/ChannelListItem.cs @@ -2,6 +2,7 @@ // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System; +using System.Collections.Generic; using OpenTK; using OpenTK.Graphics; using osu.Framework.Allocation; @@ -34,7 +35,7 @@ namespace osu.Game.Overlays.Chat private Color4 topicColour; private Color4 hoverColour; - public string[] FilterTerms => new[] { channel.Name }; + public IEnumerable FilterTerms => new[] { channel.Name }; public bool MatchingFilter { set diff --git a/osu.Game/Overlays/Chat/ChannelSection.cs b/osu.Game/Overlays/Chat/ChannelSection.cs index 1f046aff2a..5068b415bc 100644 --- a/osu.Game/Overlays/Chat/ChannelSection.cs +++ b/osu.Game/Overlays/Chat/ChannelSection.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Chat public readonly FillFlowContainer ChannelFlow; public IEnumerable FilterableChildren => ChannelFlow.Children; - public string[] FilterTerms => new[] { Header }; + public IEnumerable FilterTerms => new[] { Header }; public bool MatchingFilter { set diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs index 046e56573f..fb84853a0d 100644 --- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs +++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs @@ -47,7 +47,7 @@ namespace osu.Game.Overlays.KeyBinding private FillFlowContainer buttons; - public string[] FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); + public IEnumerable FilterTerms => new[] { text.Text }.Concat(bindings.Select(b => b.KeyCombination.ReadableString())).ToArray(); public KeyBindingRow(object action, IEnumerable bindings) { @@ -371,4 +371,4 @@ namespace osu.Game.Overlays.KeyBinding } } } -} \ No newline at end of file +} diff --git a/osu.Game/Overlays/Music/PlaylistItem.cs b/osu.Game/Overlays/Music/PlaylistItem.cs index 2aaa182685..723b3f4e96 100644 --- a/osu.Game/Overlays/Music/PlaylistItem.cs +++ b/osu.Game/Overlays/Music/PlaylistItem.cs @@ -129,7 +129,7 @@ namespace osu.Game.Overlays.Music return true; } - public string[] FilterTerms { get; private set; } + public IEnumerable FilterTerms { get; private set; } private bool matching = true; diff --git a/osu.Game/Overlays/Music/PlaylistList.cs b/osu.Game/Overlays/Music/PlaylistList.cs index 360e2ad843..6f1eaded7f 100644 --- a/osu.Game/Overlays/Music/PlaylistList.cs +++ b/osu.Game/Overlays/Music/PlaylistList.cs @@ -229,7 +229,7 @@ namespace osu.Game.Overlays.Music private class ItemSearchContainer : FillFlowContainer, IHasFilterableChildren { - public string[] FilterTerms => new string[] { }; + public IEnumerable FilterTerms => new string[] { }; public bool MatchingFilter { set diff --git a/osu.Game/Overlays/Settings/SettingsItem.cs b/osu.Game/Overlays/Settings/SettingsItem.cs index c74f4070e7..f2044f178b 100644 --- a/osu.Game/Overlays/Settings/SettingsItem.cs +++ b/osu.Game/Overlays/Settings/SettingsItem.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Collections.Generic; using OpenTK.Graphics; using osu.Framework.Configuration; using osu.Framework.Graphics; @@ -53,7 +54,7 @@ namespace osu.Game.Overlays.Settings } } - public string[] FilterTerms => new[] { LabelText }; + public IEnumerable FilterTerms => new[] { LabelText }; public bool MatchingFilter { diff --git a/osu.Game/Overlays/Settings/SettingsSection.cs b/osu.Game/Overlays/Settings/SettingsSection.cs index f091192d27..eb6e398477 100644 --- a/osu.Game/Overlays/Settings/SettingsSection.cs +++ b/osu.Game/Overlays/Settings/SettingsSection.cs @@ -23,7 +23,7 @@ namespace osu.Game.Overlays.Settings public abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public string[] FilterTerms => new[] { Header }; + public IEnumerable FilterTerms => new[] { Header }; private const int header_size = 26; private const int header_margin = 25; diff --git a/osu.Game/Overlays/Settings/SettingsSubsection.cs b/osu.Game/Overlays/Settings/SettingsSubsection.cs index 0fbb5b92f7..4164ceee21 100644 --- a/osu.Game/Overlays/Settings/SettingsSubsection.cs +++ b/osu.Game/Overlays/Settings/SettingsSubsection.cs @@ -20,7 +20,7 @@ namespace osu.Game.Overlays.Settings protected abstract string Header { get; } public IEnumerable FilterableChildren => Children.OfType(); - public string[] FilterTerms => new[] { Header }; + public IEnumerable FilterTerms => new[] { Header }; public bool MatchingFilter { set From 4a232bbc046cf19ce5607c4c38048eb5ea053375 Mon Sep 17 00:00:00 2001 From: MrTheMake Date: Wed, 13 Sep 2017 18:44:44 +0200 Subject: [PATCH 60/64] updated framework --- osu-framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu-framework b/osu-framework index f039a8cb70..b060218232 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit f039a8cb707296238d22b6c382af862725c05928 +Subproject commit b060218232fcd6f24d4922d05160616db0195bd4 From b1145272d1c7cc3d7dc51ef178cd2df700102e5c Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Sep 2017 12:58:32 +0900 Subject: [PATCH 61/64] Update code to support new inspectcode analysis rules --- appveyor.yml | 1 + osu-framework | 2 +- osu.Game/Beatmaps/WorkingBeatmap.cs | 7 +++++-- osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs | 2 +- .../Overlays/Settings/Sections/General/UpdateSettings.cs | 2 +- .../Overlays/Settings/Sections/Input/KeyboardSettings.cs | 2 +- osu.Game/Screens/Menu/MainMenu.cs | 2 +- osu.Game/Screens/Play/SongProgressGraph.cs | 8 ++++++-- osu.Game/Screens/Select/SongSelect.cs | 2 +- osu.Game/Screens/Tournament/Drawings.cs | 2 +- osu.Game/Users/Avatar.cs | 2 +- osu.sln.DotSettings | 3 +++ 12 files changed, 23 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b26a895788..21c15724e6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,4 @@ +# 2017-09-14 clone_depth: 1 version: '{branch}-{build}' configuration: Debug diff --git a/osu-framework b/osu-framework index b060218232..7347c386dc 160000 --- a/osu-framework +++ b/osu-framework @@ -1 +1 @@ -Subproject commit b060218232fcd6f24d4922d05160616db0195bd4 +Subproject commit 7347c386dcd10eb799b1ce1512536879328109f9 diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index df8e7f5e3b..bb3122489e 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -100,8 +100,11 @@ namespace osu.Game.Beatmaps public void TransferTo(WorkingBeatmap other) { - if (track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo)) - other.track = track; + lock (trackLock) + { + if (track != null && BeatmapInfo.AudioEquals(other.BeatmapInfo)) + other.track = track; + } if (background != null && BeatmapInfo.BackgroundEquals(other.BeatmapInfo)) other.background = background; diff --git a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs index 0a32b50809..495a2543d1 100644 --- a/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Debug/GCSettings.cs @@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Settings.Sections.Debug { RelativeSizeAxes = Axes.X, Text = "Force garbage collection", - Action = () => GC.Collect() + Action = GC.Collect }, }; } diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs index 01e32b5a1b..833a5ff966 100644 --- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs @@ -27,7 +27,7 @@ namespace osu.Game.Overlays.Settings.Sections.General { RelativeSizeAxes = Axes.X, Text = "Open osu! folder", - Action = () => storage.OpenInNativeExplorer(), + Action = storage.OpenInNativeExplorer, } }; } diff --git a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs index 01e73d0168..b68fd4bc04 100644 --- a/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Input/KeyboardSettings.cs @@ -18,7 +18,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input { RelativeSizeAxes = Axes.X, Text = "Key Configuration", - Action = () => keyConfig.ToggleVisibility() + Action = keyConfig.ToggleVisibility }, }; } diff --git a/osu.Game/Screens/Menu/MainMenu.cs b/osu.Game/Screens/Menu/MainMenu.cs index 2544cc2837..1c82d15f50 100644 --- a/osu.Game/Screens/Menu/MainMenu.cs +++ b/osu.Game/Screens/Menu/MainMenu.cs @@ -50,7 +50,7 @@ namespace osu.Game.Screens.Menu OnEdit = delegate { Push(new Editor()); }, OnSolo = delegate { Push(consumeSongSelect()); }, OnMulti = delegate { Push(new Lobby()); }, - OnExit = delegate { Exit(); }, + OnExit = Exit, } } }, diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index 541065e532..dc4deaaefc 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -1,8 +1,10 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System; using System.Linq; using System.Collections.Generic; +using System.Diagnostics; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects; @@ -34,10 +36,12 @@ namespace osu.Game.Screens.Play foreach (var h in objects) { - IHasEndTime end = h as IHasEndTime; + var endTime = Math.Max((h as IHasEndTime)?.EndTime ?? h.StartTime, h.StartTime); + + Debug.Assert(endTime > h.StartTime); int startRange = (int)((h.StartTime - firstHit) / interval); - int endRange = (int)(((end?.EndTime > 0 ? end.EndTime : h.StartTime) - firstHit) / interval); + int endRange = (int)((endTime - firstHit) / interval); for (int i = startRange; i <= endRange; i++) Values[i]++; } diff --git a/osu.Game/Screens/Select/SongSelect.cs b/osu.Game/Screens/Select/SongSelect.cs index f97c4fe420..84457b77a7 100644 --- a/osu.Game/Screens/Select/SongSelect.cs +++ b/osu.Game/Screens/Select/SongSelect.cs @@ -106,7 +106,7 @@ namespace osu.Game.Screens.Select Origin = Anchor.CentreRight, SelectionChanged = carouselSelectionChanged, BeatmapsChanged = carouselBeatmapsLoaded, - DeleteRequested = b => promptDelete(b), + DeleteRequested = promptDelete, RestoreRequested = s => { foreach (var b in s.Beatmaps) manager.Restore(b); }, HideDifficultyRequested = b => manager.Hide(b), StartRequested = () => carouselRaisedStart(), diff --git a/osu.Game/Screens/Tournament/Drawings.cs b/osu.Game/Screens/Tournament/Drawings.cs index 7cd81a924d..3d27552212 100644 --- a/osu.Game/Screens/Tournament/Drawings.cs +++ b/osu.Game/Screens/Tournament/Drawings.cs @@ -237,7 +237,7 @@ namespace osu.Game.Screens.Tournament RelativeSizeAxes = Axes.X, Text = "Reset", - Action = () => reset(false) + Action = () => reset() } } } diff --git a/osu.Game/Users/Avatar.cs b/osu.Game/Users/Avatar.cs index 5d518f1780..111c901ca0 100644 --- a/osu.Game/Users/Avatar.cs +++ b/osu.Game/Users/Avatar.cs @@ -26,7 +26,7 @@ namespace osu.Game.Users private void load(TextureStore textures) { Texture texture = null; - if (user?.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}"); + if (user != null && user.Id > 1) texture = textures.Get($@"https://a.ppy.sh/{user.Id}"); if (texture == null) texture = textures.Get(@"Online/avatar-guest"); Add(new Sprite diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 0b8c196ec8..8988908ee2 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -56,6 +56,8 @@ WARNING HINT HINT + HINT + HINT HINT WARNING WARNING @@ -617,6 +619,7 @@ Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu-frame <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> From fe90570d0ffab34ea977060d3612cf12ec3ee021 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Sep 2017 13:10:24 +0900 Subject: [PATCH 62/64] Lower inheritdoc code suggestions to hint level --- osu.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/osu.sln.DotSettings b/osu.sln.DotSettings index 8988908ee2..4011e3991f 100644 --- a/osu.sln.DotSettings +++ b/osu.sln.DotSettings @@ -42,6 +42,7 @@ WARNING WARNING ERROR + HINT HINT WARNING WARNING From 4f09f30b7a501d478173aad5091dd38932ef1526 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Sep 2017 13:13:54 +0900 Subject: [PATCH 63/64] Fix incorrect exception --- osu.Game/Screens/Play/SongProgressGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index dc4deaaefc..4455b97a7e 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -38,7 +38,7 @@ namespace osu.Game.Screens.Play { var endTime = Math.Max((h as IHasEndTime)?.EndTime ?? h.StartTime, h.StartTime); - Debug.Assert(endTime > h.StartTime); + Debug.Assert(endTime >= h.StartTime); int startRange = (int)((h.StartTime - firstHit) / interval); int endRange = (int)((endTime - firstHit) / interval); From d330b39db492a8b85b79a93e5ed1d6018db0b1bb Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 14 Sep 2017 13:42:58 +0900 Subject: [PATCH 64/64] Remove max --- osu.Game/Screens/Play/SongProgressGraph.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Screens/Play/SongProgressGraph.cs b/osu.Game/Screens/Play/SongProgressGraph.cs index 4455b97a7e..38c680902a 100644 --- a/osu.Game/Screens/Play/SongProgressGraph.cs +++ b/osu.Game/Screens/Play/SongProgressGraph.cs @@ -1,7 +1,6 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE -using System; using System.Linq; using System.Collections.Generic; using System.Diagnostics; @@ -36,7 +35,7 @@ namespace osu.Game.Screens.Play foreach (var h in objects) { - var endTime = Math.Max((h as IHasEndTime)?.EndTime ?? h.StartTime, h.StartTime); + var endTime = (h as IHasEndTime)?.EndTime ?? h.StartTime; Debug.Assert(endTime >= h.StartTime);