1
0
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:
Dean Herbert 2019-07-29 02:47:49 +09:00 committed by GitHub
commit 262284d095
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 153 additions and 35 deletions

View File

@ -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;

View 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;
}
}
}
}

View File

@ -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;
} }

View File

@ -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>()),
}; };

View File

@ -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

View File

@ -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;
} }
} }

View File

@ -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 = () =>