mirror of
https://github.com/ppy/osu.git
synced 2025-03-28 09:37:23 +08:00
Merge branch 'master' into truncate-long-usernames-in-private-chat
This commit is contained in:
commit
262284d095
@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
{
|
{
|
||||||
public override string Description => @"Play with no approach circles and fading circles/sliders.";
|
public override string Description => @"Play with no approach circles and fading circles/sliders.";
|
||||||
public override double ScoreMultiplier => 1.06;
|
public override double ScoreMultiplier => 1.06;
|
||||||
|
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn) };
|
||||||
private const double fade_in_duration_multiplier = 0.4;
|
private const double fade_in_duration_multiplier = 0.4;
|
||||||
private const double fade_out_duration_multiplier = 0.3;
|
private const double fade_out_duration_multiplier = 0.3;
|
||||||
|
|
||||||
|
92
osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs
Normal file
92
osu.Game.Rulesets.Osu/Mods/OsuModSpinIn.cs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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.Linq;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Mods
|
||||||
|
{
|
||||||
|
public class OsuModSpinIn : Mod, IApplicableToDrawableHitObjects, IReadFromConfig
|
||||||
|
{
|
||||||
|
public override string Name => "Spin In";
|
||||||
|
public override string Acronym => "SI";
|
||||||
|
public override IconUsage Icon => FontAwesome.Solid.Undo;
|
||||||
|
public override ModType Type => ModType.Fun;
|
||||||
|
public override string Description => "Circles spin in. No approach circles.";
|
||||||
|
public override double ScoreMultiplier => 1;
|
||||||
|
|
||||||
|
// todo: this mod should be able to be compatible with hidden with a bit of further implementation.
|
||||||
|
public override Type[] IncompatibleMods => new[] { typeof(OsuModeObjectScaleTween), typeof(OsuModHidden) };
|
||||||
|
|
||||||
|
private const int rotate_offset = 360;
|
||||||
|
private const float rotate_starting_width = 2;
|
||||||
|
|
||||||
|
private Bindable<bool> increaseFirstObjectVisibility = new Bindable<bool>();
|
||||||
|
|
||||||
|
public void ReadFromConfig(OsuConfigManager config)
|
||||||
|
{
|
||||||
|
increaseFirstObjectVisibility = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyToDrawableHitObjects(IEnumerable<DrawableHitObject> drawables)
|
||||||
|
{
|
||||||
|
foreach (var drawable in drawables.Skip(increaseFirstObjectVisibility.Value ? 1 : 0))
|
||||||
|
{
|
||||||
|
switch (drawable)
|
||||||
|
{
|
||||||
|
case DrawableSpinner _:
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
drawable.ApplyCustomUpdateState += applyZoomState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyZoomState(DrawableHitObject drawable, ArmedState state)
|
||||||
|
{
|
||||||
|
var h = (OsuHitObject)drawable.HitObject;
|
||||||
|
|
||||||
|
switch (drawable)
|
||||||
|
{
|
||||||
|
case DrawableHitCircle circle:
|
||||||
|
using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true))
|
||||||
|
{
|
||||||
|
circle.ApproachCircle.Hide();
|
||||||
|
|
||||||
|
circle.RotateTo(rotate_offset).Then().RotateTo(0, h.TimePreempt, Easing.InOutSine);
|
||||||
|
circle.ScaleTo(new Vector2(rotate_starting_width, 0)).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine);
|
||||||
|
|
||||||
|
// bypass fade in.
|
||||||
|
if (state == ArmedState.Idle)
|
||||||
|
circle.FadeIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DrawableSlider slider:
|
||||||
|
using (slider.BeginAbsoluteSequence(h.StartTime - h.TimePreempt))
|
||||||
|
{
|
||||||
|
slider.ScaleTo(0).Then().ScaleTo(1, h.TimePreempt, Easing.InOutSine);
|
||||||
|
|
||||||
|
// bypass fade in.
|
||||||
|
if (state == ArmedState.Idle)
|
||||||
|
slider.FadeIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@ -28,6 +29,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
|
|
||||||
private Bindable<bool> increaseFirstObjectVisibility = new Bindable<bool>();
|
private Bindable<bool> increaseFirstObjectVisibility = new Bindable<bool>();
|
||||||
|
|
||||||
|
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpinIn) };
|
||||||
|
|
||||||
public void ReadFromConfig(OsuConfigManager config)
|
public void ReadFromConfig(OsuConfigManager config)
|
||||||
{
|
{
|
||||||
increaseFirstObjectVisibility = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility);
|
increaseFirstObjectVisibility = config.GetBindable<bool>(OsuSetting.IncreaseFirstObjectVisibility);
|
||||||
@ -64,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
case DrawableSlider _:
|
case DrawableSlider _:
|
||||||
case DrawableHitCircle _:
|
case DrawableHitCircle _:
|
||||||
{
|
{
|
||||||
using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true))
|
using (drawable.BeginAbsoluteSequence(h.StartTime - h.TimePreempt))
|
||||||
drawable.ScaleTo(StartScale).Then().ScaleTo(EndScale, h.TimePreempt, Easing.OutSine);
|
drawable.ScaleTo(StartScale).Then().ScaleTo(EndScale, h.TimePreempt, Easing.OutSine);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -75,7 +78,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
|||||||
{
|
{
|
||||||
case DrawableHitCircle circle:
|
case DrawableHitCircle circle:
|
||||||
// we don't want to see the approach circle
|
// we don't want to see the approach circle
|
||||||
using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt, true))
|
using (circle.BeginAbsoluteSequence(h.StartTime - h.TimePreempt))
|
||||||
circle.ApproachCircle.Hide();
|
circle.ApproachCircle.Hide();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,7 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
{
|
{
|
||||||
new OsuModTransform(),
|
new OsuModTransform(),
|
||||||
new OsuModWiggle(),
|
new OsuModWiggle(),
|
||||||
|
new OsuModSpinIn(),
|
||||||
new MultiMod(new OsuModGrow(), new OsuModDeflate()),
|
new MultiMod(new OsuModGrow(), new OsuModDeflate()),
|
||||||
new MultiMod(new ModWindUp<OsuHitObject>(), new ModWindDown<OsuHitObject>()),
|
new MultiMod(new ModWindUp<OsuHitObject>(), new ModWindDown<OsuHitObject>()),
|
||||||
};
|
};
|
||||||
|
@ -26,6 +26,9 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
public class BeatmapCarousel : OsuScrollContainer
|
public class BeatmapCarousel : OsuScrollContainer
|
||||||
{
|
{
|
||||||
|
private const float bleed_top = FilterControl.HEIGHT;
|
||||||
|
private const float bleed_bottom = Footer.HEIGHT;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Triggered when the <see cref="BeatmapSets"/> loaded change and are completely loaded.
|
/// Triggered when the <see cref="BeatmapSets"/> loaded change and are completely loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -336,6 +339,25 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
public bool AllowSelection = true;
|
public bool AllowSelection = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Half the height of the visible content.
|
||||||
|
/// <remarks>
|
||||||
|
/// This is different from the height of <see cref="ScrollContainer{T}.displayableContent"/>, since
|
||||||
|
/// the beatmap carousel bleeds into the <see cref="FilterControl"/> and the <see cref="Footer"/>
|
||||||
|
/// </remarks>
|
||||||
|
/// </summary>
|
||||||
|
private float visibleHalfHeight => (DrawHeight + bleed_bottom + bleed_top) / 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The position of the lower visible bound with respect to the current scroll position.
|
||||||
|
/// </summary>
|
||||||
|
private float visibleBottomBound => Current + DrawHeight + bleed_bottom;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The position of the upper visible bound with respect to the current scroll position.
|
||||||
|
/// </summary>
|
||||||
|
private float visibleUpperBound => Current - bleed_top;
|
||||||
|
|
||||||
public void FlushPendingFilterOperations()
|
public void FlushPendingFilterOperations()
|
||||||
{
|
{
|
||||||
if (PendingFilter?.Completed == false)
|
if (PendingFilter?.Completed == false)
|
||||||
@ -412,6 +434,8 @@ namespace osu.Game.Screens.Select
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool ReceivePositionalInputAtSubTree(Vector2 screenSpacePos) => ReceivePositionalInputAt(screenSpacePos);
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
@ -422,17 +446,15 @@ namespace osu.Game.Screens.Select
|
|||||||
if (!scrollPositionCache.IsValid)
|
if (!scrollPositionCache.IsValid)
|
||||||
updateScrollPosition();
|
updateScrollPosition();
|
||||||
|
|
||||||
float drawHeight = DrawHeight;
|
|
||||||
|
|
||||||
// Remove all items that should no longer be on-screen
|
// Remove all items that should no longer be on-screen
|
||||||
scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent);
|
scrollableContent.RemoveAll(p => p.Y < visibleUpperBound - p.DrawHeight || p.Y > visibleBottomBound || !p.IsPresent);
|
||||||
|
|
||||||
// Find index range of all items that should be on-screen
|
// Find index range of all items that should be on-screen
|
||||||
Trace.Assert(Items.Count == yPositions.Count);
|
Trace.Assert(Items.Count == yPositions.Count);
|
||||||
|
|
||||||
int firstIndex = yPositions.BinarySearch(Current - DrawableCarouselItem.MAX_HEIGHT);
|
int firstIndex = yPositions.BinarySearch(visibleUpperBound - DrawableCarouselItem.MAX_HEIGHT);
|
||||||
if (firstIndex < 0) firstIndex = ~firstIndex;
|
if (firstIndex < 0) firstIndex = ~firstIndex;
|
||||||
int lastIndex = yPositions.BinarySearch(Current + drawHeight);
|
int lastIndex = yPositions.BinarySearch(visibleBottomBound);
|
||||||
if (lastIndex < 0) lastIndex = ~lastIndex;
|
if (lastIndex < 0) lastIndex = ~lastIndex;
|
||||||
|
|
||||||
int notVisibleCount = 0;
|
int notVisibleCount = 0;
|
||||||
@ -484,9 +506,8 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
// Update externally controlled state of currently visible items
|
// Update externally controlled state of currently visible items
|
||||||
// (e.g. x-offset and opacity).
|
// (e.g. x-offset and opacity).
|
||||||
float halfHeight = drawHeight / 2;
|
|
||||||
foreach (DrawableCarouselItem p in scrollableContent.Children)
|
foreach (DrawableCarouselItem p in scrollableContent.Children)
|
||||||
updateItem(p, halfHeight);
|
updateItem(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
@ -540,7 +561,7 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
yPositions.Clear();
|
yPositions.Clear();
|
||||||
|
|
||||||
float currentY = DrawHeight / 2;
|
float currentY = visibleHalfHeight;
|
||||||
DrawableCarouselBeatmapSet lastSet = null;
|
DrawableCarouselBeatmapSet lastSet = null;
|
||||||
|
|
||||||
scrollTarget = null;
|
scrollTarget = null;
|
||||||
@ -573,7 +594,6 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
float? setY = null;
|
float? setY = null;
|
||||||
if (!d.IsLoaded || beatmap.Alpha == 0) // can't use IsPresent due to DrawableCarouselItem override.
|
if (!d.IsLoaded || beatmap.Alpha == 0) // can't use IsPresent due to DrawableCarouselItem override.
|
||||||
// ReSharper disable once PossibleNullReferenceException (resharper broken?)
|
|
||||||
setY = lastSet.Y + lastSet.DrawHeight + 5;
|
setY = lastSet.Y + lastSet.DrawHeight + 5;
|
||||||
|
|
||||||
if (d.IsLoaded)
|
if (d.IsLoaded)
|
||||||
@ -594,7 +614,7 @@ namespace osu.Game.Screens.Select
|
|||||||
currentY += d.DrawHeight + 5;
|
currentY += d.DrawHeight + 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentY += DrawHeight / 2;
|
currentY += visibleHalfHeight;
|
||||||
scrollableContent.Height = currentY;
|
scrollableContent.Height = currentY;
|
||||||
|
|
||||||
if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected))
|
if (BeatmapSetsLoaded && (selectedBeatmapSet == null || selectedBeatmap == null || selectedBeatmapSet.State.Value != CarouselItemState.Selected))
|
||||||
@ -635,18 +655,15 @@ namespace osu.Game.Screens.Select
|
|||||||
/// the current scroll position.
|
/// the current scroll position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="p">The item to be updated.</param>
|
/// <param name="p">The item to be updated.</param>
|
||||||
/// <param name="halfHeight">Half the draw height of the carousel container.</param>
|
private void updateItem(DrawableCarouselItem p)
|
||||||
private void updateItem(DrawableCarouselItem p, float halfHeight)
|
|
||||||
{
|
{
|
||||||
var height = p.IsPresent ? p.DrawHeight : 0;
|
float itemDrawY = p.Position.Y - visibleUpperBound + p.DrawHeight / 2;
|
||||||
|
float dist = Math.Abs(1f - itemDrawY / visibleHalfHeight);
|
||||||
float itemDrawY = p.Position.Y - Current + height / 2;
|
|
||||||
float dist = Math.Abs(1f - itemDrawY / halfHeight);
|
|
||||||
|
|
||||||
// Setting the origin position serves as an additive position on top of potential
|
// Setting the origin position serves as an additive position on top of potential
|
||||||
// local transformation we may want to apply (e.g. when a item gets selected, we
|
// local transformation we may want to apply (e.g. when a item gets selected, we
|
||||||
// may want to smoothly transform it leftwards.)
|
// may want to smoothly transform it leftwards.)
|
||||||
p.OriginPosition = new Vector2(-offsetX(dist, halfHeight), 0);
|
p.OriginPosition = new Vector2(-offsetX(dist, visibleHalfHeight), 0);
|
||||||
|
|
||||||
// We are applying a multiplicative alpha (which is internally done by nesting an
|
// We are applying a multiplicative alpha (which is internally done by nesting an
|
||||||
// additional container and setting that container's alpha) such that we can
|
// additional container and setting that container's alpha) such that we can
|
||||||
|
@ -14,7 +14,6 @@ using osu.Game.Graphics.UserInterface;
|
|||||||
using osu.Game.Screens.Select.Filter;
|
using osu.Game.Screens.Select.Filter;
|
||||||
using Container = osu.Framework.Graphics.Containers.Container;
|
using Container = osu.Framework.Graphics.Containers.Container;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
@ -22,6 +21,8 @@ namespace osu.Game.Screens.Select
|
|||||||
{
|
{
|
||||||
public class FilterControl : Container
|
public class FilterControl : Container
|
||||||
{
|
{
|
||||||
|
public const float HEIGHT = 100;
|
||||||
|
|
||||||
public Action<FilterCriteria> FilterChanged;
|
public Action<FilterCriteria> FilterChanged;
|
||||||
|
|
||||||
private readonly OsuTabControl<SortMode> sortTabs;
|
private readonly OsuTabControl<SortMode> sortTabs;
|
||||||
@ -187,11 +188,5 @@ namespace osu.Game.Screens.Select
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria());
|
private void updateCriteria() => FilterChanged?.Invoke(CreateCriteria());
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e) => true;
|
|
||||||
|
|
||||||
protected override bool OnMouseMove(MouseMoveEvent e) => true;
|
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e) => true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ namespace osu.Game.Screens.Select
|
|||||||
Size = new Vector2(wedged_container_size.X, 1),
|
Size = new Vector2(wedged_container_size.X, 1),
|
||||||
Padding = new MarginPadding
|
Padding = new MarginPadding
|
||||||
{
|
{
|
||||||
Bottom = 50,
|
Bottom = Footer.HEIGHT,
|
||||||
Top = wedged_container_size.Y + left_area_padding,
|
Top = wedged_container_size.Y + left_area_padding,
|
||||||
Left = left_area_padding,
|
Left = left_area_padding,
|
||||||
Right = left_area_padding * 2,
|
Right = left_area_padding * 2,
|
||||||
@ -147,20 +147,29 @@ namespace osu.Game.Screens.Select
|
|||||||
Width = 0.5f,
|
Width = 0.5f,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Carousel = new BeatmapCarousel
|
new Container
|
||||||
{
|
{
|
||||||
Masking = false,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Size = new Vector2(1 - wedged_container_size.X, 1),
|
Padding = new MarginPadding
|
||||||
Anchor = Anchor.CentreRight,
|
{
|
||||||
Origin = Anchor.CentreRight,
|
Top = FilterControl.HEIGHT,
|
||||||
SelectionChanged = updateSelectedBeatmap,
|
Bottom = Footer.HEIGHT
|
||||||
BeatmapSetsChanged = carouselBeatmapsLoaded,
|
},
|
||||||
|
Child = Carousel = new BeatmapCarousel
|
||||||
|
{
|
||||||
|
Masking = false,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Size = new Vector2(1 - wedged_container_size.X, 1),
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
SelectionChanged = updateSelectedBeatmap,
|
||||||
|
BeatmapSetsChanged = carouselBeatmapsLoaded,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
FilterControl = new FilterControl
|
FilterControl = new FilterControl
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 100,
|
Height = FilterControl.HEIGHT,
|
||||||
FilterChanged = c => Carousel.Filter(c),
|
FilterChanged = c => Carousel.Filter(c),
|
||||||
Background = { Width = 2 },
|
Background = { Width = 2 },
|
||||||
Exit = () =>
|
Exit = () =>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user