mirror of
https://github.com/ppy/osu.git
synced 2024-12-15 05:42:56 +08:00
Merge branch 'master' into slider-ball-scaling
This commit is contained in:
commit
4ee20bae30
@ -63,6 +63,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.723.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2019.729.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -71,7 +71,7 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
switch (newScreen)
|
switch (newScreen)
|
||||||
{
|
{
|
||||||
case Intro _:
|
case IntroScreen _:
|
||||||
case MainMenu _:
|
case MainMenu _:
|
||||||
versionManager?.Show();
|
versionManager?.Show();
|
||||||
break;
|
break;
|
||||||
|
@ -27,6 +27,8 @@ namespace osu.Desktop.Updater
|
|||||||
|
|
||||||
public Task PrepareUpdateAsync() => UpdateManager.RestartAppWhenExited();
|
public Task PrepareUpdateAsync() => UpdateManager.RestartAppWhenExited();
|
||||||
|
|
||||||
|
private static readonly Logger logger = Logger.GetLogger("updater");
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(NotificationOverlay notification, OsuGameBase game)
|
private void load(NotificationOverlay notification, OsuGameBase game)
|
||||||
{
|
{
|
||||||
@ -77,7 +79,7 @@ namespace osu.Desktop.Updater
|
|||||||
{
|
{
|
||||||
if (useDeltaPatching)
|
if (useDeltaPatching)
|
||||||
{
|
{
|
||||||
Logger.Error(e, @"delta patching failed!");
|
logger.Add(@"delta patching failed; will attempt full download!");
|
||||||
|
|
||||||
//could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959)
|
//could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959)
|
||||||
//try again without deltas.
|
//try again without deltas.
|
||||||
@ -163,16 +165,11 @@ namespace osu.Desktop.Updater
|
|||||||
{
|
{
|
||||||
public LogLevel Level { get; set; } = LogLevel.Info;
|
public LogLevel Level { get; set; } = LogLevel.Info;
|
||||||
|
|
||||||
private Logger logger;
|
|
||||||
|
|
||||||
public void Write(string message, LogLevel logLevel)
|
public void Write(string message, LogLevel logLevel)
|
||||||
{
|
{
|
||||||
if (logLevel < Level)
|
if (logLevel < Level)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (logger == null)
|
|
||||||
logger = Logger.GetLogger("updater");
|
|
||||||
|
|
||||||
logger.Add(message);
|
logger.Add(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -97,13 +97,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
|||||||
Position = pointStartPosition,
|
Position = pointStartPosition,
|
||||||
Rotation = rotation,
|
Rotation = rotation,
|
||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
Scale = new Vector2(1.5f),
|
Scale = new Vector2(1.5f * currHitObject.Scale),
|
||||||
});
|
});
|
||||||
|
|
||||||
using (fp.BeginAbsoluteSequence(fadeInTime))
|
using (fp.BeginAbsoluteSequence(fadeInTime))
|
||||||
{
|
{
|
||||||
fp.FadeIn(currHitObject.TimeFadeIn);
|
fp.FadeIn(currHitObject.TimeFadeIn);
|
||||||
fp.ScaleTo(1, currHitObject.TimeFadeIn, Easing.Out);
|
fp.ScaleTo(currHitObject.Scale, currHitObject.TimeFadeIn, Easing.Out);
|
||||||
|
|
||||||
fp.MoveTo(pointEndPosition, currHitObject.TimeFadeIn, Easing.Out);
|
fp.MoveTo(pointEndPosition, currHitObject.TimeFadeIn, Easing.Out);
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
base.UpdateInitialTransforms();
|
base.UpdateInitialTransforms();
|
||||||
|
|
||||||
ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt));
|
ApproachCircle.FadeIn(Math.Min(HitObject.TimeFadeIn * 2, HitObject.TimePreempt));
|
||||||
ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt);
|
ApproachCircle.ScaleTo(1f, HitObject.TimePreempt);
|
||||||
ApproachCircle.Expire(true);
|
ApproachCircle.Expire(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,6 +169,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
.FadeOut(100);
|
.FadeOut(100);
|
||||||
|
|
||||||
explode.FadeIn(flash_in);
|
explode.FadeIn(flash_in);
|
||||||
|
explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad);
|
||||||
|
|
||||||
using (BeginDelayedSequence(flash_in, true))
|
using (BeginDelayedSequence(flash_in, true))
|
||||||
{
|
{
|
||||||
@ -178,7 +179,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
number.FadeOut();
|
number.FadeOut();
|
||||||
|
|
||||||
this.FadeOut(800);
|
this.FadeOut(800);
|
||||||
explodeContainer.ScaleTo(1.5f, 400, Easing.OutQuad);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Expire();
|
Expire();
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.MathUtils;
|
using osu.Framework.MathUtils;
|
||||||
@ -20,27 +22,40 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
private double animDuration;
|
private double animDuration;
|
||||||
|
|
||||||
|
private readonly SkinnableDrawable scaleContainer;
|
||||||
|
|
||||||
public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider)
|
public DrawableRepeatPoint(RepeatPoint repeatPoint, DrawableSlider drawableSlider)
|
||||||
: base(repeatPoint)
|
: base(repeatPoint)
|
||||||
{
|
{
|
||||||
this.repeatPoint = repeatPoint;
|
this.repeatPoint = repeatPoint;
|
||||||
this.drawableSlider = drawableSlider;
|
this.drawableSlider = drawableSlider;
|
||||||
|
|
||||||
Size = new Vector2(45 * repeatPoint.Scale);
|
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
|
||||||
|
|
||||||
Blending = BlendingMode.Additive;
|
Blending = BlendingMode.Additive;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon
|
||||||
{
|
|
||||||
new SkinnableDrawable("Play/osu/reversearrow", _ => new SpriteIcon
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Icon = FontAwesome.Solid.ChevronRight
|
Icon = FontAwesome.Solid.ChevronRight,
|
||||||
})
|
Size = new Vector2(0.35f)
|
||||||
|
}, confineMode: ConfineMode.NoScaling)
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly IBindable<float> scaleBindable = new Bindable<float>();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true);
|
||||||
|
scaleBindable.BindTo(HitObject.ScaleBindable);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||||
{
|
{
|
||||||
if (repeatPoint.StartTime <= Time.Current)
|
if (repeatPoint.StartTime <= Time.Current)
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
@ -16,25 +18,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
public const double ANIM_DURATION = 150;
|
public const double ANIM_DURATION = 150;
|
||||||
|
|
||||||
|
private const float default_tick_size = 16;
|
||||||
|
|
||||||
public bool Tracking { get; set; }
|
public bool Tracking { get; set; }
|
||||||
|
|
||||||
public override bool DisplayResult => false;
|
public override bool DisplayResult => false;
|
||||||
|
|
||||||
|
private readonly SkinnableDrawable scaleContainer;
|
||||||
|
|
||||||
public DrawableSliderTick(SliderTick sliderTick)
|
public DrawableSliderTick(SliderTick sliderTick)
|
||||||
: base(sliderTick)
|
: base(sliderTick)
|
||||||
{
|
{
|
||||||
Size = new Vector2(16 * sliderTick.Scale);
|
Size = new Vector2(OsuHitObject.OBJECT_RADIUS * 2);
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChild = scaleContainer = new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new CircularContainer
|
||||||
{
|
|
||||||
new SkinnableDrawable("Play/osu/sliderscorepoint", _ => new Container
|
|
||||||
{
|
{
|
||||||
Masking = true,
|
Masking = true,
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
CornerRadius = Size.X / 2,
|
Size = new Vector2(default_tick_size),
|
||||||
BorderThickness = 2,
|
BorderThickness = default_tick_size / 4,
|
||||||
BorderColour = Color4.White,
|
BorderColour = Color4.White,
|
||||||
Child = new Box
|
Child = new Box
|
||||||
{
|
{
|
||||||
@ -43,9 +46,21 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
Alpha = 0.3f,
|
Alpha = 0.3f,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly IBindable<float> scaleBindable = new Bindable<float>();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
scaleBindable.BindValueChanged(scale => scaleContainer.Scale = new Vector2(scale.NewValue), true);
|
||||||
|
scaleBindable.BindTo(HitObject.ScaleBindable);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
protected override void CheckForResult(bool userTriggered, double timeOffset)
|
||||||
{
|
{
|
||||||
if (timeOffset >= 0)
|
if (timeOffset >= 0)
|
||||||
|
@ -6,6 +6,7 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
@ -24,7 +25,26 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(TextureStore textures)
|
private void load(TextureStore textures)
|
||||||
{
|
{
|
||||||
Child = new SkinnableSprite("Play/osu/approachcircle");
|
Child = new SkinnableApproachCircle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SkinnableApproachCircle : SkinnableSprite
|
||||||
|
{
|
||||||
|
public SkinnableApproachCircle()
|
||||||
|
: base("Play/osu/approachcircle")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateDefault(string name)
|
||||||
|
{
|
||||||
|
var drawable = base.CreateDefault(name);
|
||||||
|
|
||||||
|
// account for the sprite being used for the default approach circle being taken from stable,
|
||||||
|
// when hitcircles have 5px padding on each size. this should be removed if we update the sprite.
|
||||||
|
drawable.Scale = new Vector2(128 / 118f);
|
||||||
|
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Lines;
|
using osu.Framework.Graphics.Lines;
|
||||||
@ -17,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
protected Path Path => path;
|
protected Path Path => path;
|
||||||
|
|
||||||
public float PathRadius
|
public virtual float PathRadius
|
||||||
{
|
{
|
||||||
get => path.PathRadius;
|
get => path.PathRadius;
|
||||||
set => path.PathRadius = value;
|
set => path.PathRadius = value;
|
||||||
@ -75,22 +76,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
|
|
||||||
protected SliderBody()
|
protected SliderBody()
|
||||||
{
|
{
|
||||||
InternalChild = path = new SliderPath();
|
RecyclePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initialises a new <see cref="SliderPath"/>, releasing all resources retained by the old one.
|
/// Initialises a new <see cref="SliderPath"/>, releasing all resources retained by the old one.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void RecyclePath()
|
public virtual void RecyclePath()
|
||||||
{
|
{
|
||||||
InternalChild = path = new SliderPath
|
InternalChild = path = new SliderPath
|
||||||
{
|
{
|
||||||
Position = path.Position,
|
Position = path?.Position ?? Vector2.Zero,
|
||||||
PathRadius = path.PathRadius,
|
PathRadius = path?.PathRadius ?? 10,
|
||||||
AccentColour = path.AccentColour,
|
AccentColour = path?.AccentColour ?? Color4.White,
|
||||||
BorderColour = path.BorderColour,
|
BorderColour = path?.BorderColour ?? Color4.White,
|
||||||
BorderSize = path.BorderSize,
|
BorderSize = path?.BorderSize ?? DEFAULT_BORDER_SIZE,
|
||||||
Vertices = path.Vertices
|
Vertices = path?.Vertices ?? Array.Empty<Vector2>()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
@ -23,6 +24,20 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
public double? SnakedStart { get; private set; }
|
public double? SnakedStart { get; private set; }
|
||||||
public double? SnakedEnd { get; private set; }
|
public double? SnakedEnd { get; private set; }
|
||||||
|
|
||||||
|
public override float PathRadius
|
||||||
|
{
|
||||||
|
get => base.PathRadius;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (base.PathRadius == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
base.PathRadius = value;
|
||||||
|
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override Vector2 PathOffset => snakedPathOffset;
|
public override Vector2 PathOffset => snakedPathOffset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -78,9 +93,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
slider.Path.GetPathToProgress(CurrentCurve, 0, 1);
|
slider.Path.GetPathToProgress(CurrentCurve, 0, 1);
|
||||||
SetVertices(CurrentCurve);
|
SetVertices(CurrentCurve);
|
||||||
|
|
||||||
// The body is sized to the full path size to avoid excessive autosize computations
|
// Force the body to be the final path size to avoid excessive autosize computations
|
||||||
|
Path.AutoSizeAxes = Axes.Both;
|
||||||
Size = Path.Size;
|
Size = Path.Size;
|
||||||
|
|
||||||
|
updatePathSize();
|
||||||
|
|
||||||
snakedPosition = Path.PositionInBoundingBox(Vector2.Zero);
|
snakedPosition = Path.PositionInBoundingBox(Vector2.Zero);
|
||||||
snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]);
|
snakedPathOffset = Path.PositionInBoundingBox(Path.Vertices[0]);
|
||||||
|
|
||||||
@ -93,6 +111,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
setRange(lastSnakedStart, lastSnakedEnd);
|
setRange(lastSnakedStart, lastSnakedEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void RecyclePath()
|
||||||
|
{
|
||||||
|
base.RecyclePath();
|
||||||
|
updatePathSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePathSize()
|
||||||
|
{
|
||||||
|
// Force the path to its final size to avoid excessive framebuffer resizes
|
||||||
|
Path.AutoSizeAxes = Axes.None;
|
||||||
|
Path.Size = Size;
|
||||||
|
}
|
||||||
|
|
||||||
private void setRange(double p0, double p1)
|
private void setRange(double p0, double p1)
|
||||||
{
|
{
|
||||||
if (p0 > p1)
|
if (p0 > p1)
|
||||||
|
@ -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>()),
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
|||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
Origin = Anchor.Centre;
|
Origin = Anchor.Centre;
|
||||||
|
|
||||||
|
// Calculated from osu!stable as 512 (default gamefield size) / 640 (default window size)
|
||||||
Size = new Vector2(0.8f);
|
Size = new Vector2(0.8f);
|
||||||
|
|
||||||
InternalChild = new Container
|
InternalChild = new Container
|
||||||
|
69
osu.Game.Tests/Visual/Menus/IntroTestScene.cs
Normal file
69
osu.Game.Tests/Visual/Menus/IntroTestScene.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Game.Screens;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Menus
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public abstract class IntroTestScene : OsuTestScene
|
||||||
|
{
|
||||||
|
public override IReadOnlyList<Type> RequiredTypes => new[]
|
||||||
|
{
|
||||||
|
typeof(StartupScreen),
|
||||||
|
typeof(IntroScreen),
|
||||||
|
typeof(OsuScreen),
|
||||||
|
typeof(IntroTestScene),
|
||||||
|
};
|
||||||
|
|
||||||
|
[Cached]
|
||||||
|
private OsuLogo logo;
|
||||||
|
|
||||||
|
protected IntroTestScene()
|
||||||
|
{
|
||||||
|
Drawable introStack = null;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Depth = float.MaxValue,
|
||||||
|
Colour = Color4.Black,
|
||||||
|
},
|
||||||
|
logo = new OsuLogo
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
RelativePositionAxes = Axes.Both,
|
||||||
|
Depth = float.MinValue,
|
||||||
|
Position = new Vector2(0.5f),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
AddStep("restart sequence", () =>
|
||||||
|
{
|
||||||
|
logo.FinishTransforms();
|
||||||
|
logo.IsTracking = false;
|
||||||
|
|
||||||
|
introStack?.Expire();
|
||||||
|
|
||||||
|
Add(introStack = new OsuScreenStack(CreateScreen())
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract IScreen CreateScreen();
|
||||||
|
}
|
||||||
|
}
|
15
osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs
Normal file
15
osu.Game.Tests/Visual/Menus/TestSceneIntroCircles.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Game.Screens.Menu;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Menus
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TestSceneIntroCircles : IntroTestScene
|
||||||
|
{
|
||||||
|
protected override IScreen CreateScreen() => new IntroCircles();
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
// 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 NUnit.Framework;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
|
||||||
using osu.Framework.Timing;
|
|
||||||
using osu.Game.Screens.Menu;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Menus
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class TestSceneIntroSequence : OsuTestScene
|
|
||||||
{
|
|
||||||
public override IReadOnlyList<Type> RequiredTypes => new[]
|
|
||||||
{
|
|
||||||
typeof(OsuLogo),
|
|
||||||
};
|
|
||||||
|
|
||||||
public TestSceneIntroSequence()
|
|
||||||
{
|
|
||||||
OsuLogo logo;
|
|
||||||
|
|
||||||
var rateAdjustClock = new StopwatchClock(true);
|
|
||||||
var framedClock = new FramedClock(rateAdjustClock);
|
|
||||||
framedClock.ProcessFrame();
|
|
||||||
|
|
||||||
Add(new Container
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Clock = framedClock,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = Color4.Black,
|
|
||||||
},
|
|
||||||
logo = new OsuLogo
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep(@"Restart", logo.PlayIntro);
|
|
||||||
AddSliderStep("Playback speed", 0.0, 2.0, 1, v => rateAdjustClock.Rate = v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -35,7 +35,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
private TestChatOverlay chatOverlay;
|
private TestChatOverlay chatOverlay;
|
||||||
private ChannelManager channelManager;
|
private ChannelManager channelManager;
|
||||||
|
|
||||||
private readonly Channel channel1 = new Channel(new User()) { Name = "test1" };
|
private readonly Channel channel1 = new Channel(new User()) { Name = "test really long username" };
|
||||||
private readonly Channel channel2 = new Channel(new User()) { Name = "test2" };
|
private readonly Channel channel2 = new Channel(new User()) { Name = "test2" };
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
@ -47,8 +47,8 @@ namespace osu.Game.Tournament.Screens.MapPool
|
|||||||
mapFlows = new FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>>
|
mapFlows = new FillFlowContainer<FillFlowContainer<TournamentBeatmapPanel>>
|
||||||
{
|
{
|
||||||
Y = 100,
|
Y = 100,
|
||||||
Spacing = new Vector2(10, 20),
|
Spacing = new Vector2(10, 10),
|
||||||
Padding = new MarginPadding(50),
|
Padding = new MarginPadding(25),
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
@ -218,7 +218,7 @@ namespace osu.Game.Tournament.Screens.MapPool
|
|||||||
{
|
{
|
||||||
mapFlows.Add(currentFlow = new FillFlowContainer<TournamentBeatmapPanel>
|
mapFlows.Add(currentFlow = new FillFlowContainer<TournamentBeatmapPanel>
|
||||||
{
|
{
|
||||||
Spacing = new Vector2(10, 20),
|
Spacing = new Vector2(10, 5),
|
||||||
Direction = FillDirection.Full,
|
Direction = FillDirection.Full,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y
|
AutoSizeAxes = Axes.Y
|
||||||
|
@ -386,7 +386,7 @@ namespace osu.Game.Beatmaps
|
|||||||
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
|
beatmap.OnlineBeatmapID = res.OnlineBeatmapID;
|
||||||
};
|
};
|
||||||
|
|
||||||
req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap}", e); };
|
req.Failure += e => { LogForModel(set, $"Online retrieval failed for {beatmap} ({e.Message})"); };
|
||||||
|
|
||||||
// intentionally blocking to limit web request concurrency
|
// intentionally blocking to limit web request concurrency
|
||||||
req.Perform(api);
|
req.Perform(api);
|
||||||
|
@ -253,7 +253,7 @@ namespace osu.Game.Database
|
|||||||
using (Stream s = reader.GetStream(file))
|
using (Stream s = reader.GetStream(file))
|
||||||
s.CopyTo(hashable);
|
s.CopyTo(hashable);
|
||||||
|
|
||||||
return hashable.ComputeSHA2Hash();
|
return hashable.Length > 0 ? hashable.ComputeSHA2Hash() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -76,7 +76,12 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
{
|
{
|
||||||
Masking = true,
|
Masking = true,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = path = new SmoothPath { RelativeSizeAxes = Axes.Both, PathRadius = 1 }
|
Child = path = new SmoothPath
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.None,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
PathRadius = 1
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
Direction = FillDirection.Horizontal,
|
Direction = FillDirection.Horizontal,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold) },
|
text = new OsuSpriteText { Font = OsuFont.GetFont(size: 14) },
|
||||||
icon = new SpriteIcon
|
icon = new SpriteIcon
|
||||||
{
|
{
|
||||||
Size = new Vector2(14),
|
Size = new Vector2(14),
|
||||||
@ -84,7 +84,11 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Current.ValueChanged += selected => { icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle; };
|
Current.ValueChanged += selected =>
|
||||||
|
{
|
||||||
|
icon.Icon = selected.NewValue ? FontAwesome.Regular.CheckCircle : FontAwesome.Regular.Circle;
|
||||||
|
text.Font = text.Font.With(weight: selected.NewValue ? FontWeight.Bold : FontWeight.Medium);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -87,7 +87,8 @@ namespace osu.Game
|
|||||||
private BackButton backButton;
|
private BackButton backButton;
|
||||||
|
|
||||||
private MainMenu menuScreen;
|
private MainMenu menuScreen;
|
||||||
private Intro introScreen;
|
|
||||||
|
private IntroScreen introScreen;
|
||||||
|
|
||||||
private Bindable<int> configRuleset;
|
private Bindable<int> configRuleset;
|
||||||
|
|
||||||
@ -589,7 +590,7 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
int recentLogCount = 0;
|
int recentLogCount = 0;
|
||||||
|
|
||||||
const double debounce = 5000;
|
const double debounce = 60000;
|
||||||
|
|
||||||
Logger.NewEntry += entry =>
|
Logger.NewEntry += entry =>
|
||||||
{
|
{
|
||||||
@ -761,7 +762,7 @@ namespace osu.Game
|
|||||||
if (introScreen == null)
|
if (introScreen == null)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!introScreen.DidLoadMenu || !(screenStack.CurrentScreen is Intro))
|
if (!introScreen.DidLoadMenu || !(screenStack.CurrentScreen is IntroScreen))
|
||||||
{
|
{
|
||||||
Scheduler.Add(introScreen.MakeCurrent);
|
Scheduler.Add(introScreen.MakeCurrent);
|
||||||
return true;
|
return true;
|
||||||
@ -796,7 +797,7 @@ namespace osu.Game
|
|||||||
{
|
{
|
||||||
switch (newScreen)
|
switch (newScreen)
|
||||||
{
|
{
|
||||||
case Intro intro:
|
case IntroScreen intro:
|
||||||
introScreen = intro;
|
introScreen = intro;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
|
|
||||||
public override bool IsSwitchable => false;
|
public override bool IsSwitchable => false;
|
||||||
|
|
||||||
|
protected override bool IsBoldWhenActive => false;
|
||||||
|
|
||||||
public ChannelSelectorTabItem()
|
public ChannelSelectorTabItem()
|
||||||
: base(new ChannelSelectorTabChannel())
|
: base(new ChannelSelectorTabChannel())
|
||||||
{
|
{
|
||||||
@ -22,7 +24,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
Icon.Alpha = 0;
|
Icon.Alpha = 0;
|
||||||
|
|
||||||
Text.Font = Text.Font.With(size: 45);
|
Text.Font = Text.Font.With(size: 45);
|
||||||
TextBold.Font = Text.Font.With(size: 45);
|
Text.Truncate = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -16,6 +16,7 @@ using osu.Game.Graphics.Sprites;
|
|||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Chat.Tabs
|
namespace osu.Game.Overlays.Chat.Tabs
|
||||||
{
|
{
|
||||||
@ -28,7 +29,6 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
public override bool IsRemovable => !Pinned;
|
public override bool IsRemovable => !Pinned;
|
||||||
|
|
||||||
protected readonly SpriteText Text;
|
protected readonly SpriteText Text;
|
||||||
protected readonly SpriteText TextBold;
|
|
||||||
protected readonly ClickableContainer CloseButton;
|
protected readonly ClickableContainer CloseButton;
|
||||||
private readonly Box box;
|
private readonly Box box;
|
||||||
private readonly Box highlightBox;
|
private readonly Box highlightBox;
|
||||||
@ -87,20 +87,17 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
},
|
},
|
||||||
Text = new OsuSpriteText
|
Text = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Margin = new MarginPadding(5),
|
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Text = value.ToString(),
|
Text = value.ToString(),
|
||||||
Font = OsuFont.GetFont(size: 18)
|
Font = OsuFont.GetFont(size: 18),
|
||||||
},
|
Padding = new MarginPadding(5)
|
||||||
TextBold = new OsuSpriteText
|
|
||||||
{
|
{
|
||||||
Alpha = 0,
|
Left = LeftTextPadding,
|
||||||
Margin = new MarginPadding(5),
|
Right = RightTextPadding,
|
||||||
Origin = Anchor.CentreLeft,
|
},
|
||||||
Anchor = Anchor.CentreLeft,
|
RelativeSizeAxes = Axes.X,
|
||||||
Text = value.ToString(),
|
Truncate = true,
|
||||||
Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold)
|
|
||||||
},
|
},
|
||||||
CloseButton = new TabCloseButton
|
CloseButton = new TabCloseButton
|
||||||
{
|
{
|
||||||
@ -118,10 +115,16 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual float LeftTextPadding => 5;
|
||||||
|
|
||||||
|
protected virtual float RightTextPadding => IsRemovable ? 40 : 5;
|
||||||
|
|
||||||
protected virtual IconUsage DisplayIcon => FontAwesome.Solid.Hashtag;
|
protected virtual IconUsage DisplayIcon => FontAwesome.Solid.Hashtag;
|
||||||
|
|
||||||
protected virtual bool ShowCloseOnHover => true;
|
protected virtual bool ShowCloseOnHover => true;
|
||||||
|
|
||||||
|
protected virtual bool IsBoldWhenActive => true;
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
{
|
{
|
||||||
if (IsRemovable && ShowCloseOnHover)
|
if (IsRemovable && ShowCloseOnHover)
|
||||||
@ -138,6 +141,19 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
updateState();
|
updateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override bool OnMouseUp(MouseUpEvent e)
|
||||||
|
{
|
||||||
|
switch (e.Button)
|
||||||
|
{
|
||||||
|
case MouseButton.Middle:
|
||||||
|
CloseButton.Click();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
@ -189,8 +205,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
box.FadeColour(BackgroundActive, TRANSITION_LENGTH, Easing.OutQuint);
|
box.FadeColour(BackgroundActive, TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
highlightBox.FadeIn(TRANSITION_LENGTH, Easing.OutQuint);
|
highlightBox.FadeIn(TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
|
||||||
Text.FadeOut(TRANSITION_LENGTH, Easing.OutQuint);
|
if (IsBoldWhenActive) Text.Font = Text.Font.With(weight: FontWeight.Bold);
|
||||||
TextBold.FadeIn(TRANSITION_LENGTH, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void FadeInactive()
|
protected virtual void FadeInactive()
|
||||||
@ -202,8 +217,7 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
box.FadeColour(BackgroundInactive, TRANSITION_LENGTH, Easing.OutQuint);
|
box.FadeColour(BackgroundInactive, TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
highlightBox.FadeOut(TRANSITION_LENGTH, Easing.OutQuint);
|
highlightBox.FadeOut(TRANSITION_LENGTH, Easing.OutQuint);
|
||||||
|
|
||||||
Text.FadeIn(TRANSITION_LENGTH, Easing.OutQuint);
|
Text.Font = Text.Font.With(weight: FontWeight.Medium);
|
||||||
TextBold.FadeOut(TRANSITION_LENGTH, Easing.OutQuint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnActivated() => updateState();
|
protected override void OnActivated() => updateState();
|
||||||
|
@ -62,11 +62,10 @@ namespace osu.Game.Overlays.Chat.Tabs
|
|||||||
});
|
});
|
||||||
|
|
||||||
avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint);
|
avatar.OnLoadComplete += d => d.FadeInFromZero(300, Easing.OutQuint);
|
||||||
|
|
||||||
Text.X = ChatOverlay.TAB_AREA_HEIGHT;
|
|
||||||
TextBold.X = ChatOverlay.TAB_AREA_HEIGHT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override float LeftTextPadding => base.LeftTextPadding + ChatOverlay.TAB_AREA_HEIGHT;
|
||||||
|
|
||||||
protected override bool ShowCloseOnHover => false;
|
protected override bool ShowCloseOnHover => false;
|
||||||
|
|
||||||
protected override void FadeActive()
|
protected override void FadeActive()
|
||||||
|
@ -148,12 +148,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
if (State.Value == newState && !force)
|
if (State.Value == newState && !force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// apply any custom state overrides
|
|
||||||
ApplyCustomUpdateState?.Invoke(this, newState);
|
|
||||||
|
|
||||||
if (newState == ArmedState.Hit)
|
|
||||||
PlaySamples();
|
|
||||||
|
|
||||||
if (UseTransformStateManagement)
|
if (UseTransformStateManagement)
|
||||||
{
|
{
|
||||||
double transformTime = HitObject.StartTime - InitialLifetimeOffset;
|
double transformTime = HitObject.StartTime - InitialLifetimeOffset;
|
||||||
@ -178,6 +172,12 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
state.Value = newState;
|
state.Value = newState;
|
||||||
|
|
||||||
UpdateState(newState);
|
UpdateState(newState);
|
||||||
|
|
||||||
|
// apply any custom state overrides
|
||||||
|
ApplyCustomUpdateState?.Invoke(this, newState);
|
||||||
|
|
||||||
|
if (newState == ArmedState.Hit)
|
||||||
|
PlaySamples();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -80,6 +80,9 @@ namespace osu.Game.Scoring.Legacy
|
|||||||
else if (version >= 20121008)
|
else if (version >= 20121008)
|
||||||
scoreInfo.OnlineScoreID = sr.ReadInt32();
|
scoreInfo.OnlineScoreID = sr.ReadInt32();
|
||||||
|
|
||||||
|
if (scoreInfo.OnlineScoreID <= 0)
|
||||||
|
scoreInfo.OnlineScoreID = null;
|
||||||
|
|
||||||
if (compressedReplay?.Length > 0)
|
if (compressedReplay?.Length > 0)
|
||||||
{
|
{
|
||||||
using (var replayInStream = new MemoryStream(compressedReplay))
|
using (var replayInStream = new MemoryStream(compressedReplay))
|
||||||
|
@ -45,7 +45,15 @@ namespace osu.Game.Screens
|
|||||||
private OsuScreen loadableScreen;
|
private OsuScreen loadableScreen;
|
||||||
private ShaderPrecompiler precompiler;
|
private ShaderPrecompiler precompiler;
|
||||||
|
|
||||||
protected virtual OsuScreen CreateLoadableScreen() => showDisclaimer ? (OsuScreen)new Disclaimer() : new Intro();
|
protected virtual OsuScreen CreateLoadableScreen()
|
||||||
|
{
|
||||||
|
if (showDisclaimer)
|
||||||
|
return new Disclaimer(getIntroSequence());
|
||||||
|
|
||||||
|
return getIntroSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntroScreen getIntroSequence() => new IntroCircles();
|
||||||
|
|
||||||
protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler();
|
protected virtual ShaderPrecompiler CreateShaderPrecompiler() => new ShaderPrecompiler();
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ namespace osu.Game.Screens.Menu
|
|||||||
{
|
{
|
||||||
public class Disclaimer : StartupScreen
|
public class Disclaimer : StartupScreen
|
||||||
{
|
{
|
||||||
private Intro intro;
|
|
||||||
private SpriteIcon icon;
|
private SpriteIcon icon;
|
||||||
private Color4 iconColour;
|
private Color4 iconColour;
|
||||||
private LinkFlowContainer textFlow;
|
private LinkFlowContainer textFlow;
|
||||||
@ -32,10 +31,13 @@ namespace osu.Game.Screens.Menu
|
|||||||
private const float icon_y = -85;
|
private const float icon_y = -85;
|
||||||
private const float icon_size = 30;
|
private const float icon_size = 30;
|
||||||
|
|
||||||
|
private readonly OsuScreen nextScreen;
|
||||||
|
|
||||||
private readonly Bindable<User> currentUser = new Bindable<User>();
|
private readonly Bindable<User> currentUser = new Bindable<User>();
|
||||||
|
|
||||||
public Disclaimer()
|
public Disclaimer(OsuScreen nextScreen = null)
|
||||||
{
|
{
|
||||||
|
this.nextScreen = nextScreen;
|
||||||
ValidForResume = false;
|
ValidForResume = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +148,8 @@ namespace osu.Game.Screens.Menu
|
|||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
LoadComponentAsync(intro = new Intro());
|
if (nextScreen != null)
|
||||||
|
LoadComponentAsync(nextScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnEntering(IScreen last)
|
public override void OnEntering(IScreen last)
|
||||||
@ -170,7 +173,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
.Then(5500)
|
.Then(5500)
|
||||||
.FadeOut(250)
|
.FadeOut(250)
|
||||||
.ScaleTo(0.9f, 250, Easing.InQuint)
|
.ScaleTo(0.9f, 250, Easing.InQuint)
|
||||||
.Finally(d => this.Push(intro));
|
.Finally(d => this.Push(nextScreen));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// 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 osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
|
||||||
using osu.Framework.Audio.Sample;
|
using osu.Framework.Audio.Sample;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@ -12,41 +11,24 @@ using osu.Framework.MathUtils;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.IO.Archives;
|
using osu.Game.IO.Archives;
|
||||||
using osu.Game.Screens.Backgrounds;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Menu
|
namespace osu.Game.Screens.Menu
|
||||||
{
|
{
|
||||||
public class Intro : StartupScreen
|
public class IntroCircles : IntroScreen
|
||||||
{
|
{
|
||||||
private const string menu_music_beatmap_hash = "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83";
|
private const string menu_music_beatmap_hash = "3c8b1fcc9434dbb29e2fb613d3b9eada9d7bb6c125ceb32396c3b53437280c83";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether we have loaded the menu previously.
|
|
||||||
/// </summary>
|
|
||||||
public bool DidLoadMenu;
|
|
||||||
|
|
||||||
private MainMenu mainMenu;
|
|
||||||
private SampleChannel welcome;
|
private SampleChannel welcome;
|
||||||
private SampleChannel seeya;
|
|
||||||
|
|
||||||
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack();
|
|
||||||
|
|
||||||
private readonly BindableDouble exitingVolumeFade = new BindableDouble(1);
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private AudioManager audio { get; set; }
|
|
||||||
|
|
||||||
private Bindable<bool> menuVoice;
|
|
||||||
private Bindable<bool> menuMusic;
|
private Bindable<bool> menuMusic;
|
||||||
|
|
||||||
private Track track;
|
private Track track;
|
||||||
|
|
||||||
private WorkingBeatmap introBeatmap;
|
private WorkingBeatmap introBeatmap;
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game)
|
private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game, ISampleStore samples)
|
||||||
{
|
{
|
||||||
menuVoice = config.GetBindable<bool>(OsuSetting.MenuVoice);
|
|
||||||
menuMusic = config.GetBindable<bool>(OsuSetting.MenuMusic);
|
menuMusic = config.GetBindable<bool>(OsuSetting.MenuMusic);
|
||||||
|
|
||||||
BeatmapSetInfo setInfo = null;
|
BeatmapSetInfo setInfo = null;
|
||||||
@ -75,15 +57,13 @@ namespace osu.Game.Screens.Menu
|
|||||||
introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
introBeatmap = beatmaps.GetWorkingBeatmap(setInfo.Beatmaps[0]);
|
||||||
track = introBeatmap.Track;
|
track = introBeatmap.Track;
|
||||||
|
|
||||||
welcome = audio.Samples.Get(@"welcome");
|
if (config.Get<bool>(OsuSetting.MenuVoice))
|
||||||
seeya = audio.Samples.Get(@"seeya");
|
welcome = samples.Get(@"welcome");
|
||||||
}
|
}
|
||||||
|
|
||||||
private const double delay_step_one = 2300;
|
private const double delay_step_one = 2300;
|
||||||
private const double delay_step_two = 600;
|
private const double delay_step_two = 600;
|
||||||
|
|
||||||
public const int EXIT_DELAY = 3000;
|
|
||||||
|
|
||||||
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||||
{
|
{
|
||||||
base.LogoArriving(logo, resuming);
|
base.LogoArriving(logo, resuming);
|
||||||
@ -93,86 +73,34 @@ namespace osu.Game.Screens.Menu
|
|||||||
Beatmap.Value = introBeatmap;
|
Beatmap.Value = introBeatmap;
|
||||||
introBeatmap = null;
|
introBeatmap = null;
|
||||||
|
|
||||||
if (menuVoice.Value)
|
welcome?.Play();
|
||||||
welcome.Play();
|
|
||||||
|
|
||||||
Scheduler.AddDelayed(delegate
|
Scheduler.AddDelayed(delegate
|
||||||
{
|
{
|
||||||
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu.
|
// Only start the current track if it is the menu music. A beatmap's track is started when entering the Main Manu.
|
||||||
if (menuMusic.Value)
|
if (menuMusic.Value)
|
||||||
{
|
{
|
||||||
track.Start();
|
track.Restart();
|
||||||
track = null;
|
track = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadComponentAsync(mainMenu = new MainMenu());
|
PrepareMenuLoad();
|
||||||
|
|
||||||
Scheduler.AddDelayed(delegate
|
Scheduler.AddDelayed(LoadMenu, delay_step_one);
|
||||||
{
|
|
||||||
DidLoadMenu = true;
|
|
||||||
this.Push(mainMenu);
|
|
||||||
}, delay_step_one);
|
|
||||||
}, delay_step_two);
|
}, delay_step_two);
|
||||||
}
|
|
||||||
|
|
||||||
logo.Colour = Color4.White;
|
|
||||||
logo.Ripple = false;
|
|
||||||
|
|
||||||
const int quick_appear = 350;
|
|
||||||
|
|
||||||
int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0;
|
|
||||||
|
|
||||||
logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint);
|
|
||||||
|
|
||||||
if (!resuming)
|
|
||||||
{
|
|
||||||
logo.ScaleTo(1);
|
logo.ScaleTo(1);
|
||||||
logo.FadeIn();
|
logo.FadeIn();
|
||||||
logo.PlayIntro();
|
logo.PlayIntro();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
logo.Triangles = false;
|
|
||||||
|
|
||||||
logo
|
|
||||||
.ScaleTo(1, initialMovementTime, Easing.OutQuint)
|
|
||||||
.FadeIn(quick_appear, Easing.OutQuint)
|
|
||||||
.Then()
|
|
||||||
.RotateTo(20, EXIT_DELAY * 1.5f)
|
|
||||||
.FadeOut(EXIT_DELAY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnSuspending(IScreen next)
|
public override void OnSuspending(IScreen next)
|
||||||
{
|
{
|
||||||
|
track = null;
|
||||||
|
|
||||||
this.FadeOut(300);
|
this.FadeOut(300);
|
||||||
base.OnSuspending(next);
|
base.OnSuspending(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool OnExiting(IScreen next)
|
|
||||||
{
|
|
||||||
//cancel exiting if we haven't loaded the menu yet.
|
|
||||||
return !DidLoadMenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnResuming(IScreen last)
|
|
||||||
{
|
|
||||||
this.FadeIn(300);
|
|
||||||
|
|
||||||
double fadeOutTime = EXIT_DELAY;
|
|
||||||
//we also handle the exit transition.
|
|
||||||
if (menuVoice.Value)
|
|
||||||
seeya.Play();
|
|
||||||
else
|
|
||||||
fadeOutTime = 500;
|
|
||||||
|
|
||||||
audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade);
|
|
||||||
this.TransformBindableTo(exitingVolumeFade, 0, fadeOutTime).OnComplete(_ => this.Exit());
|
|
||||||
|
|
||||||
//don't want to fade out completely else we will stop running updates.
|
|
||||||
Game.FadeTo(0.01f, fadeOutTime);
|
|
||||||
|
|
||||||
base.OnResuming(last);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
114
osu.Game/Screens/Menu/IntroScreen.cs
Normal file
114
osu.Game/Screens/Menu/IntroScreen.cs
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Sample;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Screens;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Screens.Backgrounds;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Menu
|
||||||
|
{
|
||||||
|
public abstract class IntroScreen : StartupScreen
|
||||||
|
{
|
||||||
|
private readonly BindableDouble exitingVolumeFade = new BindableDouble(1);
|
||||||
|
|
||||||
|
public const int EXIT_DELAY = 3000;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private AudioManager audio { get; set; }
|
||||||
|
|
||||||
|
private SampleChannel seeya;
|
||||||
|
|
||||||
|
private Bindable<bool> menuVoice;
|
||||||
|
|
||||||
|
protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuConfigManager config, BeatmapManager beatmaps, Framework.Game game)
|
||||||
|
{
|
||||||
|
menuVoice = config.GetBindable<bool>(OsuSetting.MenuVoice);
|
||||||
|
seeya = audio.Samples.Get(@"seeya");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether we have loaded the menu previously.
|
||||||
|
/// </summary>
|
||||||
|
public bool DidLoadMenu { get; private set; }
|
||||||
|
|
||||||
|
public override bool OnExiting(IScreen next)
|
||||||
|
{
|
||||||
|
//cancel exiting if we haven't loaded the menu yet.
|
||||||
|
return !DidLoadMenu;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnResuming(IScreen last)
|
||||||
|
{
|
||||||
|
this.FadeIn(300);
|
||||||
|
|
||||||
|
double fadeOutTime = EXIT_DELAY;
|
||||||
|
//we also handle the exit transition.
|
||||||
|
if (menuVoice.Value)
|
||||||
|
seeya.Play();
|
||||||
|
else
|
||||||
|
fadeOutTime = 500;
|
||||||
|
|
||||||
|
audio.AddAdjustment(AdjustableProperty.Volume, exitingVolumeFade);
|
||||||
|
this.TransformBindableTo(exitingVolumeFade, 0, fadeOutTime).OnComplete(_ => this.Exit());
|
||||||
|
|
||||||
|
//don't want to fade out completely else we will stop running updates.
|
||||||
|
Game.FadeTo(0.01f, fadeOutTime);
|
||||||
|
|
||||||
|
base.OnResuming(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LogoArriving(OsuLogo logo, bool resuming)
|
||||||
|
{
|
||||||
|
base.LogoArriving(logo, resuming);
|
||||||
|
|
||||||
|
logo.Colour = Color4.White;
|
||||||
|
logo.Triangles = false;
|
||||||
|
logo.Ripple = false;
|
||||||
|
|
||||||
|
if (!resuming)
|
||||||
|
{
|
||||||
|
logo.MoveTo(new Vector2(0.5f));
|
||||||
|
logo.ScaleTo(Vector2.One);
|
||||||
|
logo.Hide();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const int quick_appear = 350;
|
||||||
|
int initialMovementTime = logo.Alpha > 0.2f ? quick_appear : 0;
|
||||||
|
|
||||||
|
logo.MoveTo(new Vector2(0.5f), initialMovementTime, Easing.OutQuint);
|
||||||
|
|
||||||
|
logo
|
||||||
|
.ScaleTo(1, initialMovementTime, Easing.OutQuint)
|
||||||
|
.FadeIn(quick_appear, Easing.OutQuint)
|
||||||
|
.Then()
|
||||||
|
.RotateTo(20, EXIT_DELAY * 1.5f)
|
||||||
|
.FadeOut(EXIT_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MainMenu mainMenu;
|
||||||
|
|
||||||
|
protected void PrepareMenuLoad()
|
||||||
|
{
|
||||||
|
LoadComponentAsync(mainMenu = new MainMenu());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void LoadMenu()
|
||||||
|
{
|
||||||
|
DidLoadMenu = true;
|
||||||
|
this.Push(mainMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -123,7 +123,7 @@ namespace osu.Game.Screens.Menu
|
|||||||
var track = Beatmap.Value.Track;
|
var track = Beatmap.Value.Track;
|
||||||
var metadata = Beatmap.Value.Metadata;
|
var metadata = Beatmap.Value.Metadata;
|
||||||
|
|
||||||
if (last is Intro && track != null)
|
if (last is IntroScreen && track != null)
|
||||||
{
|
{
|
||||||
if (!track.IsRunning)
|
if (!track.IsRunning)
|
||||||
{
|
{
|
||||||
|
@ -212,7 +212,7 @@ namespace osu.Game.Screens.Multi
|
|||||||
|
|
||||||
public override bool OnExiting(IScreen next)
|
public override bool OnExiting(IScreen next)
|
||||||
{
|
{
|
||||||
if (!(screenStack.CurrentScreen is LoungeSubScreen))
|
if (screenStack.CurrentScreen != null && !(screenStack.CurrentScreen is LoungeSubScreen))
|
||||||
{
|
{
|
||||||
screenStack.Exit();
|
screenStack.Exit();
|
||||||
return true;
|
return true;
|
||||||
|
@ -19,11 +19,11 @@ namespace osu.Game.Screens.Play
|
|||||||
private const float remaining_time_container_max_size = 0.3f;
|
private const float remaining_time_container_max_size = 0.3f;
|
||||||
private const int vertical_margin = 25;
|
private const int vertical_margin = 25;
|
||||||
|
|
||||||
private List<BreakPeriod> breaks;
|
|
||||||
|
|
||||||
private readonly Container fadeContainer;
|
private readonly Container fadeContainer;
|
||||||
|
|
||||||
public List<BreakPeriod> Breaks
|
private IReadOnlyList<BreakPeriod> breaks;
|
||||||
|
|
||||||
|
public IReadOnlyList<BreakPeriod> Breaks
|
||||||
{
|
{
|
||||||
get => breaks;
|
get => breaks;
|
||||||
set
|
set
|
||||||
|
@ -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>
|
||||||
@ -81,7 +84,8 @@ namespace osu.Game.Screens.Select
|
|||||||
itemsCache.Invalidate();
|
itemsCache.Invalidate();
|
||||||
scrollPositionCache.Invalidate();
|
scrollPositionCache.Invalidate();
|
||||||
|
|
||||||
Schedule(() =>
|
// Run on late scheduler want to ensure this runs after all pending UpdateBeatmapSet / RemoveBeatmapSet operations are run.
|
||||||
|
SchedulerAfterChildren.Add(() =>
|
||||||
{
|
{
|
||||||
BeatmapSetsChanged?.Invoke();
|
BeatmapSetsChanged?.Invoke();
|
||||||
BeatmapSetsLoaded = true;
|
BeatmapSetsLoaded = true;
|
||||||
@ -129,9 +133,7 @@ namespace osu.Game.Screens.Select
|
|||||||
loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable());
|
loadBeatmapSets(beatmaps.GetAllUsableBeatmapSetsEnumerable());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet)
|
public void RemoveBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
|
||||||
{
|
|
||||||
Schedule(() =>
|
|
||||||
{
|
{
|
||||||
var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
|
var existingSet = beatmapSets.FirstOrDefault(b => b.BeatmapSet.ID == beatmapSet.ID);
|
||||||
|
|
||||||
@ -141,7 +143,6 @@ namespace osu.Game.Screens.Select
|
|||||||
root.RemoveChild(existingSet);
|
root.RemoveChild(existingSet);
|
||||||
itemsCache.Invalidate();
|
itemsCache.Invalidate();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
|
public void UpdateBeatmapSet(BeatmapSetInfo beatmapSet) => Schedule(() =>
|
||||||
{
|
{
|
||||||
@ -338,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)
|
||||||
@ -414,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();
|
||||||
@ -424,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;
|
||||||
@ -486,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)
|
||||||
@ -542,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;
|
||||||
@ -575,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)
|
||||||
@ -596,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))
|
||||||
@ -637,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
|
||||||
|
@ -25,22 +25,6 @@ namespace osu.Game.Screens.Select
|
|||||||
|
|
||||||
private Bindable<BeatmapDetailTab> selectedTab;
|
private Bindable<BeatmapDetailTab> selectedTab;
|
||||||
|
|
||||||
private void invokeOnFilter()
|
|
||||||
{
|
|
||||||
OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colour, OsuConfigManager config)
|
|
||||||
{
|
|
||||||
modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight;
|
|
||||||
|
|
||||||
selectedTab = config.GetBindable<BeatmapDetailTab>(OsuSetting.BeatmapDetailTab);
|
|
||||||
|
|
||||||
tabs.Current.BindTo(selectedTab);
|
|
||||||
tabs.Current.TriggerChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
public BeatmapDetailAreaTabControl()
|
public BeatmapDetailAreaTabControl()
|
||||||
{
|
{
|
||||||
Height = HEIGHT;
|
Height = HEIGHT;
|
||||||
@ -66,12 +50,31 @@ namespace osu.Game.Screens.Select
|
|||||||
Anchor = Anchor.BottomRight,
|
Anchor = Anchor.BottomRight,
|
||||||
Origin = Anchor.BottomRight,
|
Origin = Anchor.BottomRight,
|
||||||
Text = @"Mods",
|
Text = @"Mods",
|
||||||
|
Alpha = 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
tabs.Current.ValueChanged += _ => invokeOnFilter();
|
tabs.Current.ValueChanged += _ => invokeOnFilter();
|
||||||
modsCheckbox.Current.ValueChanged += _ => invokeOnFilter();
|
modsCheckbox.Current.ValueChanged += _ => invokeOnFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuColour colour, OsuConfigManager config)
|
||||||
|
{
|
||||||
|
modsCheckbox.AccentColour = tabs.AccentColour = colour.YellowLight;
|
||||||
|
|
||||||
|
selectedTab = config.GetBindable<BeatmapDetailTab>(OsuSetting.BeatmapDetailTab);
|
||||||
|
|
||||||
|
tabs.Current.BindTo(selectedTab);
|
||||||
|
tabs.Current.TriggerChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invokeOnFilter()
|
||||||
|
{
|
||||||
|
OnFilter?.Invoke(tabs.Current.Value, modsCheckbox.Current.Value);
|
||||||
|
|
||||||
|
modsCheckbox.FadeTo(tabs.Current.Value == BeatmapDetailTab.Details ? 0 : 1, 200, Easing.OutQuint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum BeatmapDetailTab
|
public enum BeatmapDetailTab
|
||||||
|
@ -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,7 +147,15 @@ namespace osu.Game.Screens.Select
|
|||||||
Width = 0.5f,
|
Width = 0.5f,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Carousel = new BeatmapCarousel
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Top = FilterControl.HEIGHT,
|
||||||
|
Bottom = Footer.HEIGHT
|
||||||
|
},
|
||||||
|
Child = Carousel = new BeatmapCarousel
|
||||||
{
|
{
|
||||||
Masking = false,
|
Masking = false,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
@ -157,10 +165,11 @@ namespace osu.Game.Screens.Select
|
|||||||
SelectionChanged = updateSelectedBeatmap,
|
SelectionChanged = updateSelectedBeatmap,
|
||||||
BeatmapSetsChanged = carouselBeatmapsLoaded,
|
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 = () =>
|
||||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
private void onChange() =>
|
private void onChange() =>
|
||||||
// schedule required to avoid calls after disposed.
|
// schedule required to avoid calls after disposed.
|
||||||
// note that this has the side-effect of components only performance a skin change when they are alive.
|
// note that this has the side-effect of components only performing a skin change when they are alive.
|
||||||
Scheduler.AddOnce(() => SkinChanged(skin, allowDefaultFallback));
|
Scheduler.AddOnce(() => SkinChanged(skin, allowDefaultFallback));
|
||||||
|
|
||||||
protected override void LoadAsyncComplete()
|
protected override void LoadAsyncComplete()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// 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;
|
||||||
@ -8,23 +8,13 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
public class SkinnableDrawable : SkinnableDrawable<Drawable>
|
|
||||||
{
|
|
||||||
public SkinnableDrawable(string name, Func<string, Drawable> defaultImplementation, Func<ISkinSource, bool> allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit)
|
|
||||||
: base(name, defaultImplementation, allowFallback, confineMode)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A drawable which can be skinned via an <see cref="ISkinSource"/>.
|
/// A drawable which can be skinned via an <see cref="ISkinSource"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The type of drawable.</typeparam>
|
public class SkinnableDrawable : SkinReloadableDrawable
|
||||||
public class SkinnableDrawable<T> : SkinReloadableDrawable
|
|
||||||
where T : Drawable
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The displayed component. May or may not be a type-<typeparamref name="T"/> member.
|
/// The displayed component.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Drawable Drawable { get; private set; }
|
protected Drawable Drawable { get; private set; }
|
||||||
|
|
||||||
@ -39,7 +29,7 @@ namespace osu.Game.Skinning
|
|||||||
/// <param name="defaultImplementation">A function to create the default skin implementation of this element.</param>
|
/// <param name="defaultImplementation">A function to create the default skin implementation of this element.</param>
|
||||||
/// <param name="allowFallback">A conditional to decide whether to allow fallback to the default implementation if a skinned element is not present.</param>
|
/// <param name="allowFallback">A conditional to decide whether to allow fallback to the default implementation if a skinned element is not present.</param>
|
||||||
/// <param name="confineMode">How (if at all) the <see cref="Drawable"/> should be resize to fit within our own bounds.</param>
|
/// <param name="confineMode">How (if at all) the <see cref="Drawable"/> should be resize to fit within our own bounds.</param>
|
||||||
public SkinnableDrawable(string name, Func<string, T> defaultImplementation, Func<ISkinSource, bool> allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit)
|
public SkinnableDrawable(string name, Func<string, Drawable> defaultImplementation, Func<ISkinSource, bool> allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit)
|
||||||
: this(name, allowFallback, confineMode)
|
: this(name, allowFallback, confineMode)
|
||||||
{
|
{
|
||||||
createDefault = defaultImplementation;
|
createDefault = defaultImplementation;
|
||||||
@ -54,13 +44,13 @@ namespace osu.Game.Skinning
|
|||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Func<string, T> createDefault;
|
private readonly Func<string, Drawable> createDefault;
|
||||||
|
|
||||||
private readonly Cached scaling = new Cached();
|
private readonly Cached scaling = new Cached();
|
||||||
|
|
||||||
private bool isDefault;
|
private bool isDefault;
|
||||||
|
|
||||||
protected virtual T CreateDefault(string name) => createDefault(name);
|
protected virtual Drawable CreateDefault(string name) => createDefault(name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether to apply size restrictions (specified via <see cref="confineMode"/>) to the default implementation.
|
/// Whether to apply size restrictions (specified via <see cref="confineMode"/>) to the default implementation.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.Textures;
|
using osu.Framework.Graphics.Textures;
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ namespace osu.Game.Skinning
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A skinnable element which uses a stable sprite and can therefore share implementation logic.
|
/// A skinnable element which uses a stable sprite and can therefore share implementation logic.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SkinnableSprite : SkinnableDrawable<Sprite>
|
public class SkinnableSprite : SkinnableDrawable
|
||||||
{
|
{
|
||||||
protected override bool ApplySizeRestrictionsToDefault => true;
|
protected override bool ApplySizeRestrictionsToDefault => true;
|
||||||
|
|
||||||
@ -23,6 +24,6 @@ namespace osu.Game.Skinning
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Sprite CreateDefault(string name) => new Sprite { Texture = textures.Get(name) };
|
protected override Drawable CreateDefault(string name) => new Sprite { Texture = textures.Get(name) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ using osu.Framework.Graphics.Sprites;
|
|||||||
|
|
||||||
namespace osu.Game.Skinning
|
namespace osu.Game.Skinning
|
||||||
{
|
{
|
||||||
public class SkinnableSpriteText : SkinnableDrawable<SpriteText>, IHasText
|
public class SkinnableSpriteText : SkinnableDrawable, IHasText
|
||||||
{
|
{
|
||||||
public SkinnableSpriteText(string name, Func<string, SpriteText> defaultImplementation, Func<ISkinSource, bool> allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit)
|
public SkinnableSpriteText(string name, Func<string, SpriteText> defaultImplementation, Func<ISkinSource, bool> allowFallback = null, ConfineMode confineMode = ConfineMode.ScaleDownToFit)
|
||||||
: base(name, defaultImplementation, allowFallback, confineMode)
|
: base(name, defaultImplementation, allowFallback, confineMode)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.4" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2019.723.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2019.729.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.23.0" />
|
<PackageReference Include="SharpCompress" Version="0.23.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.12.0" />
|
<PackageReference Include="NUnit" Version="3.12.0" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
@ -105,8 +105,8 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2019.702.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2019.723.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2019.729.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.723.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2019.729.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.22.0" />
|
<PackageReference Include="SharpCompress" Version="0.22.0" />
|
||||||
<PackageReference Include="NUnit" Version="3.11.0" />
|
<PackageReference Include="NUnit" Version="3.11.0" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
// 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.Threading.Tasks;
|
||||||
using Foundation;
|
using Foundation;
|
||||||
using osu.Framework.iOS;
|
using osu.Framework.iOS;
|
||||||
using osu.Game;
|
using osu.Game;
|
||||||
|
using UIKit;
|
||||||
|
|
||||||
namespace osu.iOS
|
namespace osu.iOS
|
||||||
{
|
{
|
||||||
[Register("AppDelegate")]
|
[Register("AppDelegate")]
|
||||||
public class AppDelegate : GameAppDelegate
|
public class AppDelegate : GameAppDelegate
|
||||||
{
|
{
|
||||||
protected override Framework.Game CreateGame() => new OsuGameIOS();
|
private OsuGameIOS game;
|
||||||
|
|
||||||
|
protected override Framework.Game CreateGame() => game = new OsuGameIOS();
|
||||||
|
|
||||||
|
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
|
||||||
|
{
|
||||||
|
Task.Run(() => game.Import(url.Path));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,5 +40,70 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>XSAppIconAssets</key>
|
<key>XSAppIconAssets</key>
|
||||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
<string>Assets.xcassets/AppIcon.appiconset</string>
|
||||||
|
<key>UTExportedTypeDeclarations</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string></string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>sh.ppy.osu.items</string>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict/>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>sh.ppy.osu.items</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>sh.ppy.osu.osr</string>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<string>osr</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>sh.ppy.osu.items</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>sh.ppy.osu.osk</string>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<string>osk</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>UTTypeConformsTo</key>
|
||||||
|
<array>
|
||||||
|
<string>sh.ppy.osu.items</string>
|
||||||
|
</array>
|
||||||
|
<key>UTTypeIdentifier</key>
|
||||||
|
<string>sh.ppy.osu.osz</string>
|
||||||
|
<key>UTTypeTagSpecification</key>
|
||||||
|
<dict>
|
||||||
|
<key>public.filename-extension</key>
|
||||||
|
<string>osz</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>LSHandlerRank</key>
|
||||||
|
<string>Owner</string>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Supported osu! files</string>
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>sh.ppy.osu.items</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
Loading…
Reference in New Issue
Block a user