From 83b2b63d2c0bbb4d92e785777191331c0ef5ff2c Mon Sep 17 00:00:00 2001 From: Roman Kapustin Date: Thu, 6 Feb 2020 23:02:03 +0300 Subject: [PATCH 01/37] Make ScreenshotManager a Drawable --- osu.Game/Graphics/ScreenshotManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index 3ad36577b5..dc681102ce 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -9,7 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Audio; using osu.Framework.Audio.Sample; using osu.Framework.Bindables; -using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics; using osu.Framework.Input; using osu.Framework.Input.Bindings; using osu.Framework.Platform; @@ -22,7 +22,7 @@ using SixLabors.ImageSharp; namespace osu.Game.Graphics { - public class ScreenshotManager : Container, IKeyBindingHandler, IHandleGlobalKeyboardInput + public class ScreenshotManager : Drawable, IKeyBindingHandler, IHandleGlobalKeyboardInput { private readonly BindableBool cursorVisibility = new BindableBool(true); From 4495192c25ba78891aec846caedbbebe3fc48792 Mon Sep 17 00:00:00 2001 From: UselessToucan Date: Thu, 6 Feb 2020 23:22:30 +0300 Subject: [PATCH 02/37] Make ScreenshotManager a Component Co-Authored-By: Salman Ahmed --- osu.Game/Graphics/ScreenshotManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Graphics/ScreenshotManager.cs b/osu.Game/Graphics/ScreenshotManager.cs index dc681102ce..e21545688b 100644 --- a/osu.Game/Graphics/ScreenshotManager.cs +++ b/osu.Game/Graphics/ScreenshotManager.cs @@ -22,7 +22,7 @@ using SixLabors.ImageSharp; namespace osu.Game.Graphics { - public class ScreenshotManager : Drawable, IKeyBindingHandler, IHandleGlobalKeyboardInput + public class ScreenshotManager : Component, IKeyBindingHandler, IHandleGlobalKeyboardInput { private readonly BindableBool cursorVisibility = new BindableBool(true); From 7460018cd3775394d3eca84e282bb0b165633b41 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 14:58:07 +0900 Subject: [PATCH 03/37] Move combo colours to GlobalSkinColours --- .../TestSceneLegacyBeatmapSkin.cs | 2 +- .../Gameplay/TestSceneHitObjectAccentColour.cs | 4 ++-- .../Skins/TestSceneSkinConfigurationLookup.cs | 6 +++--- .../Objects/Drawables/DrawableHitObject.cs | 2 +- osu.Game/Screens/Menu/LogoVisualisation.cs | 2 +- osu.Game/Screens/Menu/MenuSideFlashes.cs | 2 +- osu.Game/Skinning/DefaultSkin.cs | 4 ++-- .../{GlobalSkinColour.cs => GlobalSkinColours.cs} | 3 ++- osu.Game/Skinning/GlobalSkinConfiguration.cs | 1 - osu.Game/Skinning/LegacySkin.cs | 15 +++++++++------ 10 files changed, 22 insertions(+), 19 deletions(-) rename osu.Game/Skinning/{GlobalSkinColour.cs => GlobalSkinColours.cs} (79%) diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs index bbb50c287b..3ff37c4147 100644 --- a/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs +++ b/osu.Game.Rulesets.Osu.Tests/TestSceneLegacyBeatmapSkin.cs @@ -89,7 +89,7 @@ namespace osu.Game.Rulesets.Osu.Tests public IReadOnlyList UsableComboColours => GameplayClockContainer.ChildrenOfType() .First() - .GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; + .GetConfig>(GlobalSkinColours.ComboColours)?.Value; } private class CustomSkinWorkingBeatmap : ClockBackedTestWorkingBeatmap diff --git a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs index c6d1f9da29..17dc27543d 100644 --- a/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs +++ b/osu.Game.Tests/Gameplay/TestSceneHitObjectAccentColour.cs @@ -126,10 +126,10 @@ namespace osu.Game.Tests.Gameplay { switch (lookup) { - case GlobalSkinConfiguration global: + case GlobalSkinColours global: switch (global) { - case GlobalSkinConfiguration.ComboColours: + case GlobalSkinColours.ComboColours: return SkinUtils.As(new Bindable>(ComboColours)); } diff --git a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs index ed54cc982d..35313ee858 100644 --- a/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs +++ b/osu.Game.Tests/Skins/TestSceneSkinConfigurationLookup.cs @@ -95,7 +95,7 @@ namespace osu.Game.Tests.Skins [Test] public void TestGlobalLookup() { - AddAssert("Check combo colours", () => requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.Count > 0); + AddAssert("Check combo colours", () => requester.GetConfig>(GlobalSkinColours.ComboColours)?.Value?.Count > 0); } [Test] @@ -121,7 +121,7 @@ namespace osu.Game.Tests.Skins public void TestEmptyComboColours() { AddAssert("Check retrieved combo colours is skin default colours", () => - requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(SkinConfiguration.DefaultComboColours) ?? false); + requester.GetConfig>(GlobalSkinColours.ComboColours)?.Value?.SequenceEqual(SkinConfiguration.DefaultComboColours) ?? false); } [Test] @@ -136,7 +136,7 @@ namespace osu.Game.Tests.Skins AddStep("Disallow default colours fallback in source2", () => source2.Configuration.AllowDefaultComboColoursFallback = false); AddAssert("Check retrieved combo colours from source1", () => - requester.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value?.SequenceEqual(source1.Configuration.ComboColours) ?? false); + requester.GetConfig>(GlobalSkinColours.ComboColours)?.Value?.SequenceEqual(source1.Configuration.ComboColours) ?? false); } [Test] diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs index 4ac30fe7fb..e391157b5b 100644 --- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs +++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs @@ -349,7 +349,7 @@ namespace osu.Game.Rulesets.Objects.Drawables { if (HitObject is IHasComboInformation combo) { - var comboColours = CurrentSkin.GetConfig>(GlobalSkinConfiguration.ComboColours)?.Value; + var comboColours = CurrentSkin.GetConfig>(GlobalSkinColours.ComboColours)?.Value; AccentColour.Value = comboColours?.Count > 0 ? comboColours[combo.ComboIndex % comboColours.Count] : Color4.White; } } diff --git a/osu.Game/Screens/Menu/LogoVisualisation.cs b/osu.Game/Screens/Menu/LogoVisualisation.cs index 8fc07f5989..06ca161fed 100644 --- a/osu.Game/Screens/Menu/LogoVisualisation.cs +++ b/osu.Game/Screens/Menu/LogoVisualisation.cs @@ -123,7 +123,7 @@ namespace osu.Game.Screens.Menu Color4 defaultColour = Color4.White.Opacity(0.2f); if (user.Value?.IsSupporter ?? false) - AccentColour = skin.Value.GetConfig(GlobalSkinColour.MenuGlow)?.Value ?? defaultColour; + AccentColour = skin.Value.GetConfig(GlobalSkinColours.MenuGlow)?.Value ?? defaultColour; else AccentColour = defaultColour; } diff --git a/osu.Game/Screens/Menu/MenuSideFlashes.cs b/osu.Game/Screens/Menu/MenuSideFlashes.cs index 3a88cda4ef..321381ac8d 100644 --- a/osu.Game/Screens/Menu/MenuSideFlashes.cs +++ b/osu.Game/Screens/Menu/MenuSideFlashes.cs @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Menu Color4 baseColour = colours.Blue; if (user.Value?.IsSupporter ?? false) - baseColour = skin.Value.GetConfig(GlobalSkinColour.MenuGlow)?.Value ?? baseColour; + baseColour = skin.Value.GetConfig(GlobalSkinColours.MenuGlow)?.Value ?? baseColour; // linear colour looks better in this case, so let's use it for now. Color4 gradientDark = baseColour.Opacity(0).ToLinear(); diff --git a/osu.Game/Skinning/DefaultSkin.cs b/osu.Game/Skinning/DefaultSkin.cs index 2a065ea3d7..6b4af21b37 100644 --- a/osu.Game/Skinning/DefaultSkin.cs +++ b/osu.Game/Skinning/DefaultSkin.cs @@ -31,10 +31,10 @@ namespace osu.Game.Skinning { // todo: this code is pulled from LegacySkin and should not exist. // will likely change based on how databased storage of skin configuration goes. - case GlobalSkinConfiguration global: + case GlobalSkinColours global: switch (global) { - case GlobalSkinConfiguration.ComboColours: + case GlobalSkinColours.ComboColours: return SkinUtils.As(new Bindable>(Configuration.ComboColours)); } diff --git a/osu.Game/Skinning/GlobalSkinColour.cs b/osu.Game/Skinning/GlobalSkinColours.cs similarity index 79% rename from osu.Game/Skinning/GlobalSkinColour.cs rename to osu.Game/Skinning/GlobalSkinColours.cs index d039be98ce..f889371b98 100644 --- a/osu.Game/Skinning/GlobalSkinColour.cs +++ b/osu.Game/Skinning/GlobalSkinColours.cs @@ -3,8 +3,9 @@ namespace osu.Game.Skinning { - public enum GlobalSkinColour + public enum GlobalSkinColours { + ComboColours, MenuGlow } } diff --git a/osu.Game/Skinning/GlobalSkinConfiguration.cs b/osu.Game/Skinning/GlobalSkinConfiguration.cs index 66dc9a9395..0532e64546 100644 --- a/osu.Game/Skinning/GlobalSkinConfiguration.cs +++ b/osu.Game/Skinning/GlobalSkinConfiguration.cs @@ -5,6 +5,5 @@ namespace osu.Game.Skinning { public enum GlobalSkinConfiguration { - ComboColours } } diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 671d37fda4..609fb79d9a 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -68,22 +69,22 @@ namespace osu.Game.Skinning { switch (lookup) { - case GlobalSkinConfiguration global: - switch (global) + case GlobalSkinColours colour: + switch (colour) { - case GlobalSkinConfiguration.ComboColours: + case GlobalSkinColours.ComboColours: var comboColours = Configuration.ComboColours; if (comboColours != null) return SkinUtils.As(new Bindable>(comboColours)); break; + + default: + return SkinUtils.As(getCustomColour(colour.ToString())); } break; - case GlobalSkinColour colour: - return SkinUtils.As(getCustomColour(colour.ToString())); - case LegacySkinConfiguration.LegacySetting legacy: switch (legacy) { @@ -100,6 +101,8 @@ namespace osu.Game.Skinning return SkinUtils.As(getCustomColour(customColour.Lookup.ToString())); default: + // handles lookups like GlobalSkinConfiguration + try { if (Configuration.ConfigDictionary.TryGetValue(lookup.ToString(), out var val)) From 544685be4863631b47df94f19d4f6307cb014d71 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 14:58:29 +0900 Subject: [PATCH 04/37] Add support for reading skin frame rate from configuration file --- .../Skinning/OsuLegacySkinTransformer.cs | 9 ++- osu.Game/Skinning/GlobalSkinConfiguration.cs | 1 + osu.Game/Skinning/LegacySkinExtensions.cs | 72 +++++++++++-------- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs index 266b619334..d6c3f443eb 100644 --- a/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs +++ b/osu.Game.Rulesets.Osu/Skinning/OsuLegacySkinTransformer.cs @@ -46,17 +46,20 @@ namespace osu.Game.Rulesets.Osu.Skinning switch (osuComponent.Component) { case OsuSkinComponents.FollowPoint: - return this.GetAnimation(component.LookupName, true, false); + return this.GetAnimation(component.LookupName, true, false, true); case OsuSkinComponents.SliderFollowCircle: - var followCircle = this.GetAnimation("sliderfollowcircle", true, true); + var followCircle = this.GetAnimation("sliderfollowcircle", true, true, true); if (followCircle != null) // follow circles are 2x the hitcircle resolution in legacy skins (since they are scaled down from >1x followCircle.Scale *= 0.5f; return followCircle; case OsuSkinComponents.SliderBall: - var sliderBallContent = this.GetAnimation("sliderb", true, true, ""); + var sliderBallContent = this.GetAnimation("sliderb", true, true, animationSeparator: ""); + + // todo: slider ball has a custom frame delay based on velocity + // Math.Max((150 / Velocity) * GameBase.SIXTY_FRAME_TIME, GameBase.SIXTY_FRAME_TIME); if (sliderBallContent != null) { diff --git a/osu.Game/Skinning/GlobalSkinConfiguration.cs b/osu.Game/Skinning/GlobalSkinConfiguration.cs index 0532e64546..8774fe5a97 100644 --- a/osu.Game/Skinning/GlobalSkinConfiguration.cs +++ b/osu.Game/Skinning/GlobalSkinConfiguration.cs @@ -5,5 +5,6 @@ namespace osu.Game.Skinning { public enum GlobalSkinConfiguration { + AnimationFramerate } } diff --git a/osu.Game/Skinning/LegacySkinExtensions.cs b/osu.Game/Skinning/LegacySkinExtensions.cs index c758b699ed..fa4de21eec 100644 --- a/osu.Game/Skinning/LegacySkinExtensions.cs +++ b/osu.Game/Skinning/LegacySkinExtensions.cs @@ -1,6 +1,8 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System.Collections.Generic; +using System.Linq; using osu.Framework.Graphics; using osu.Framework.Graphics.Animations; using osu.Framework.Graphics.Sprites; @@ -10,48 +12,62 @@ namespace osu.Game.Skinning { public static class LegacySkinExtensions { - public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, string animationSeparator = "-") + public static Drawable GetAnimation(this ISkin source, string componentName, bool animatable, bool looping, bool applyConfigFrameRate = false, string animationSeparator = "-") { - const double default_frame_time = 1000 / 60d; - Texture texture; - Texture getFrameTexture(int frame) => source.GetTexture($"{componentName}{animationSeparator}{frame}"); - - TextureAnimation animation = null; - if (animatable) { - for (int i = 0; true; i++) + var textures = getTextures().ToArray(); + + if (textures.Length > 0) { - if ((texture = getFrameTexture(i)) == null) - break; - - if (animation == null) + var animation = new TextureAnimation { - animation = new TextureAnimation - { - DefaultFrameLength = default_frame_time, - Repeat = looping - }; - } + DefaultFrameLength = getFrameLength(source, applyConfigFrameRate, textures), + Repeat = looping, + }; - animation.AddFrame(texture); + foreach (var t in textures) + animation.AddFrame(t); + + return animation; } } - if (animation != null) - return animation; - + // if an animation was not allowed or not found, fall back to a sprite retrieval. if ((texture = source.GetTexture(componentName)) != null) - { - return new Sprite - { - Texture = texture - }; - } + return new Sprite { Texture = texture }; return null; + + IEnumerable getTextures() + { + for (int i = 0; true; i++) + { + if ((texture = source.GetTexture($"{componentName}{animationSeparator}{i}")) == null) + break; + + yield return texture; + } + } + } + + private const double default_frame_time = 1000 / 60d; + + private static double getFrameLength(ISkin source, bool applyConfigFrameRate, Texture[] textures) + { + if (applyConfigFrameRate) + { + var iniRate = source.GetConfig(GlobalSkinConfiguration.AnimationFramerate); + + if (iniRate != null) + return 1000f / iniRate.Value; + + return 1000f / textures.Length; + } + + return default_frame_time; } } } From 9181bb41c621c217c187535e9d899a7d8a76258d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 15:11:09 +0900 Subject: [PATCH 05/37] Remove unused using --- osu.Game/Skinning/LegacySkin.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game/Skinning/LegacySkin.cs b/osu.Game/Skinning/LegacySkin.cs index 609fb79d9a..94611317d5 100644 --- a/osu.Game/Skinning/LegacySkin.cs +++ b/osu.Game/Skinning/LegacySkin.cs @@ -1,7 +1,6 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Collections.Generic; using System.IO; using System.Linq; From 9997ae17bc17dc45cd790e151c416786a727f6e6 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 16:42:56 +0900 Subject: [PATCH 06/37] Fix editor test scene exiting after loading --- osu.Game/Tests/Visual/EditorTestScene.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/osu.Game/Tests/Visual/EditorTestScene.cs b/osu.Game/Tests/Visual/EditorTestScene.cs index 75bbb3e110..80bc3bdb87 100644 --- a/osu.Game/Tests/Visual/EditorTestScene.cs +++ b/osu.Game/Tests/Visual/EditorTestScene.cs @@ -24,8 +24,13 @@ namespace osu.Game.Tests.Visual private void load() { Beatmap.Value = CreateWorkingBeatmap(ruleset.RulesetInfo); + } - LoadScreen(new Editor()); + public override void SetUpSteps() + { + base.SetUpSteps(); + + AddStep("Load editor", () => LoadScreen(new Editor())); } } } From b7996f91fc0849f767a9251be2763f81fdca8e60 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 17:51:38 +0900 Subject: [PATCH 07/37] Update the windows platform offset to match stable --- osu.Game/Screens/Play/GameplayClockContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/GameplayClockContainer.cs b/osu.Game/Screens/Play/GameplayClockContainer.cs index 9f46fddc5e..1c061c215b 100644 --- a/osu.Game/Screens/Play/GameplayClockContainer.cs +++ b/osu.Game/Screens/Play/GameplayClockContainer.cs @@ -78,7 +78,7 @@ namespace osu.Game.Screens.Play // Lazer's audio timings in general doesn't match stable. This is the result of user testing, albeit limited. // This only seems to be required on windows. We need to eventually figure out why, with a bit of luck. - platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 22 : 0 }; + platformOffsetClock = new FramedOffsetClock(adjustableClock) { Offset = RuntimeInfo.OS == RuntimeInfo.Platform.Windows ? 15 : 0 }; // the final usable gameplay clock with user-set offsets applied. userOffsetClock = new FramedOffsetClock(platformOffsetClock); From e31d69c7497b666aec2b3f982cd4d18a10df1e89 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 18:02:48 +0900 Subject: [PATCH 08/37] Add commit status to EndPlacement; call BeginPlacement on initial movement --- .../Edit/Blueprints/ManiaPlacementBlueprint.cs | 2 +- .../Blueprints/HitCircles/HitCirclePlacementBlueprint.cs | 3 ++- .../Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs | 3 ++- .../Blueprints/Spinners/SpinnerPlacementBlueprint.cs | 2 +- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 9 ++++++--- osu.Game/Rulesets/Edit/PlacementBlueprint.cs | 5 +++-- .../Edit/Compose/Components/ComposeBlueprintContainer.cs | 2 ++ osu.Game/Screens/Edit/Compose/IPlacementHandler.cs | 3 ++- osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs | 5 +++-- 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs index 7a3b42914e..362d6d40a8 100644 --- a/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Mania/Edit/Blueprints/ManiaPlacementBlueprint.cs @@ -56,7 +56,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints protected override void OnMouseUp(MouseUpEvent e) { - EndPlacement(); + EndPlacement(true); base.OnMouseUp(e); } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs index bb47c7e464..407f5f540e 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/HitCircles/HitCirclePlacementBlueprint.cs @@ -30,12 +30,13 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.HitCircles protected override bool OnClick(ClickEvent e) { - EndPlacement(); + EndPlacement(true); return true; } public override void UpdatePosition(Vector2 screenSpacePosition) { + BeginPlacement(); HitObject.Position = ToLocalSpace(screenSpacePosition); } } diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs index 90512849d4..75d05b9b6c 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Sliders/SliderPlacementBlueprint.cs @@ -68,6 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders switch (state) { case PlacementState.Initial: + BeginPlacement(); HitObject.Position = ToLocalSpace(screenSpacePosition); break; @@ -132,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders private void endCurve() { updateSlider(); - EndPlacement(); + EndPlacement(true); } protected override void Update() diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 5525b8936e..8dc3cb0855 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners if (isPlacingEnd) { HitObject.EndTime = EditorClock.CurrentTime; - EndPlacement(); + EndPlacement(true); } else { diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index e181e1f431..e3f2fa915a 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -254,11 +254,14 @@ namespace osu.Game.Rulesets.Edit hitObject.StartTime = GetSnappedPosition(distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position), hitObject.StartTime).time; } - public void EndPlacement(HitObject hitObject) + public void EndPlacement(HitObject hitObject, bool commit) { - EditorBeatmap.Add(hitObject); + if (commit) + { + EditorBeatmap.Add(hitObject); - adjustableClock.Seek(hitObject.StartTime); + adjustableClock.Seek(hitObject.StartTime); + } showGridFor(Enumerable.Empty()); } diff --git a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs index 07283d2245..24fa96e1c5 100644 --- a/osu.Game/Rulesets/Edit/PlacementBlueprint.cs +++ b/osu.Game/Rulesets/Edit/PlacementBlueprint.cs @@ -103,11 +103,12 @@ namespace osu.Game.Rulesets.Edit /// Signals that the placement of has finished. /// This will destroy this , and add the to the . /// - protected void EndPlacement() + /// Whether the object should be committed. + public void EndPlacement(bool commit) { if (!PlacementBegun) BeginPlacement(); - placementHandler.EndPlacement(HitObject); + placementHandler.EndPlacement(HitObject, commit); } /// diff --git a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs index 3c41dead5d..b257688568 100644 --- a/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/ComposeBlueprintContainer.cs @@ -63,6 +63,8 @@ namespace osu.Game.Screens.Edit.Compose.Components private void refreshTool() { placementBlueprintContainer.Clear(); + + currentPlacement?.EndPlacement(false); currentPlacement = null; var blueprint = CurrentTool?.CreatePlacementBlueprint(); diff --git a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs index 47a4277430..aefcbc6542 100644 --- a/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs +++ b/osu.Game/Screens/Edit/Compose/IPlacementHandler.cs @@ -17,7 +17,8 @@ namespace osu.Game.Screens.Edit.Compose /// Notifies that a placement has finished. /// /// The that has been placed. - void EndPlacement(HitObject hitObject); + /// Whether the object should be committed. + void EndPlacement(HitObject hitObject, bool commit); /// /// Deletes a . diff --git a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs index 0688620b8e..ce95dfa62f 100644 --- a/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs +++ b/osu.Game/Tests/Visual/PlacementBlueprintTestScene.cs @@ -53,9 +53,10 @@ namespace osu.Game.Tests.Visual { } - public void EndPlacement(HitObject hitObject) + public void EndPlacement(HitObject hitObject, bool commit) { - AddHitObject(CreateHitObject(hitObject)); + if (commit) + AddHitObject(CreateHitObject(hitObject)); Remove(currentBlueprint); Add(currentBlueprint = CreateBlueprint()); From e08437c5dc34ec3bec18e81d5556e83c1fb56727 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 18:03:14 +0900 Subject: [PATCH 09/37] Track placement object in EditorBeatmap --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 4 ++++ osu.Game/Screens/Edit/EditorBeatmap.cs | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index e3f2fa915a..d946b2eb7f 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -250,12 +250,16 @@ namespace osu.Game.Rulesets.Edit public void BeginPlacement(HitObject hitObject) { + EditorBeatmap.PlacementObject.Value = hitObject; + if (distanceSnapGrid != null) hitObject.StartTime = GetSnappedPosition(distanceSnapGrid.ToLocalSpace(inputManager.CurrentState.Mouse.Position), hitObject.StartTime).time; } public void EndPlacement(HitObject hitObject, bool commit) { + EditorBeatmap.PlacementObject.Value = null; + if (commit) { EditorBeatmap.Add(hitObject); diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index cacb539891..e1f3ddf191 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -33,7 +33,15 @@ namespace osu.Game.Screens.Edit /// public event Action StartTimeChanged; - public BindableList SelectedHitObjects { get; } = new BindableList(); + /// + /// All currently selected s. + /// + public readonly BindableList SelectedHitObjects = new BindableList(); + + /// + /// The current placement + /// + public readonly Bindable PlacementObject = new Bindable(); public readonly IBeatmap PlayableBeatmap; From 56a091674b31fbe80d9ff08b704cfe8cd2fd7850 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 18:04:10 +0900 Subject: [PATCH 10/37] Add placement display to timeline --- .../Compose/Components/BlueprintContainer.cs | 24 +++++++------- .../Timeline/TimelineBlueprintContainer.cs | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 675b2b648d..55b2b801e7 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected DragBox DragBox { get; private set; } - private Container selectionBlueprints; + protected Container SelectionBlueprints; private SelectionHandler selectionHandler; @@ -62,7 +62,7 @@ namespace osu.Game.Screens.Edit.Compose.Components { DragBox = CreateDragBox(select), selectionHandler, - selectionBlueprints = CreateSelectionBlueprintContainer(), + SelectionBlueprints = CreateSelectionBlueprintContainer(), DragBox.CreateProxy().With(p => p.Depth = float.MinValue) }); @@ -73,7 +73,7 @@ namespace osu.Game.Screens.Edit.Compose.Components selectedHitObjects.ItemsAdded += objects => { foreach (var o in objects) - selectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Select(); + SelectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Select(); SelectionChanged?.Invoke(selectedHitObjects); }; @@ -81,7 +81,7 @@ namespace osu.Game.Screens.Edit.Compose.Components selectedHitObjects.ItemsRemoved += objects => { foreach (var o in objects) - selectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Deselect(); + SelectionBlueprints.FirstOrDefault(b => b.HitObject == o)?.Deselect(); SelectionChanged?.Invoke(selectedHitObjects); }; @@ -230,7 +230,7 @@ namespace osu.Game.Screens.Edit.Compose.Components private void removeBlueprintFor(HitObject hitObject) { - var blueprint = selectionBlueprints.SingleOrDefault(m => m.HitObject == hitObject); + var blueprint = SelectionBlueprints.SingleOrDefault(m => m.HitObject == hitObject); if (blueprint == null) return; @@ -239,7 +239,7 @@ namespace osu.Game.Screens.Edit.Compose.Components blueprint.Selected -= onBlueprintSelected; blueprint.Deselected -= onBlueprintDeselected; - selectionBlueprints.Remove(blueprint); + SelectionBlueprints.Remove(blueprint); } protected virtual void AddBlueprintFor(HitObject hitObject) @@ -251,7 +251,7 @@ namespace osu.Game.Screens.Edit.Compose.Components blueprint.Selected += onBlueprintSelected; blueprint.Deselected += onBlueprintDeselected; - selectionBlueprints.Add(blueprint); + SelectionBlueprints.Add(blueprint); } #endregion @@ -278,7 +278,7 @@ namespace osu.Game.Screens.Edit.Compose.Components if (!allowDeselection && selectionHandler.SelectedBlueprints.Any(s => s.IsHovered)) return; - foreach (SelectionBlueprint blueprint in selectionBlueprints.AliveChildren) + foreach (SelectionBlueprint blueprint in SelectionBlueprints.AliveChildren) { if (blueprint.IsHovered) { @@ -308,7 +308,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// The rectangle to perform a selection on in screen-space coordinates. private void select(RectangleF rect) { - foreach (var blueprint in selectionBlueprints) + foreach (var blueprint in SelectionBlueprints) { if (blueprint.IsAlive && blueprint.IsPresent && rect.Contains(blueprint.SelectionPoint)) blueprint.Select(); @@ -322,7 +322,7 @@ namespace osu.Game.Screens.Edit.Compose.Components /// private void selectAll() { - selectionBlueprints.ToList().ForEach(m => m.Select()); + SelectionBlueprints.ToList().ForEach(m => m.Select()); selectionHandler.UpdateVisibility(); } @@ -334,14 +334,14 @@ namespace osu.Game.Screens.Edit.Compose.Components private void onBlueprintSelected(SelectionBlueprint blueprint) { selectionHandler.HandleSelected(blueprint); - selectionBlueprints.ChangeChildDepth(blueprint, 1); + SelectionBlueprints.ChangeChildDepth(blueprint, 1); beatmap.SelectedHitObjects.Add(blueprint.HitObject); } private void onBlueprintDeselected(SelectionBlueprint blueprint) { selectionHandler.HandleDeselected(blueprint); - selectionBlueprints.ChangeChildDepth(blueprint, 0); + SelectionBlueprints.ChangeChildDepth(blueprint, 0); beatmap.SelectedHitObjects.Remove(blueprint.HitObject); } diff --git a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs index 9f3d776e5c..84328466c3 100644 --- a/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/Timeline/TimelineBlueprintContainer.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Primitives; @@ -21,8 +22,15 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline [Resolved(CanBeNull = true)] private Timeline timeline { get; set; } + [Resolved] + private EditorBeatmap beatmap { get; set; } + private DragEvent lastDragEvent; + private Bindable placement; + + private SelectionBlueprint placementBlueprint; + public TimelineBlueprintContainer() { RelativeSizeAxes = Axes.Both; @@ -43,6 +51,29 @@ namespace osu.Game.Screens.Edit.Compose.Components.Timeline { base.LoadComplete(); DragBox.Alpha = 0; + + placement = beatmap.PlacementObject.GetBoundCopy(); + placement.ValueChanged += placementChanged; + } + + private void placementChanged(ValueChangedEvent obj) + { + if (obj.NewValue == null) + { + if (placementBlueprint != null) + { + SelectionBlueprints.Remove(placementBlueprint); + placementBlueprint = null; + } + } + else + { + placementBlueprint = CreateBlueprintFor(obj.NewValue); + + placementBlueprint.Colour = Color4.MediumPurple; + + SelectionBlueprints.Add(placementBlueprint); + } } protected override Container CreateSelectionBlueprintContainer() => new TimelineSelectionBlueprintContainer { RelativeSizeAxes = Axes.Both }; From 2082948f9a4f1ee2573e4217b78068f561da0766 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 18:23:59 +0900 Subject: [PATCH 11/37] Make editor screens display below timeline --- .../Screens/Edit/EditorScreenWithTimeline.cs | 86 +++++++++---------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs index 7ee1005add..e9ff0b5598 100644 --- a/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs +++ b/osu.Game/Screens/Edit/EditorScreenWithTimeline.cs @@ -18,6 +18,8 @@ namespace osu.Game.Screens.Edit private const float vertical_margins = 10; private const float horizontal_margins = 20; + private const float timeline_height = 110; + private readonly BindableBeatDivisor beatDivisor = new BindableBeatDivisor(); private Container timelineContainer; @@ -32,65 +34,57 @@ namespace osu.Game.Screens.Edit Children = new Drawable[] { - new GridContainer + mainContent = new Container { + Name = "Main content", RelativeSizeAxes = Axes.Both, - Content = new[] + Padding = new MarginPadding { - new Drawable[] + Horizontal = horizontal_margins, + Top = vertical_margins + timeline_height, + Bottom = vertical_margins + }, + }, + new Container + { + Name = "Timeline", + RelativeSizeAxes = Axes.X, + Height = timeline_height, + Children = new Drawable[] + { + new Box { - new Container + RelativeSizeAxes = Axes.Both, + Colour = Color4.Black.Opacity(0.5f) + }, + new Container + { + Name = "Timeline content", + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, + Child = new GridContainer { - Name = "Timeline", RelativeSizeAxes = Axes.Both, - Children = new Drawable[] + Content = new[] { - new Box + new Drawable[] { - RelativeSizeAxes = Axes.Both, - Colour = Color4.Black.Opacity(0.5f) - }, - new Container - { - Name = "Timeline content", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, - Child = new GridContainer + timelineContainer = new Container { RelativeSizeAxes = Axes.Both, - Content = new[] - { - new Drawable[] - { - timelineContainer = new Container - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Right = 5 }, - }, - new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } - }, - }, - ColumnDimensions = new[] - { - new Dimension(), - new Dimension(GridSizeMode.Absolute, 90), - } + Padding = new MarginPadding { Right = 5 }, }, - } + new BeatDivisorControl(beatDivisor) { RelativeSizeAxes = Axes.Both } + }, + }, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension(GridSizeMode.Absolute, 90), } - } - }, - new Drawable[] - { - mainContent = new Container - { - Name = "Main content", - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Horizontal = horizontal_margins, Vertical = vertical_margins }, - } + }, } - }, - RowDimensions = new[] { new Dimension(GridSizeMode.Absolute, 110) } + } }, }; From 6297606baaec8865d2201647746bb379c0e37ac9 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 19:08:37 +0900 Subject: [PATCH 12/37] Make sMake spinner's EndTime correct on construction --- osu.Game.Rulesets.Osu/Objects/Spinner.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Objects/Spinner.cs b/osu.Game.Rulesets.Osu/Objects/Spinner.cs index 2441a1449d..0b8d03d118 100644 --- a/osu.Game.Rulesets.Osu/Objects/Spinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Spinner.cs @@ -13,8 +13,13 @@ namespace osu.Game.Rulesets.Osu.Objects { public class Spinner : OsuHitObject, IHasEndTime { - public double EndTime { get; set; } - public double Duration => EndTime - StartTime; + public double EndTime + { + get => StartTime + Duration; + set => Duration = value - StartTime; + } + + public double Duration { get; set; } /// /// Number of spins required to finish the spinner without miss. From a6531bf73e06504636f38d336aa397669cc41069 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 19:08:49 +0900 Subject: [PATCH 13/37] Don't show distance snap grid for spinners (for now) --- osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs | 6 ++++++ osu.Game/Rulesets/Edit/HitObjectComposer.cs | 11 ++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs index b01488e7c2..cdf78a5902 100644 --- a/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs +++ b/osu.Game.Rulesets.Osu/Edit/OsuHitObjectComposer.cs @@ -36,6 +36,9 @@ namespace osu.Game.Rulesets.Osu.Edit protected override DistanceSnapGrid CreateDistanceSnapGrid(IEnumerable selectedHitObjects) { + if (BlueprintContainer.CurrentTool is SpinnerCompositionTool) + return null; + var objects = selectedHitObjects.ToList(); if (objects.Count == 0) @@ -89,6 +92,9 @@ namespace osu.Game.Rulesets.Osu.Edit targetIndex++; } + if (sourceObject is Spinner) + return null; + return new OsuDistanceSnapGrid((OsuHitObject)sourceObject, (OsuHitObject)targetObject); } } diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index e181e1f431..7b7c154191 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -49,8 +49,9 @@ namespace osu.Game.Rulesets.Edit [Resolved] private IBeatSnapProvider beatSnapProvider { get; set; } + protected ComposeBlueprintContainer BlueprintContainer; + private DrawableEditRulesetWrapper drawableRulesetWrapper; - private ComposeBlueprintContainer blueprintContainer; private Container distanceSnapGridContainer; private DistanceSnapGrid distanceSnapGrid; private readonly List layerContainers = new List(); @@ -94,7 +95,7 @@ namespace osu.Game.Rulesets.Edit new EditorPlayfieldBorder { RelativeSizeAxes = Axes.Both } }); - var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(blueprintContainer = CreateBlueprintContainer()); + var layerAboveRuleset = drawableRulesetWrapper.CreatePlayfieldAdjustmentContainer().WithChild(BlueprintContainer = CreateBlueprintContainer()); layerContainers.Add(layerBelowRuleset); layerContainers.Add(layerAboveRuleset); @@ -142,7 +143,7 @@ namespace osu.Game.Rulesets.Edit setSelectTool(); - blueprintContainer.SelectionChanged += selectionChanged; + BlueprintContainer.SelectionChanged += selectionChanged; } protected override bool OnKeyDown(KeyDownEvent e) @@ -174,7 +175,7 @@ namespace osu.Game.Rulesets.Edit { base.Update(); - if (EditorClock.CurrentTime != lastGridUpdateTime && !(blueprintContainer.CurrentTool is SelectTool)) + if (EditorClock.CurrentTime != lastGridUpdateTime && !(BlueprintContainer.CurrentTool is SelectTool)) showGridFor(Enumerable.Empty()); } @@ -210,7 +211,7 @@ namespace osu.Game.Rulesets.Edit private void toolSelected(HitObjectCompositionTool tool) { - blueprintContainer.CurrentTool = tool; + BlueprintContainer.CurrentTool = tool; if (tool is SelectTool) distanceSnapGridContainer.Hide(); From 830afe52096961bde1f33201f63e376c654811ce Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Fri, 7 Feb 2020 19:09:47 +0900 Subject: [PATCH 14/37] Make spinner blueprint update values more frequently. Also handle right-click --- .../Spinners/SpinnerPlacementBlueprint.cs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 5525b8936e..6d881d5f71 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -1,13 +1,14 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. -using osu.Framework.Graphics; +using System; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.UI; using osuTK; +using osuTK.Input; namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners { @@ -29,22 +30,29 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners { base.Update(); + if (isPlacingEnd) + HitObject.EndTime = Math.Max(HitObject.StartTime, EditorClock.CurrentTime); + piece.UpdateFrom(HitObject); } - protected override bool OnClick(ClickEvent e) + protected override bool OnMouseDown(MouseDownEvent e) { if (isPlacingEnd) { + if (e.Button != MouseButton.Right) + return false; + HitObject.EndTime = EditorClock.CurrentTime; EndPlacement(); } else { - isPlacingEnd = true; - piece.FadeTo(1f, 150, Easing.OutQuint); + if (e.Button != MouseButton.Left) + return false; BeginPlacement(); + isPlacingEnd = true; } return true; From 2d1afb66fb2d9c86b7bae7b930ee65710fe5508b Mon Sep 17 00:00:00 2001 From: Andrei Zavatski Date: Fri, 7 Feb 2020 16:21:47 +0300 Subject: [PATCH 15/37] Add history counts to user api --- osu.Game/Users/User.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/osu.Game/Users/User.cs b/osu.Game/Users/User.cs index 5d0ffd5a67..c573fdd089 100644 --- a/osu.Game/Users/User.cs +++ b/osu.Game/Users/User.cs @@ -203,6 +203,21 @@ namespace osu.Game.Users public int ID; } + [JsonProperty("monthly_playcounts")] + public UserHistoryCount[] MonthlyPlaycounts; + + [JsonProperty("replays_watched_counts")] + public UserHistoryCount[] ReplaysWatchedCounts; + + public class UserHistoryCount + { + [JsonProperty("start_date")] + public DateTime Date; + + [JsonProperty("count")] + public long Count; + } + public override string ToString() => Username; /// From 678eb8ec3128a3ef0dd839b852041c72bd0947ee Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 Feb 2020 00:12:23 +0900 Subject: [PATCH 16/37] Reduce accessibility to set Co-Authored-By: Dan Balasescu --- osu.Game/Rulesets/Edit/HitObjectComposer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Rulesets/Edit/HitObjectComposer.cs b/osu.Game/Rulesets/Edit/HitObjectComposer.cs index 7b7c154191..f6c73d5e4c 100644 --- a/osu.Game/Rulesets/Edit/HitObjectComposer.cs +++ b/osu.Game/Rulesets/Edit/HitObjectComposer.cs @@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.Edit [Resolved] private IBeatSnapProvider beatSnapProvider { get; set; } - protected ComposeBlueprintContainer BlueprintContainer; + protected ComposeBlueprintContainer BlueprintContainer { get; private set; } private DrawableEditRulesetWrapper drawableRulesetWrapper; private Container distanceSnapGridContainer; From 51edd8827772898e6e5ece224e4507cdeb182dac Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 8 Feb 2020 00:28:52 +0900 Subject: [PATCH 17/37] Add back fade --- .../Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs index 6d881d5f71..48c1ce11e0 100644 --- a/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs +++ b/osu.Game.Rulesets.Osu/Edit/Blueprints/Spinners/SpinnerPlacementBlueprint.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Graphics; using osu.Framework.Input.Events; using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners.Components; @@ -52,6 +53,8 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Spinners return false; BeginPlacement(); + piece.FadeTo(1f, 150, Easing.OutQuint); + isPlacingEnd = true; } From 59cf2037d062b7af68e7ea912a5a5715d1016d5a Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Fri, 7 Feb 2020 21:11:58 +0100 Subject: [PATCH 18/37] Introduce SortedStatistics --- osu.Game/Scoring/ScoreInfo.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index bed9104cad..a40f436a6e 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -151,6 +151,8 @@ namespace osu.Game.Scoring [JsonProperty("statistics")] public Dictionary Statistics = new Dictionary(); + public IOrderedEnumerable> SortedStatistics => Statistics.OrderByDescending(pair => pair.Key); + [JsonIgnore] [Column("Statistics")] public string StatisticsJson From 2770fb71b251fa315be1af4a83b1993ba5838e55 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Fri, 7 Feb 2020 21:12:21 +0100 Subject: [PATCH 19/37] Use SortedStatistics where needed --- osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs | 4 ++-- .../Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs | 4 +--- osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs index 7a17412722..758140a12d 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoreTable.cs @@ -82,7 +82,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores new TableColumn("max combo", Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 70, maxSize: 90)) }; - foreach (var statistic in score.Statistics) + foreach (var statistic in score.SortedStatistics) columns.Add(new TableColumn(statistic.Key.GetDescription(), Anchor.CentreLeft, new Dimension(GridSizeMode.Distributed, minSize: 50, maxSize: 70))); columns.AddRange(new[] @@ -150,7 +150,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores } }); - foreach (var kvp in score.Statistics) + foreach (var kvp in score.SortedStatistics) { content.Add(new OsuSpriteText { diff --git a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs index 8a17fef367..6c9f0b0321 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/TopScoreStatisticsSection.cs @@ -99,9 +99,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores maxComboColumn.Text = $@"{value.MaxCombo:N0}x"; ppColumn.Text = $@"{value.PP:N0}"; - statisticsColumns.ChildrenEnumerable = value.Statistics - .OrderByDescending(pair => pair.Key) - .Select(kvp => createStatisticsColumn(kvp.Key, kvp.Value)); + statisticsColumns.ChildrenEnumerable = value.SortedStatistics.Select(kvp => createStatisticsColumn(kvp.Key, kvp.Value)); modsColumn.Mods = value.Mods; } } diff --git a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs index 43234c0b29..0aab067de1 100644 --- a/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs +++ b/osu.Game/Screens/Ranking/Pages/ScoreResultsPage.cs @@ -188,7 +188,7 @@ namespace osu.Game.Screens.Ranking.Pages }, }; - statisticsContainer.ChildrenEnumerable = Score.Statistics.OrderByDescending(p => p.Key).Select(s => new DrawableScoreStatistic(s)); + statisticsContainer.ChildrenEnumerable = Score.SortedStatistics.Select(s => new DrawableScoreStatistic(s)); } protected override void LoadComplete() From 1ba8cc904a5b72693bad9f5309be5f4ae5f095fd Mon Sep 17 00:00:00 2001 From: jorolf Date: Fri, 7 Feb 2020 21:42:47 +0100 Subject: [PATCH 20/37] Make the caret blink to the beat --- osu.Game/Graphics/UserInterface/OsuTextBox.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index f5b7bc3073..36740fb015 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Audio.Track; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; @@ -9,6 +10,9 @@ using osu.Game.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Input.Events; +using osu.Game.Beatmaps.ControlPoints; +using osu.Game.Graphics.Containers; +using osuTK; namespace osu.Game.Graphics.UserInterface { @@ -59,5 +63,47 @@ namespace osu.Game.Graphics.UserInterface } protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }; + + protected override Caret CreateCaret() => new BeatCaret + { + CaretWidth = CaretWidth, + SelectionColour = SelectionColour, + }; + + private class BeatCaret : BasicCaret + { + private bool hasSelection; + + public BeatCaret() + { + AddInternal(new CaretBeatSyncedContainer(this)); + } + + public override void DisplayAt(Vector2 position, float? selectionWidth) + { + base.DisplayAt(position, selectionWidth); + + hasSelection = selectionWidth != null; + if (selectionWidth == null) + ClearTransforms(targetMember: nameof(Alpha)); + } + + private class CaretBeatSyncedContainer : BeatSyncedContainer + { + private readonly BeatCaret caret; + + public CaretBeatSyncedContainer(BeatCaret caret) + { + this.caret = caret; + MinimumBeatLength = 300; + } + + protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) + { + if (!caret.hasSelection) + caret.FadeTo(0.7f).FadeTo(0.4f, timingPoint.BeatLength, Easing.InOutSine); + } + } + } } } From 8c10d31af947d8ace2265952bfa2bbbea62e2d43 Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Fri, 7 Feb 2020 22:09:45 +0100 Subject: [PATCH 21/37] Make accuracy formatting more consistent --- osu.Game/Utils/FormatUtils.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Utils/FormatUtils.cs b/osu.Game/Utils/FormatUtils.cs index b3758b3375..f2ab99f4b7 100644 --- a/osu.Game/Utils/FormatUtils.cs +++ b/osu.Game/Utils/FormatUtils.cs @@ -7,18 +7,16 @@ namespace osu.Game.Utils { /// /// Turns the provided accuracy into a percentage with 2 decimal places. - /// Omits all decimal places when equals 1d. /// /// The accuracy to be formatted /// formatted accuracy in percentage - public static string FormatAccuracy(this double accuracy) => accuracy == 1 ? "100%" : $"{accuracy:0.00%}"; + public static string FormatAccuracy(this double accuracy) => $"{accuracy:0.00%}"; /// /// Turns the provided accuracy into a percentage with 2 decimal places. - /// Omits all decimal places when equals 100m. /// /// The accuracy to be formatted /// formatted accuracy in percentage - public static string FormatAccuracy(this decimal accuracy) => accuracy == 100 ? "100%" : $"{accuracy:0.00}%"; + public static string FormatAccuracy(this decimal accuracy) => $"{accuracy:0.00}%"; } } From 393b566966c5cd8d6be9b765ebd79e8e9280f1fd Mon Sep 17 00:00:00 2001 From: TheWildTree Date: Fri, 7 Feb 2020 22:16:06 +0100 Subject: [PATCH 22/37] Make PercentageCounter use FormatAccuracy --- osu.Game/Graphics/UserInterface/PercentageCounter.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/PercentageCounter.cs b/osu.Game/Graphics/UserInterface/PercentageCounter.cs index 064c663d59..940c9808ce 100644 --- a/osu.Game/Graphics/UserInterface/PercentageCounter.cs +++ b/osu.Game/Graphics/UserInterface/PercentageCounter.cs @@ -3,6 +3,7 @@ using System; using osu.Framework.Allocation; +using osu.Game.Utils; namespace osu.Game.Graphics.UserInterface { @@ -29,10 +30,7 @@ namespace osu.Game.Graphics.UserInterface [BackgroundDependencyLoader] private void load(OsuColour colours) => AccentColour = colours.BlueLighter; - protected override string FormatCount(double count) - { - return $@"{count:P2}"; - } + protected override string FormatCount(double count) => count.FormatAccuracy(); protected override double GetProportionalDuration(double currentValue, double newValue) { From 9bfd3a1a6348e4f7be4ef305bfbec7b2d207f8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sat, 8 Feb 2020 00:11:19 +0100 Subject: [PATCH 23/37] Make PercentageBreakInfoLine use FormatAccuracy --- osu.Game/Screens/Play/Break/BreakInfoLine.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osu.Game/Screens/Play/Break/BreakInfoLine.cs b/osu.Game/Screens/Play/Break/BreakInfoLine.cs index 70e7b8f297..18aab394f8 100644 --- a/osu.Game/Screens/Play/Break/BreakInfoLine.cs +++ b/osu.Game/Screens/Play/Break/BreakInfoLine.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; +using osu.Game.Utils; namespace osu.Game.Screens.Play.Break { @@ -85,6 +86,6 @@ namespace osu.Game.Screens.Play.Break { } - protected override string Format(double count) => $@"{count:P2}"; + protected override string Format(double count) => count.FormatAccuracy(); } } From 801e39a5433f12e385c61da0860a640d1d1a617f Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sat, 8 Feb 2020 11:35:27 +0900 Subject: [PATCH 24/37] Improve xmldoc for PlacementObject --- osu.Game/Screens/Edit/EditorBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/EditorBeatmap.cs b/osu.Game/Screens/Edit/EditorBeatmap.cs index e1f3ddf191..5216e85903 100644 --- a/osu.Game/Screens/Edit/EditorBeatmap.cs +++ b/osu.Game/Screens/Edit/EditorBeatmap.cs @@ -39,7 +39,7 @@ namespace osu.Game.Screens.Edit public readonly BindableList SelectedHitObjects = new BindableList(); /// - /// The current placement + /// The current placement. Null if there's no active placement. /// public readonly Bindable PlacementObject = new Bindable(); From e0de60a277c4f9792b889efc1bb44d39e0251f91 Mon Sep 17 00:00:00 2001 From: Joehu Date: Fri, 7 Feb 2020 21:03:33 -0800 Subject: [PATCH 25/37] Update default background dim to 80% to match stable --- osu.Game/Configuration/OsuConfigManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Configuration/OsuConfigManager.cs b/osu.Game/Configuration/OsuConfigManager.cs index 4155381790..6ae3c7ac64 100644 --- a/osu.Game/Configuration/OsuConfigManager.cs +++ b/osu.Game/Configuration/OsuConfigManager.cs @@ -78,7 +78,7 @@ namespace osu.Game.Configuration Set(OsuSetting.MenuParallax, true); // Gameplay - Set(OsuSetting.DimLevel, 0.3, 0, 1, 0.01); + Set(OsuSetting.DimLevel, 0.8, 0, 1, 0.01); Set(OsuSetting.BlurLevel, 0, 0, 1, 0.01); Set(OsuSetting.LightenDuringBreaks, true); From 5b452293d6055754bf007582c5a151a9ad859ede Mon Sep 17 00:00:00 2001 From: Berkan Diler Date: Sat, 8 Feb 2020 18:05:27 +0100 Subject: [PATCH 26/37] Minor cleanups for legacy beatmap decoders Replaces some string.StartsWith(string, StringComparison.Ordinal) calls with ring.StartsWith(char) , when only one char is compared. Possible since .NET-Standard 2.1 And another LegacyStoryboardDecoder.handleEvents() cleanup, saves some MB of allocations. --- osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyDecoder.cs | 2 +- osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs index 009da0656b..4b01b2490e 100644 --- a/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyBeatmapDecoder.cs @@ -64,7 +64,7 @@ namespace osu.Game.Beatmaps.Formats hitObject.ApplyDefaults(this.beatmap.ControlPointInfo, this.beatmap.BeatmapInfo.BaseDifficulty); } - protected override bool ShouldSkipLine(string line) => base.ShouldSkipLine(line) || line.StartsWith(" ", StringComparison.Ordinal) || line.StartsWith("_", StringComparison.Ordinal); + protected override bool ShouldSkipLine(string line) => base.ShouldSkipLine(line) || line.StartsWith(' ') || line.StartsWith('_'); protected override void ParseLine(Beatmap beatmap, Section section, string line) { diff --git a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs index 0ec80eee41..e28e235788 100644 --- a/osu.Game/Beatmaps/Formats/LegacyDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyDecoder.cs @@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps.Formats if (ShouldSkipLine(line)) continue; - if (line.StartsWith(@"[", StringComparison.Ordinal) && line.EndsWith(@"]", StringComparison.Ordinal)) + if (line.StartsWith('[') && line.EndsWith(']')) { if (!Enum.TryParse(line[1..^1], out section)) { diff --git a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs index 35576e0f33..6569f76b2d 100644 --- a/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs +++ b/osu.Game/Beatmaps/Formats/LegacyStoryboardDecoder.cs @@ -64,15 +64,16 @@ namespace osu.Game.Beatmaps.Formats private void handleEvents(string line) { var depth = 0; - var lineSpan = line.AsSpan(); - while (lineSpan.StartsWith(" ", StringComparison.Ordinal) || lineSpan.StartsWith("_", StringComparison.Ordinal)) + foreach (char c in line) { - lineSpan = lineSpan.Slice(1); - ++depth; + if (c == ' ' || c == '_') + depth++; + else + break; } - line = lineSpan.ToString(); + line = line.Substring(depth); decodeVariables(ref line); From c2e0c83724f0d981c780d5a1fb337c84f4248db7 Mon Sep 17 00:00:00 2001 From: jorolf Date: Sat, 8 Feb 2020 20:25:16 +0100 Subject: [PATCH 27/37] change the hierarchy layout --- osu.Game/Graphics/UserInterface/OsuTextBox.cs | 69 +++++++++++++++---- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index 36740fb015..d58a22685e 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -9,6 +9,7 @@ using osu.Framework.Graphics.UserInterface; using osu.Game.Graphics.Sprites; using osuTK.Graphics; using osu.Framework.Extensions.Color4Extensions; +using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Game.Beatmaps.ControlPoints; using osu.Game.Graphics.Containers; @@ -70,38 +71,82 @@ namespace osu.Game.Graphics.UserInterface SelectionColour = SelectionColour, }; - private class BeatCaret : BasicCaret + private class BeatCaret : Caret { - private bool hasSelection; + private const float caret_move_time = 60; + + private readonly CaretBeatSyncedContainer beatSync; public BeatCaret() { - AddInternal(new CaretBeatSyncedContainer(this)); + RelativeSizeAxes = Axes.Y; + Size = new Vector2(1, 0.9f); + + Colour = Color4.Transparent; + Anchor = Anchor.CentreLeft; + Origin = Anchor.CentreLeft; + + Masking = true; + CornerRadius = 1; + InternalChild = beatSync = new CaretBeatSyncedContainer + { + RelativeSizeAxes = Axes.Both, + }; } + public override void Hide() => this.FadeOut(200); + + public float CaretWidth { get; set; } + + public Color4 SelectionColour { get; set; } + public override void DisplayAt(Vector2 position, float? selectionWidth) { - base.DisplayAt(position, selectionWidth); + beatSync.HasSelection = selectionWidth != null; - hasSelection = selectionWidth != null; - if (selectionWidth == null) - ClearTransforms(targetMember: nameof(Alpha)); + if (selectionWidth != null) + { + this.MoveTo(new Vector2(position.X, position.Y), 60, Easing.Out); + this.ResizeWidthTo(selectionWidth.Value + CaretWidth / 2, caret_move_time, Easing.Out); + this.FadeColour(SelectionColour, 200, Easing.Out); + } + else + { + this.MoveTo(new Vector2(position.X - CaretWidth / 2, position.Y), 60, Easing.Out); + this.ResizeWidthTo(CaretWidth, caret_move_time, Easing.Out); + this.FadeColour(Color4.White, 200, Easing.Out); + } } private class CaretBeatSyncedContainer : BeatSyncedContainer { - private readonly BeatCaret caret; + private bool hasSelection; - public CaretBeatSyncedContainer(BeatCaret caret) + public bool HasSelection + { + set + { + hasSelection = value; + if (value) + + this.FadeTo(0.5f, 200, Easing.Out); + } + } + + public CaretBeatSyncedContainer() { - this.caret = caret; MinimumBeatLength = 300; + InternalChild = new Box + { + RelativeSizeAxes = Axes.Both, + Colour = Color4.White, + }; } protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes) { - if (!caret.hasSelection) - caret.FadeTo(0.7f).FadeTo(0.4f, timingPoint.BeatLength, Easing.InOutSine); + if (!hasSelection) + this.FadeTo(0.7f).FadeTo(0.4f, timingPoint.BeatLength, Easing.InOutSine); } } } From 93ff25d2a43ee62c40c46e4489515e51f39f5395 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Feb 2020 15:36:44 +0900 Subject: [PATCH 28/37] Rename caret class --- osu.Game/Graphics/UserInterface/OsuTextBox.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/OsuTextBox.cs b/osu.Game/Graphics/UserInterface/OsuTextBox.cs index d58a22685e..4abbf8db57 100644 --- a/osu.Game/Graphics/UserInterface/OsuTextBox.cs +++ b/osu.Game/Graphics/UserInterface/OsuTextBox.cs @@ -65,19 +65,19 @@ namespace osu.Game.Graphics.UserInterface protected override Drawable GetDrawableCharacter(char c) => new OsuSpriteText { Text = c.ToString(), Font = OsuFont.GetFont(size: CalculatedTextSize) }; - protected override Caret CreateCaret() => new BeatCaret + protected override Caret CreateCaret() => new OsuCaret { CaretWidth = CaretWidth, SelectionColour = SelectionColour, }; - private class BeatCaret : Caret + private class OsuCaret : Caret { private const float caret_move_time = 60; private readonly CaretBeatSyncedContainer beatSync; - public BeatCaret() + public OsuCaret() { RelativeSizeAxes = Axes.Y; Size = new Vector2(1, 0.9f); From 590429b43ba9ba9f12e0e7914d52fe866daf1a03 Mon Sep 17 00:00:00 2001 From: ProTheory8 Date: Sun, 9 Feb 2020 09:15:32 +0000 Subject: [PATCH 29/37] Now TestAutoOpenOnModSelect checks if customisation closes after deselecting mod --- osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 22ba972390..a9353d189f 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestCustomisationOpensOnModSelect() + public void TestAutoOpenOnModSelect() { createModSelect(); @@ -71,6 +71,8 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.Alpha == 0); AddStep("select mod", () => modSelect.SelectMod(testCustomisableAutoOpenMod)); AddAssert("Customisation opened", () => modSelect.ModSettingsContainer.Alpha == 1); + AddStep("deselect mod", () => modSelect.SelectMod(testCustomisableAutoOpenMod)); + AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.Alpha == 0); } private void createModSelect() From d73ef7c37e86639fbbeac95431077ba2d374201d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Feb 2020 21:25:11 +0900 Subject: [PATCH 30/37] Change DummyBeatmap's track to be 0 length --- osu.Game/Beatmaps/WorkingBeatmap.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 05c344b199..30f2045a83 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -59,7 +59,7 @@ namespace osu.Game.Beatmaps switch (lastObject) { case null: - length = excess_length; + length = 0; break; case IHasEndTime endTime: From c1f52ef5941dd5c84c3dd6432ccf261558dce8ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Feb 2020 21:25:28 +0900 Subject: [PATCH 31/37] Refactor BeatSyncContainer to handle zero length tracks --- .../Containers/BeatSyncedContainer.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs index be9aefa359..f36079682e 100644 --- a/osu.Game/Graphics/Containers/BeatSyncedContainer.cs +++ b/osu.Game/Graphics/Containers/BeatSyncedContainer.cs @@ -59,9 +59,9 @@ namespace osu.Game.Graphics.Containers Track track = null; IBeatmap beatmap = null; - double currentTrackTime; - TimingControlPoint timingPoint; - EffectControlPoint effectPoint; + double currentTrackTime = 0; + TimingControlPoint timingPoint = null; + EffectControlPoint effectPoint = null; if (Beatmap.Value.TrackLoaded && Beatmap.Value.BeatmapLoaded) { @@ -69,24 +69,18 @@ namespace osu.Game.Graphics.Containers beatmap = Beatmap.Value.Beatmap; } - if (track != null && beatmap != null && track.IsRunning) + if (track != null && beatmap != null && track.IsRunning && track.Length > 0) { - currentTrackTime = track.Length > 0 ? track.CurrentTime + EarlyActivationMilliseconds : Clock.CurrentTime; + currentTrackTime = track.CurrentTime + EarlyActivationMilliseconds; timingPoint = beatmap.ControlPointInfo.TimingPointAt(currentTrackTime); effectPoint = beatmap.ControlPointInfo.EffectPointAt(currentTrackTime); - - if (timingPoint.BeatLength == 0) - { - IsBeatSyncedWithTrack = false; - return; - } - - IsBeatSyncedWithTrack = true; } - else + + IsBeatSyncedWithTrack = timingPoint?.BeatLength > 0; + + if (timingPoint == null || !IsBeatSyncedWithTrack) { - IsBeatSyncedWithTrack = false; currentTrackTime = Clock.CurrentTime; timingPoint = defaultTiming; effectPoint = defaultEffect; From 96574a98adc8b48c2637aabc3287562eb8893f06 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Sun, 9 Feb 2020 21:34:56 +0900 Subject: [PATCH 32/37] Use non-zero length for fallback virtual track (allows tests to work as expected) --- osu.Game/Beatmaps/WorkingBeatmap.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs index 30f2045a83..5dc483b61c 100644 --- a/osu.Game/Beatmaps/WorkingBeatmap.cs +++ b/osu.Game/Beatmaps/WorkingBeatmap.cs @@ -39,7 +39,7 @@ namespace osu.Game.Beatmaps BeatmapSetInfo = beatmapInfo.BeatmapSet; Metadata = beatmapInfo.Metadata ?? BeatmapSetInfo?.Metadata ?? new BeatmapMetadata(); - track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack()); + track = new RecyclableLazy(() => GetTrack() ?? GetVirtualTrack(1000)); background = new RecyclableLazy(GetBackground, BackgroundStillValid); waveform = new RecyclableLazy(GetWaveform); storyboard = new RecyclableLazy(GetStoryboard); @@ -48,7 +48,7 @@ namespace osu.Game.Beatmaps total_count.Value++; } - protected virtual Track GetVirtualTrack() + protected virtual Track GetVirtualTrack(double emptyLength = 0) { const double excess_length = 1000; @@ -59,7 +59,7 @@ namespace osu.Game.Beatmaps switch (lastObject) { case null: - length = 0; + length = emptyLength; break; case IHasEndTime endTime: From 404cb613429289faa85d05bdfcf1be181ecb6c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 9 Feb 2020 14:39:27 +0100 Subject: [PATCH 33/37] Open mod select in a more reliable way --- .../Visual/UserInterface/TestSceneModSettings.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index a9353d189f..7781eeb315 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -38,8 +38,8 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestButtonShowsOnCustomisableMod() { createModSelect(); + openModSelect(); - AddStep("open", () => modSelect.Show()); AddAssert("button disabled", () => !modSelect.CustomiseButton.Enabled.Value); AddUntilStep("wait for button load", () => modSelect.ButtonsLoaded); AddStep("select mod", () => modSelect.SelectMod(testCustomisableMod)); @@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.UserInterface AddAssert("mods still active", () => SelectedMods.Value.Count == 1); - AddStep("open", () => modSelect.Show()); + openModSelect(); AddAssert("button enabled", () => modSelect.CustomiseButton.Enabled.Value); } @@ -66,8 +66,8 @@ namespace osu.Game.Tests.Visual.UserInterface public void TestAutoOpenOnModSelect() { createModSelect(); + openModSelect(); - AddStep("open", () => modSelect.Show()); AddAssert("Customisation closed", () => modSelect.ModSettingsContainer.Alpha == 0); AddStep("select mod", () => modSelect.SelectMod(testCustomisableAutoOpenMod)); AddAssert("Customisation opened", () => modSelect.ModSettingsContainer.Alpha == 1); @@ -88,6 +88,12 @@ namespace osu.Game.Tests.Visual.UserInterface }); } + private void openModSelect() + { + AddStep("open", () => modSelect.Show()); + AddUntilStep("wait for ready", () => modSelect.State.Value == Visibility.Visible && modSelect.ButtonsLoaded); + } + private class TestModSelectOverlay : ModSelectOverlay { public new Container ModSettingsContainer => base.ModSettingsContainer; From 7e28f2fe6aae19fdf91e68211cca5c0d19bee6be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Dach?= Date: Sun, 9 Feb 2020 14:41:02 +0100 Subject: [PATCH 34/37] Rename test to better reflect its purpose --- osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs index 7781eeb315..7ff463361a 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneModSettings.cs @@ -63,7 +63,7 @@ namespace osu.Game.Tests.Visual.UserInterface } [Test] - public void TestAutoOpenOnModSelect() + public void TestCustomisationMenuVisibility() { createModSelect(); openModSelect(); From 28cf5c7a5983b5ab9f9b6366faf751a94afb695d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Mon, 10 Feb 2020 14:28:43 +0900 Subject: [PATCH 35/37] Add accessor --- osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs index 55b2b801e7..417d32ca4f 100644 --- a/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs +++ b/osu.Game/Screens/Edit/Compose/Components/BlueprintContainer.cs @@ -32,7 +32,7 @@ namespace osu.Game.Screens.Edit.Compose.Components protected DragBox DragBox { get; private set; } - protected Container SelectionBlueprints; + protected Container SelectionBlueprints { get; private set; } private SelectionHandler selectionHandler; From 2252f790848c8b8e695afab6d28be272229ce0e4 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2020 08:01:14 +0000 Subject: [PATCH 36/37] Bump Sentry from 2.0.1 to 2.0.2 Bumps [Sentry](https://github.com/getsentry/sentry-dotnet) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/getsentry/sentry-dotnet/releases) - [Commits](https://github.com/getsentry/sentry-dotnet/compare/2.0.1...2.0.2) Signed-off-by: dependabot-preview[bot] --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 21c9eab4c6..389fbe8210 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -24,7 +24,7 @@ - + From 48781e5685bee2e428dd03e44b66979a2a8e7ed9 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2020 08:24:12 +0000 Subject: [PATCH 37/37] Bump Microsoft.NET.Test.Sdk from 16.4.0 to 16.5.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 16.4.0 to 16.5.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Commits](https://github.com/microsoft/vstest/compare/v16.4.0...v16.5.0) Signed-off-by: dependabot-preview[bot] --- .../osu.Game.Rulesets.Catch.Tests.csproj | 2 +- .../osu.Game.Rulesets.Mania.Tests.csproj | 2 +- osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj | 2 +- .../osu.Game.Rulesets.Taiko.Tests.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 2 +- osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 9559d13328..8c371db257 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index dea6e6c0fb..6855b99f28 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index 9d4e016eae..217707b180 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index d728d65bfd..f6054a5d6f 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -2,7 +2,7 @@ - + diff --git a/osu.Game.Tests/osu.Game.Tests.csproj b/osu.Game.Tests/osu.Game.Tests.csproj index 6c799e5e90..35eb3fa161 100644 --- a/osu.Game.Tests/osu.Game.Tests.csproj +++ b/osu.Game.Tests/osu.Game.Tests.csproj @@ -3,7 +3,7 @@ - + diff --git a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj index 7ecfd6ef70..3b45fc83fd 100644 --- a/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj +++ b/osu.Game.Tournament.Tests/osu.Game.Tournament.Tests.csproj @@ -5,7 +5,7 @@ - +