mirror of
https://github.com/osukey/osukey.git
synced 2025-05-04 21:27:22 +09:00
Merge branch 'master' into fix-menu-cursor-container-allocs
This commit is contained in:
commit
df3b91d029
@ -5,6 +5,6 @@
|
|||||||
"version": "3.1.100"
|
"version": "3.1.100"
|
||||||
},
|
},
|
||||||
"msbuild-sdks": {
|
"msbuild-sdks": {
|
||||||
"Microsoft.Build.Traversal": "2.0.50"
|
"Microsoft.Build.Traversal": "2.0.52"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -52,6 +52,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.714.1" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2020.723.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests.Mods
|
|||||||
public void TestDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Droplet { StartTime = 1000 }), shouldMiss);
|
public void TestDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new Droplet { StartTime = 1000 }), shouldMiss);
|
||||||
|
|
||||||
// We only care about testing misses, hits are tested via JuiceStream
|
// We only care about testing misses, hits are tested via JuiceStream
|
||||||
[TestCase(true)]
|
[TestCase(false)]
|
||||||
public void TestTinyDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new TinyDroplet { StartTime = 1000 }), shouldMiss);
|
public void TestTinyDroplet(bool shouldMiss) => CreateHitObjectTest(new HitObjectTestData(new TinyDroplet { StartTime = 1000 }), shouldMiss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,11 @@
|
|||||||
// 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.Game.Rulesets.Catch.Judgements;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Mods
|
namespace osu.Game.Rulesets.Catch.Mods
|
||||||
{
|
{
|
||||||
public class CatchModPerfect : ModPerfect
|
public class CatchModPerfect : ModPerfect
|
||||||
{
|
{
|
||||||
protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
|
|
||||||
=> !(result.Judgement is CatchBananaJudgement)
|
|
||||||
&& base.FailCondition(healthProcessor, result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,18 +35,15 @@ namespace osu.Game.Rulesets.Catch.Replays
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override List<IInput> GetPendingInputs()
|
public override void CollectPendingInputs(List<IInput> inputs)
|
||||||
{
|
{
|
||||||
if (!Position.HasValue) return new List<IInput>();
|
if (!Position.HasValue) return;
|
||||||
|
|
||||||
return new List<IInput>
|
inputs.Add(new CatchReplayState
|
||||||
{
|
{
|
||||||
new CatchReplayState
|
PressedActions = CurrentFrame?.Actions ?? new List<CatchAction>(),
|
||||||
{
|
CatcherX = Position.Value
|
||||||
PressedActions = CurrentFrame?.Actions ?? new List<CatchAction>(),
|
});
|
||||||
CatcherX = Position.Value
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CatchReplayState : ReplayState<CatchAction>
|
public class CatchReplayState : ReplayState<CatchAction>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
@ -10,6 +11,8 @@ using osu.Game.Replays;
|
|||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mania.Objects;
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Mania.Replays;
|
using osu.Game.Rulesets.Mania.Replays;
|
||||||
|
using osu.Game.Rulesets.Mania.Scoring;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -236,6 +239,53 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
assertTailJudgement(HitResult.Meh);
|
assertTailJudgement(HitResult.Meh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMissReleaseAndHitSecondRelease()
|
||||||
|
{
|
||||||
|
var windows = new ManiaHitWindows();
|
||||||
|
windows.SetDifficulty(10);
|
||||||
|
|
||||||
|
var beatmap = new Beatmap<ManiaHitObject>
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new HoldNote
|
||||||
|
{
|
||||||
|
StartTime = 1000,
|
||||||
|
Duration = 500,
|
||||||
|
Column = 0,
|
||||||
|
},
|
||||||
|
new HoldNote
|
||||||
|
{
|
||||||
|
StartTime = 1000 + 500 + windows.WindowFor(HitResult.Miss) + 10,
|
||||||
|
Duration = 500,
|
||||||
|
Column = 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
BeatmapInfo =
|
||||||
|
{
|
||||||
|
BaseDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
SliderTickRate = 4,
|
||||||
|
OverallDifficulty = 10,
|
||||||
|
},
|
||||||
|
Ruleset = new ManiaRuleset().RulesetInfo
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
performTest(new List<ReplayFrame>
|
||||||
|
{
|
||||||
|
new ManiaReplayFrame(beatmap.HitObjects[1].StartTime, ManiaAction.Key1),
|
||||||
|
new ManiaReplayFrame(beatmap.HitObjects[1].GetEndTime()),
|
||||||
|
}, beatmap);
|
||||||
|
|
||||||
|
AddAssert("first hold note missed", () => judgementResults.Where(j => beatmap.HitObjects[0].NestedHitObjects.Contains(j.HitObject))
|
||||||
|
.All(j => j.Type == HitResult.Miss));
|
||||||
|
|
||||||
|
AddAssert("second hold note missed", () => judgementResults.Where(j => beatmap.HitObjects[1].NestedHitObjects.Contains(j.HitObject))
|
||||||
|
.All(j => j.Type == HitResult.Perfect));
|
||||||
|
}
|
||||||
|
|
||||||
private void assertHeadJudgement(HitResult result)
|
private void assertHeadJudgement(HitResult result)
|
||||||
=> AddAssert($"head judged as {result}", () => judgementResults[0].Type == result);
|
=> AddAssert($"head judged as {result}", () => judgementResults[0].Type == result);
|
||||||
|
|
||||||
@ -250,11 +300,11 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
|
|
||||||
private ScoreAccessibleReplayPlayer currentPlayer;
|
private ScoreAccessibleReplayPlayer currentPlayer;
|
||||||
|
|
||||||
private void performTest(List<ReplayFrame> frames)
|
private void performTest(List<ReplayFrame> frames, Beatmap<ManiaHitObject> beatmap = null)
|
||||||
{
|
{
|
||||||
AddStep("load player", () =>
|
if (beatmap == null)
|
||||||
{
|
{
|
||||||
Beatmap.Value = CreateWorkingBeatmap(new Beatmap<ManiaHitObject>
|
beatmap = new Beatmap<ManiaHitObject>
|
||||||
{
|
{
|
||||||
HitObjects =
|
HitObjects =
|
||||||
{
|
{
|
||||||
@ -270,9 +320,14 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 4 },
|
BaseDifficulty = new BeatmapDifficulty { SliderTickRate = 4 },
|
||||||
Ruleset = new ManiaRuleset().RulesetInfo
|
Ruleset = new ManiaRuleset().RulesetInfo
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
Beatmap.Value.Beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f });
|
beatmap.ControlPointInfo.Add(0, new DifficultyControlPoint { SpeedMultiplier = 0.1f });
|
||||||
|
}
|
||||||
|
|
||||||
|
AddStep("load player", () =>
|
||||||
|
{
|
||||||
|
Beatmap.Value = CreateWorkingBeatmap(beatmap);
|
||||||
|
|
||||||
var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } });
|
var p = new ScoreAccessibleReplayPlayer(new Score { Replay = new Replay { Frames = frames } });
|
||||||
|
|
||||||
|
@ -167,6 +167,12 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
|||||||
if (action != Action.Value)
|
if (action != Action.Value)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// The tail has a lenience applied to it which is factored into the miss window (i.e. the miss judgement will be delayed).
|
||||||
|
// But the hold cannot ever be started within the late-lenience window, so we should skip trying to begin the hold during that time.
|
||||||
|
// Note: Unlike below, we use the tail's start time to determine the time offset.
|
||||||
|
if (Time.Current > Tail.HitObject.StartTime && !Tail.HitObject.HitWindows.CanBeHit(Time.Current - Tail.HitObject.StartTime))
|
||||||
|
return false;
|
||||||
|
|
||||||
beginHoldAt(Time.Current - Head.HitObject.StartTime);
|
beginHoldAt(Time.Current - Head.HitObject.StartTime);
|
||||||
Head.UpdateResult();
|
Head.UpdateResult();
|
||||||
|
|
||||||
|
@ -18,6 +18,9 @@ namespace osu.Game.Rulesets.Mania.Replays
|
|||||||
|
|
||||||
protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any();
|
protected override bool IsImportant(ManiaReplayFrame frame) => frame.Actions.Any();
|
||||||
|
|
||||||
public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<ManiaAction> { PressedActions = CurrentFrame?.Actions ?? new List<ManiaAction>() } };
|
public override void CollectPendingInputs(List<IInput> inputs)
|
||||||
|
{
|
||||||
|
inputs.Add(new ReplayState<ManiaAction> { PressedActions = CurrentFrame?.Actions ?? new List<ManiaAction>() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
const double time_slider = 1500;
|
const double time_slider = 1500;
|
||||||
const double time_circle = 1510;
|
const double time_circle = 1510;
|
||||||
Vector2 positionCircle = Vector2.Zero;
|
Vector2 positionCircle = Vector2.Zero;
|
||||||
Vector2 positionSlider = new Vector2(80);
|
Vector2 positionSlider = new Vector2(30);
|
||||||
|
|
||||||
var hitObjects = new List<OsuHitObject>
|
var hitObjects = new List<OsuHitObject>
|
||||||
{
|
{
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
private void testSingle(float circleSize, bool auto = false)
|
private void testSingle(float circleSize, bool auto = false)
|
||||||
{
|
{
|
||||||
var spinner = new Spinner { StartTime = Time.Current + 1000, EndTime = Time.Current + 4000 };
|
var spinner = new Spinner { StartTime = Time.Current + 2000, EndTime = Time.Current + 5000 };
|
||||||
|
|
||||||
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
|
spinner.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using System.Linq;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
@ -11,6 +12,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Skinning;
|
using osu.Game.Rulesets.Osu.Skinning;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
@ -81,6 +83,42 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
foreach (var drawableHitObject in NestedHitObjects)
|
foreach (var drawableHitObject in NestedHitObjects)
|
||||||
drawableHitObject.AccentColour.Value = colour.NewValue;
|
drawableHitObject.AccentColour.Value = colour.NewValue;
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
Tracking.BindValueChanged(updateSlidingSample);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SkinnableSound slidingSample;
|
||||||
|
|
||||||
|
protected override void LoadSamples()
|
||||||
|
{
|
||||||
|
base.LoadSamples();
|
||||||
|
|
||||||
|
slidingSample?.Expire();
|
||||||
|
slidingSample = null;
|
||||||
|
|
||||||
|
var firstSample = HitObject.Samples.FirstOrDefault();
|
||||||
|
|
||||||
|
if (firstSample != null)
|
||||||
|
{
|
||||||
|
var clone = HitObject.SampleControlPoint.ApplyTo(firstSample);
|
||||||
|
clone.Name = "sliderslide";
|
||||||
|
|
||||||
|
AddInternal(slidingSample = new SkinnableSound(clone)
|
||||||
|
{
|
||||||
|
Looping = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSlidingSample(ValueChangedEvent<bool> tracking)
|
||||||
|
{
|
||||||
|
// note that samples will not start playing if exiting a seek operation in the middle of a slider.
|
||||||
|
// may be something we want to address at a later point, but not so easy to make happen right now
|
||||||
|
// (SkinnableSound would need to expose whether the sample is already playing and this logic would need to run in Update).
|
||||||
|
if (tracking.NewValue && ShouldPlaySamples)
|
||||||
|
slidingSample?.Play();
|
||||||
|
else
|
||||||
|
slidingSample?.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
protected override void AddNestedHitObject(DrawableHitObject hitObject)
|
||||||
@ -156,6 +194,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
Tracking.Value = Ball.Tracking;
|
Tracking.Value = Ball.Tracking;
|
||||||
|
|
||||||
|
if (Tracking.Value && slidingSample != null)
|
||||||
|
// keep the sliding sample playing at the current tracking position
|
||||||
|
slidingSample.Balance.Value = CalculateSamplePlaybackBalance(Ball.X / OsuPlayfield.BASE_SIZE.X);
|
||||||
|
|
||||||
double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
double completionProgress = Math.Clamp((Time.Current - slider.StartTime) / slider.Duration, 0, 1);
|
||||||
|
|
||||||
Ball.UpdateProgress(completionProgress);
|
Ball.UpdateProgress(completionProgress);
|
||||||
|
@ -23,6 +23,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
|
|
||||||
private readonly Drawable scaleContainer;
|
private readonly Drawable scaleContainer;
|
||||||
|
|
||||||
|
public override bool DisplayResult => false;
|
||||||
|
|
||||||
public DrawableSliderRepeat(SliderRepeat sliderRepeat, DrawableSlider drawableSlider)
|
public DrawableSliderRepeat(SliderRepeat sliderRepeat, DrawableSlider drawableSlider)
|
||||||
: base(sliderRepeat)
|
: base(sliderRepeat)
|
||||||
{
|
{
|
||||||
|
@ -93,7 +93,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
Background = new SpinnerBackground
|
Background = new SpinnerBackground
|
||||||
{
|
{
|
||||||
Alpha = 0.6f,
|
Disc =
|
||||||
|
{
|
||||||
|
Alpha = 0f,
|
||||||
|
},
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
},
|
},
|
||||||
@ -125,10 +128,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
normalColour = baseColour;
|
normalColour = baseColour;
|
||||||
|
completeColour = colours.YellowLight;
|
||||||
|
|
||||||
Background.AccentColour = normalColour;
|
Background.AccentColour = normalColour;
|
||||||
|
Ticks.AccentColour = normalColour;
|
||||||
completeColour = colours.YellowLight.Opacity(0.75f);
|
|
||||||
|
|
||||||
Disc.AccentColour = fillColour;
|
Disc.AccentColour = fillColour;
|
||||||
circle.Colour = colours.BlueDark;
|
circle.Colour = colours.BlueDark;
|
||||||
@ -147,16 +150,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
if (Progress >= 1 && !Disc.Complete)
|
if (Progress >= 1 && !Disc.Complete)
|
||||||
{
|
{
|
||||||
Disc.Complete = true;
|
Disc.Complete = true;
|
||||||
|
transformFillColour(completeColour, 200);
|
||||||
const float duration = 200;
|
|
||||||
|
|
||||||
Disc.FadeAccent(completeColour, duration);
|
|
||||||
|
|
||||||
Background.FadeAccent(completeColour, duration);
|
|
||||||
Background.FadeOut(duration);
|
|
||||||
|
|
||||||
circle.FadeColour(completeColour, duration);
|
|
||||||
glow.FadeColour(completeColour, duration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userTriggered || Time.Current < Spinner.EndTime)
|
if (userTriggered || Time.Current < Spinner.EndTime)
|
||||||
@ -204,32 +198,59 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
base.UpdateInitialTransforms();
|
base.UpdateInitialTransforms();
|
||||||
|
|
||||||
circleContainer.ScaleTo(Spinner.Scale * 0.3f);
|
circleContainer.ScaleTo(0);
|
||||||
circleContainer.ScaleTo(Spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint);
|
mainContainer.ScaleTo(0);
|
||||||
|
|
||||||
mainContainer
|
using (BeginDelayedSequence(HitObject.TimePreempt / 2, true))
|
||||||
.ScaleTo(0)
|
{
|
||||||
.ScaleTo(Spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint)
|
float phaseOneScale = Spinner.Scale * 0.7f;
|
||||||
.Then()
|
|
||||||
.ScaleTo(1, 500, Easing.OutQuint);
|
circleContainer.ScaleTo(phaseOneScale, HitObject.TimePreempt / 4, Easing.OutQuint);
|
||||||
|
|
||||||
|
mainContainer
|
||||||
|
.ScaleTo(phaseOneScale * circle.DrawHeight / DrawHeight * 1.6f, HitObject.TimePreempt / 4, Easing.OutQuint)
|
||||||
|
.RotateTo((float)(25 * Spinner.Duration / 2000), HitObject.TimePreempt + Spinner.Duration);
|
||||||
|
|
||||||
|
using (BeginDelayedSequence(HitObject.TimePreempt / 2, true))
|
||||||
|
{
|
||||||
|
circleContainer.ScaleTo(Spinner.Scale, 400, Easing.OutQuint);
|
||||||
|
mainContainer.ScaleTo(1, 400, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateStateTransforms(ArmedState state)
|
protected override void UpdateStateTransforms(ArmedState state)
|
||||||
{
|
{
|
||||||
base.UpdateStateTransforms(state);
|
base.UpdateStateTransforms(state);
|
||||||
|
|
||||||
var sequence = this.Delay(Spinner.Duration).FadeOut(160);
|
using (BeginDelayedSequence(Spinner.Duration, true))
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
{
|
||||||
case ArmedState.Hit:
|
this.FadeOut(160);
|
||||||
sequence.ScaleTo(Scale * 1.2f, 320, Easing.Out);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ArmedState.Miss:
|
switch (state)
|
||||||
sequence.ScaleTo(Scale * 0.8f, 320, Easing.In);
|
{
|
||||||
break;
|
case ArmedState.Hit:
|
||||||
|
transformFillColour(completeColour, 0);
|
||||||
|
this.ScaleTo(Scale * 1.2f, 320, Easing.Out);
|
||||||
|
mainContainer.RotateTo(mainContainer.Rotation + 180, 320);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ArmedState.Miss:
|
||||||
|
this.ScaleTo(Scale * 0.8f, 320, Easing.In);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void transformFillColour(Colour4 colour, double duration)
|
||||||
|
{
|
||||||
|
Disc.FadeAccent(colour, duration);
|
||||||
|
|
||||||
|
Background.FadeAccent(colour.Darken(1), duration);
|
||||||
|
Ticks.FadeAccent(colour, duration);
|
||||||
|
|
||||||
|
circle.FadeColour(colour, duration);
|
||||||
|
glow.FadeColour(colour, duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
private readonly Slider slider;
|
private readonly Slider slider;
|
||||||
private readonly Drawable followCircle;
|
private readonly Drawable followCircle;
|
||||||
private readonly DrawableSlider drawableSlider;
|
private readonly DrawableSlider drawableSlider;
|
||||||
private readonly CircularContainer ball;
|
private readonly Drawable ball;
|
||||||
|
|
||||||
public SliderBall(Slider slider, DrawableSlider drawableSlider = null)
|
public SliderBall(Slider slider, DrawableSlider drawableSlider = null)
|
||||||
{
|
{
|
||||||
@ -54,19 +54,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()),
|
Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderFollowCircle), _ => new DefaultFollowCircle()),
|
||||||
},
|
},
|
||||||
ball = new CircularContainer
|
ball = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall())
|
||||||
{
|
{
|
||||||
Masking = true,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Alpha = 1,
|
Origin = Anchor.Centre,
|
||||||
Child = new Container
|
},
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Child = new SkinnableDrawable(new OsuSkinComponent(OsuSkinComponents.SliderBall), _ => new DefaultSliderBall()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,12 +179,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
Position = newPos;
|
Position = newPos;
|
||||||
Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI);
|
ball.Rotation = -90 + (float)(-Math.Atan2(diff.X, diff.Y) * 180 / Math.PI);
|
||||||
|
|
||||||
lastPosition = newPos;
|
lastPosition = newPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FollowCircleContainer : Container
|
private class FollowCircleContainer : CircularContainer
|
||||||
{
|
{
|
||||||
public override bool HandlePositionalInput => true;
|
public override bool HandlePositionalInput => true;
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
// 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 osuTK.Graphics;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Effects;
|
using osu.Framework.Graphics.Effects;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
public class SpinnerBackground : CircularContainer, IHasAccentColour
|
public class SpinnerBackground : CircularContainer, IHasAccentColour
|
||||||
{
|
{
|
||||||
protected Box Disc;
|
public readonly Box Disc;
|
||||||
|
|
||||||
public Color4 AccentColour
|
public Color4 AccentColour
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// 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;
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -9,10 +10,11 @@ using osu.Framework.Graphics.Effects;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
||||||
{
|
{
|
||||||
public class SpinnerTicks : Container
|
public class SpinnerTicks : Container, IHasAccentColour
|
||||||
{
|
{
|
||||||
public SpinnerTicks()
|
public SpinnerTicks()
|
||||||
{
|
{
|
||||||
@ -20,28 +22,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
Anchor = Anchor.Centre;
|
Anchor = Anchor.Centre;
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
const float count = 18;
|
const float count = 8;
|
||||||
|
|
||||||
for (float i = 0; i < count; i++)
|
for (float i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
Add(new Container
|
Add(new Container
|
||||||
{
|
{
|
||||||
Colour = Color4.Black,
|
|
||||||
Alpha = 0.4f,
|
Alpha = 0.4f,
|
||||||
EdgeEffect = new EdgeEffectParameters
|
Blending = BlendingParameters.Additive,
|
||||||
{
|
|
||||||
Type = EdgeEffectType.Glow,
|
|
||||||
Radius = 10,
|
|
||||||
Colour = Color4.Gray.Opacity(0.2f),
|
|
||||||
},
|
|
||||||
RelativePositionAxes = Axes.Both,
|
RelativePositionAxes = Axes.Both,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
CornerRadius = 5,
|
CornerRadius = 5,
|
||||||
Size = new Vector2(60, 10),
|
Size = new Vector2(60, 10),
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Position = new Vector2(
|
Position = new Vector2(
|
||||||
0.5f + MathF.Sin(i / count * 2 * MathF.PI) / 2 * 0.86f,
|
0.5f + MathF.Sin(i / count * 2 * MathF.PI) / 2 * 0.83f,
|
||||||
0.5f + MathF.Cos(i / count * 2 * MathF.PI) / 2 * 0.86f
|
0.5f + MathF.Cos(i / count * 2 * MathF.PI) / 2 * 0.83f
|
||||||
),
|
),
|
||||||
Rotation = -i / count * 360 + 90,
|
Rotation = -i / count * 360 + 90,
|
||||||
Children = new[]
|
Children = new[]
|
||||||
@ -54,5 +50,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Color4 AccentColour
|
||||||
|
{
|
||||||
|
get => Colour;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Colour = value;
|
||||||
|
|
||||||
|
foreach (var c in Children.OfType<Container>())
|
||||||
|
{
|
||||||
|
c.EdgeEffect =
|
||||||
|
new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Type = EdgeEffectType.Glow,
|
||||||
|
Radius = 20,
|
||||||
|
Colour = value.Opacity(0.8f),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,19 +36,10 @@ namespace osu.Game.Rulesets.Osu.Replays
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override List<IInput> GetPendingInputs()
|
public override void CollectPendingInputs(List<IInput> inputs)
|
||||||
{
|
{
|
||||||
return new List<IInput>
|
inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(Position ?? Vector2.Zero) });
|
||||||
{
|
inputs.Add(new ReplayState<OsuAction> { PressedActions = CurrentFrame?.Actions ?? new List<OsuAction>() });
|
||||||
new MousePositionAbsoluteInput
|
|
||||||
{
|
|
||||||
Position = GamefieldToScreenSpace(Position ?? Vector2.Zero)
|
|
||||||
},
|
|
||||||
new ReplayState<OsuAction>
|
|
||||||
{
|
|
||||||
PressedActions = CurrentFrame?.Actions ?? new List<OsuAction>()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,9 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
{
|
{
|
||||||
private readonly Drawable animationContent;
|
private readonly Drawable animationContent;
|
||||||
|
|
||||||
|
private Sprite layerNd;
|
||||||
|
private Sprite layerSpec;
|
||||||
|
|
||||||
public LegacySliderBall(Drawable animationContent)
|
public LegacySliderBall(Drawable animationContent)
|
||||||
{
|
{
|
||||||
this.animationContent = animationContent;
|
this.animationContent = animationContent;
|
||||||
@ -29,18 +32,37 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
|||||||
|
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
new Sprite
|
layerNd = new Sprite
|
||||||
{
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
Texture = skin.GetTexture("sliderb-nd"),
|
Texture = skin.GetTexture("sliderb-nd"),
|
||||||
Colour = new Color4(5, 5, 5, 255),
|
Colour = new Color4(5, 5, 5, 255),
|
||||||
},
|
},
|
||||||
animationContent,
|
animationContent.With(d =>
|
||||||
new Sprite
|
|
||||||
{
|
{
|
||||||
|
d.Anchor = Anchor.Centre;
|
||||||
|
d.Origin = Anchor.Centre;
|
||||||
|
}),
|
||||||
|
layerSpec = new Sprite
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
Texture = skin.GetTexture("sliderb-spec"),
|
Texture = skin.GetTexture("sliderb-spec"),
|
||||||
Blending = BlendingParameters.Additive,
|
Blending = BlendingParameters.Additive,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void UpdateAfterChildren()
|
||||||
|
{
|
||||||
|
base.UpdateAfterChildren();
|
||||||
|
|
||||||
|
//undo rotation on layers which should not be rotated.
|
||||||
|
float appliedRotation = Parent.Rotation;
|
||||||
|
|
||||||
|
layerNd.Rotation = -appliedRotation;
|
||||||
|
layerSpec.Rotation = -appliedRotation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ namespace osu.Game.Rulesets.Taiko.Tests.Skinning
|
|||||||
|
|
||||||
assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Idle);
|
assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Idle);
|
||||||
assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Miss }, TaikoMascotAnimationState.Fail);
|
assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Miss }, TaikoMascotAnimationState.Fail);
|
||||||
assertStateAfterResult(new JudgementResult(new DrumRoll(), new TaikoDrumRollJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Fail);
|
assertStateAfterResult(new JudgementResult(new DrumRoll(), new TaikoDrumRollJudgement()) { Type = HitResult.Great }, TaikoMascotAnimationState.Idle);
|
||||||
assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Good }, TaikoMascotAnimationState.Idle);
|
assertStateAfterResult(new JudgementResult(new Hit(), new TaikoJudgement()) { Type = HitResult.Good }, TaikoMascotAnimationState.Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
};
|
};
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSpinnerDoesNotFail()
|
public void TestSpinnerDoesFail()
|
||||||
{
|
{
|
||||||
bool judged = false;
|
bool judged = false;
|
||||||
AddStep("Setup judgements", () =>
|
AddStep("Setup judgements", () =>
|
||||||
@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
|||||||
Player.ScoreProcessor.NewJudgement += b => judged = true;
|
Player.ScoreProcessor.NewJudgement += b => judged = true;
|
||||||
});
|
});
|
||||||
AddUntilStep("swell judged", () => judged);
|
AddUntilStep("swell judged", () => judged);
|
||||||
AddAssert("not failed", () => !Player.HasFailed);
|
AddAssert("failed", () => Player.HasFailed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements
|
|||||||
{
|
{
|
||||||
public class TaikoDrumRollJudgement : TaikoJudgement
|
public class TaikoDrumRollJudgement : TaikoJudgement
|
||||||
{
|
{
|
||||||
public override bool AffectsCombo => false;
|
|
||||||
|
|
||||||
protected override double HealthIncreaseFor(HitResult result)
|
protected override double HealthIncreaseFor(HitResult result)
|
||||||
{
|
{
|
||||||
// Drum rolls can be ignored with no health penalty
|
// Drum rolls can be ignored with no health penalty
|
||||||
|
@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Judgements
|
|||||||
{
|
{
|
||||||
public class TaikoSwellJudgement : TaikoJudgement
|
public class TaikoSwellJudgement : TaikoJudgement
|
||||||
{
|
{
|
||||||
public override bool AffectsCombo => false;
|
|
||||||
|
|
||||||
protected override double HealthIncreaseFor(HitResult result)
|
protected override double HealthIncreaseFor(HitResult result)
|
||||||
{
|
{
|
||||||
switch (result)
|
switch (result)
|
||||||
|
@ -18,6 +18,9 @@ namespace osu.Game.Rulesets.Taiko.Replays
|
|||||||
|
|
||||||
protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any();
|
protected override bool IsImportant(TaikoReplayFrame frame) => frame.Actions.Any();
|
||||||
|
|
||||||
public override List<IInput> GetPendingInputs() => new List<IInput> { new ReplayState<TaikoAction> { PressedActions = CurrentFrame?.Actions ?? new List<TaikoAction>() } };
|
public override void CollectPendingInputs(List<IInput> inputs)
|
||||||
|
{
|
||||||
|
inputs.Add(new ReplayState<TaikoAction> { PressedActions = CurrentFrame?.Actions ?? new List<TaikoAction>() });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,19 +173,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override List<IInput> GetPendingInputs()
|
public override void CollectPendingInputs(List<IInput> inputs)
|
||||||
{
|
{
|
||||||
return new List<IInput>
|
inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) });
|
||||||
{
|
inputs.Add(new ReplayState<TestAction> { PressedActions = CurrentFrame?.Actions ?? new List<TestAction>() });
|
||||||
new MousePositionAbsoluteInput
|
|
||||||
{
|
|
||||||
Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero)
|
|
||||||
},
|
|
||||||
new ReplayState<TestAction>
|
|
||||||
{
|
|
||||||
PressedActions = CurrentFrame?.Actions ?? new List<TestAction>()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,19 +113,10 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override List<IInput> GetPendingInputs()
|
public override void CollectPendingInputs(List<IInput> inputs)
|
||||||
{
|
{
|
||||||
return new List<IInput>
|
inputs.Add(new MousePositionAbsoluteInput { Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero) });
|
||||||
{
|
inputs.Add(new ReplayState<TestAction> { PressedActions = CurrentFrame?.Actions ?? new List<TestAction>() });
|
||||||
new MousePositionAbsoluteInput
|
|
||||||
{
|
|
||||||
Position = GamefieldToScreenSpace(CurrentFrame?.Position ?? Vector2.Zero)
|
|
||||||
},
|
|
||||||
new ReplayState<TestAction>
|
|
||||||
{
|
|
||||||
PressedActions = CurrentFrame?.Actions ?? new List<TestAction>()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -65,11 +64,11 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private void bindHandler(double delay = 0)
|
private void bindHandler(double delay = 0)
|
||||||
{
|
{
|
||||||
var roomScores = new List<RoomScore>();
|
var roomScores = new List<MultiplayerScore>();
|
||||||
|
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
{
|
{
|
||||||
roomScores.Add(new RoomScore
|
roomScores.Add(new MultiplayerScore
|
||||||
{
|
{
|
||||||
ID = i,
|
ID = i,
|
||||||
Accuracy = 0.9 - 0.01 * i,
|
Accuracy = 0.9 - 0.01 * i,
|
||||||
|
@ -30,12 +30,6 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
Add(selector = new SpotlightSelector());
|
Add(selector = new SpotlightSelector());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestVisibility()
|
|
||||||
{
|
|
||||||
AddStep("Toggle Visibility", selector.ToggleVisibility);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestLocalSpotlights()
|
public void TestLocalSpotlights()
|
||||||
{
|
{
|
||||||
|
@ -1,84 +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 NUnit.Framework;
|
|
||||||
using osu.Game.Overlays;
|
|
||||||
using osu.Game.Users;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
public class TestSceneSocialOverlay : OsuTestScene
|
|
||||||
{
|
|
||||||
protected override bool UseOnlineAPI => true;
|
|
||||||
|
|
||||||
public TestSceneSocialOverlay()
|
|
||||||
{
|
|
||||||
SocialOverlay s = new SocialOverlay
|
|
||||||
{
|
|
||||||
Users = new[]
|
|
||||||
{
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"flyte",
|
|
||||||
Id = 3103765,
|
|
||||||
Country = new Country { FlagName = @"JP" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c1.jpg",
|
|
||||||
},
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"Cookiezi",
|
|
||||||
Id = 124493,
|
|
||||||
Country = new Country { FlagName = @"KR" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c2.jpg",
|
|
||||||
},
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"Angelsim",
|
|
||||||
Id = 1777162,
|
|
||||||
Country = new Country { FlagName = @"KR" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
|
||||||
},
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"Rafis",
|
|
||||||
Id = 2558286,
|
|
||||||
Country = new Country { FlagName = @"PL" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c4.jpg",
|
|
||||||
},
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"hvick225",
|
|
||||||
Id = 50265,
|
|
||||||
Country = new Country { FlagName = @"TW" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c5.jpg",
|
|
||||||
},
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"peppy",
|
|
||||||
Id = 2,
|
|
||||||
Country = new Country { FlagName = @"AU" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
|
|
||||||
},
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"filsdelama",
|
|
||||||
Id = 2831793,
|
|
||||||
Country = new Country { FlagName = @"FR" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c7.jpg"
|
|
||||||
},
|
|
||||||
new User
|
|
||||||
{
|
|
||||||
Username = @"_index",
|
|
||||||
Id = 652457,
|
|
||||||
Country = new Country { FlagName = @"RU" },
|
|
||||||
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c8.jpg"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Add(s);
|
|
||||||
|
|
||||||
AddStep(@"toggle", s.ToggleVisibility);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -42,6 +42,19 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
Spacing = new Vector2(10f),
|
Spacing = new Vector2(10f),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
|
new UserBrickPanel(new User
|
||||||
|
{
|
||||||
|
Username = @"flyte",
|
||||||
|
Id = 3103765,
|
||||||
|
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg"
|
||||||
|
}),
|
||||||
|
new UserBrickPanel(new User
|
||||||
|
{
|
||||||
|
Username = @"peppy",
|
||||||
|
Id = 2,
|
||||||
|
Colour = "99EB47",
|
||||||
|
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
|
||||||
|
}),
|
||||||
flyte = new UserGridPanel(new User
|
flyte = new UserGridPanel(new User
|
||||||
{
|
{
|
||||||
Username = @"flyte",
|
Username = @"flyte",
|
||||||
|
@ -36,11 +36,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
addHeader("Orange OverlayHeader (no background)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange);
|
addHeader("Orange OverlayHeader (no background, 100 padding)", new TestNoBackgroundHeader(), OverlayColourScheme.Orange);
|
||||||
addHeader("Blue OverlayHeader", new TestNoControlHeader(), OverlayColourScheme.Blue);
|
addHeader("Blue OverlayHeader (default 50 padding)", new TestNoControlHeader(), OverlayColourScheme.Blue);
|
||||||
addHeader("Green TabControlOverlayHeader (string) with ruleset selector", new TestStringTabControlHeader(), OverlayColourScheme.Green);
|
addHeader("Green TabControlOverlayHeader (string) with ruleset selector", new TestStringTabControlHeader(), OverlayColourScheme.Green);
|
||||||
addHeader("Pink TabControlOverlayHeader (enum)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink);
|
addHeader("Pink TabControlOverlayHeader (enum, 30 padding)", new TestEnumTabControlHeader(), OverlayColourScheme.Pink);
|
||||||
addHeader("Red BreadcrumbControlOverlayHeader (no background)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red);
|
addHeader("Red BreadcrumbControlOverlayHeader (no background, 10 padding)", new TestBreadcrumbControlHeader(), OverlayColourScheme.Red);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addHeader(string name, OverlayHeader header, OverlayColourScheme colourScheme)
|
private void addHeader(string name, OverlayHeader header, OverlayColourScheme colourScheme)
|
||||||
@ -86,6 +86,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
private class TestNoBackgroundHeader : OverlayHeader
|
private class TestNoBackgroundHeader : OverlayHeader
|
||||||
{
|
{
|
||||||
protected override OverlayTitle CreateTitle() => new TestTitle();
|
protected override OverlayTitle CreateTitle() => new TestTitle();
|
||||||
|
|
||||||
|
public TestNoBackgroundHeader()
|
||||||
|
{
|
||||||
|
ContentSidePadding = 100;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestNoControlHeader : OverlayHeader
|
private class TestNoControlHeader : OverlayHeader
|
||||||
@ -112,6 +117,11 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
private class TestEnumTabControlHeader : TabControlOverlayHeader<TestEnum>
|
private class TestEnumTabControlHeader : TabControlOverlayHeader<TestEnum>
|
||||||
{
|
{
|
||||||
|
public TestEnumTabControlHeader()
|
||||||
|
{
|
||||||
|
ContentSidePadding = 30;
|
||||||
|
}
|
||||||
|
|
||||||
protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/rankings");
|
protected override Drawable CreateBackground() => new OverlayHeaderBackground(@"Headers/rankings");
|
||||||
|
|
||||||
protected override OverlayTitle CreateTitle() => new TestTitle();
|
protected override OverlayTitle CreateTitle() => new TestTitle();
|
||||||
@ -130,6 +140,8 @@ namespace osu.Game.Tests.Visual.UserInterface
|
|||||||
|
|
||||||
public TestBreadcrumbControlHeader()
|
public TestBreadcrumbControlHeader()
|
||||||
{
|
{
|
||||||
|
ContentSidePadding = 10;
|
||||||
|
|
||||||
TabControl.AddItem("tab1");
|
TabControl.AddItem("tab1");
|
||||||
TabControl.AddItem("tab2");
|
TabControl.AddItem("tab2");
|
||||||
TabControl.Current.Value = "tab2";
|
TabControl.Current.Value = "tab2";
|
||||||
|
@ -64,49 +64,49 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to find the difficulty control point at.</param>
|
/// <param name="time">The time to find the difficulty control point at.</param>
|
||||||
/// <returns>The difficulty control point.</returns>
|
/// <returns>The difficulty control point.</returns>
|
||||||
public DifficultyControlPoint DifficultyPointAt(double time) => binarySearchWithFallback(DifficultyPoints, time);
|
public DifficultyControlPoint DifficultyPointAt(double time) => binarySearchWithFallback(DifficultyPoints, time, DifficultyControlPoint.DEFAULT);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the effect control point that is active at <paramref name="time"/>.
|
/// Finds the effect control point that is active at <paramref name="time"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to find the effect control point at.</param>
|
/// <param name="time">The time to find the effect control point at.</param>
|
||||||
/// <returns>The effect control point.</returns>
|
/// <returns>The effect control point.</returns>
|
||||||
public EffectControlPoint EffectPointAt(double time) => binarySearchWithFallback(EffectPoints, time);
|
public EffectControlPoint EffectPointAt(double time) => binarySearchWithFallback(EffectPoints, time, EffectControlPoint.DEFAULT);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the sound control point that is active at <paramref name="time"/>.
|
/// Finds the sound control point that is active at <paramref name="time"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to find the sound control point at.</param>
|
/// <param name="time">The time to find the sound control point at.</param>
|
||||||
/// <returns>The sound control point.</returns>
|
/// <returns>The sound control point.</returns>
|
||||||
public SampleControlPoint SamplePointAt(double time) => binarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : null);
|
public SampleControlPoint SamplePointAt(double time) => binarySearchWithFallback(SamplePoints, time, SamplePoints.Count > 0 ? SamplePoints[0] : SampleControlPoint.DEFAULT);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the timing control point that is active at <paramref name="time"/>.
|
/// Finds the timing control point that is active at <paramref name="time"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="time">The time to find the timing control point at.</param>
|
/// <param name="time">The time to find the timing control point at.</param>
|
||||||
/// <returns>The timing control point.</returns>
|
/// <returns>The timing control point.</returns>
|
||||||
public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : null);
|
public TimingControlPoint TimingPointAt(double time) => binarySearchWithFallback(TimingPoints, time, TimingPoints.Count > 0 ? TimingPoints[0] : TimingControlPoint.DEFAULT);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the maximum BPM represented by any timing control point.
|
/// Finds the maximum BPM represented by any timing control point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public double BPMMaximum =>
|
public double BPMMaximum =>
|
||||||
60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength;
|
60000 / (TimingPoints.OrderBy(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the minimum BPM represented by any timing control point.
|
/// Finds the minimum BPM represented by any timing control point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public double BPMMinimum =>
|
public double BPMMinimum =>
|
||||||
60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? new TimingControlPoint()).BeatLength;
|
60000 / (TimingPoints.OrderByDescending(c => c.BeatLength).FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finds the mode BPM (most common BPM) represented by the control points.
|
/// Finds the mode BPM (most common BPM) represented by the control points.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public double BPMMode =>
|
public double BPMMode =>
|
||||||
60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? new TimingControlPoint()).BeatLength;
|
60000 / (TimingPoints.GroupBy(c => c.BeatLength).OrderByDescending(grp => grp.Count()).FirstOrDefault()?.FirstOrDefault() ?? TimingControlPoint.DEFAULT).BeatLength;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Remove all <see cref="ControlPointGroup"/>s and return to a pristine state.
|
/// Remove all <see cref="ControlPointGroup"/>s and return to a pristine state.
|
||||||
@ -170,12 +170,12 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="list">The list to search.</param>
|
/// <param name="list">The list to search.</param>
|
||||||
/// <param name="time">The time to find the control point at.</param>
|
/// <param name="time">The time to find the control point at.</param>
|
||||||
/// <param name="prePoint">The control point to use when <paramref name="time"/> is before any control points. If null, a new control point will be constructed.</param>
|
/// <param name="fallback">The control point to use when <paramref name="time"/> is before any control points.</param>
|
||||||
/// <returns>The active control point at <paramref name="time"/>, or a fallback <see cref="ControlPoint"/> if none found.</returns>
|
/// <returns>The active control point at <paramref name="time"/>, or a fallback <see cref="ControlPoint"/> if none found.</returns>
|
||||||
private T binarySearchWithFallback<T>(IReadOnlyList<T> list, double time, T prePoint = null)
|
private T binarySearchWithFallback<T>(IReadOnlyList<T> list, double time, T fallback)
|
||||||
where T : ControlPoint, new()
|
where T : ControlPoint
|
||||||
{
|
{
|
||||||
return binarySearch(list, time) ?? prePoint ?? new T();
|
return binarySearch(list, time) ?? fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -7,6 +7,11 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
{
|
{
|
||||||
public class DifficultyControlPoint : ControlPoint
|
public class DifficultyControlPoint : ControlPoint
|
||||||
{
|
{
|
||||||
|
public static readonly DifficultyControlPoint DEFAULT = new DifficultyControlPoint
|
||||||
|
{
|
||||||
|
SpeedMultiplierBindable = { Disabled = true },
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The speed multiplier at this control point.
|
/// The speed multiplier at this control point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -7,6 +7,12 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
{
|
{
|
||||||
public class EffectControlPoint : ControlPoint
|
public class EffectControlPoint : ControlPoint
|
||||||
{
|
{
|
||||||
|
public static readonly EffectControlPoint DEFAULT = new EffectControlPoint
|
||||||
|
{
|
||||||
|
KiaiModeBindable = { Disabled = true },
|
||||||
|
OmitFirstBarLineBindable = { Disabled = true }
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the first bar line of this control point is ignored.
|
/// Whether the first bar line of this control point is ignored.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -10,6 +10,12 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
{
|
{
|
||||||
public const string DEFAULT_BANK = "normal";
|
public const string DEFAULT_BANK = "normal";
|
||||||
|
|
||||||
|
public static readonly SampleControlPoint DEFAULT = new SampleControlPoint
|
||||||
|
{
|
||||||
|
SampleBankBindable = { Disabled = true },
|
||||||
|
SampleVolumeBindable = { Disabled = true }
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default sample bank at this control point.
|
/// The default sample bank at this control point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -13,6 +13,21 @@ namespace osu.Game.Beatmaps.ControlPoints
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple };
|
public readonly Bindable<TimeSignatures> TimeSignatureBindable = new Bindable<TimeSignatures>(TimeSignatures.SimpleQuadruple) { Default = TimeSignatures.SimpleQuadruple };
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing.
|
||||||
|
/// </summary>
|
||||||
|
private const double default_beat_length = 60000.0 / 60.0;
|
||||||
|
|
||||||
|
public static readonly TimingControlPoint DEFAULT = new TimingControlPoint
|
||||||
|
{
|
||||||
|
BeatLengthBindable =
|
||||||
|
{
|
||||||
|
Value = default_beat_length,
|
||||||
|
Disabled = true
|
||||||
|
},
|
||||||
|
TimeSignatureBindable = { Disabled = true }
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The time signature at this control point.
|
/// The time signature at this control point.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -43,14 +43,6 @@ namespace osu.Game.Graphics.Containers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double MinimumBeatLength { get; set; }
|
public double MinimumBeatLength { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Default length of a beat in milliseconds. Used whenever there is no beatmap or track playing.
|
|
||||||
/// </summary>
|
|
||||||
private const double default_beat_length = 60000.0 / 60.0;
|
|
||||||
|
|
||||||
private TimingControlPoint defaultTiming;
|
|
||||||
private EffectControlPoint defaultEffect;
|
|
||||||
|
|
||||||
protected bool IsBeatSyncedWithTrack { get; private set; }
|
protected bool IsBeatSyncedWithTrack { get; private set; }
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
@ -81,8 +73,8 @@ namespace osu.Game.Graphics.Containers
|
|||||||
if (timingPoint == null || !IsBeatSyncedWithTrack)
|
if (timingPoint == null || !IsBeatSyncedWithTrack)
|
||||||
{
|
{
|
||||||
currentTrackTime = Clock.CurrentTime;
|
currentTrackTime = Clock.CurrentTime;
|
||||||
timingPoint = defaultTiming;
|
timingPoint = TimingControlPoint.DEFAULT;
|
||||||
effectPoint = defaultEffect;
|
effectPoint = EffectControlPoint.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
double beatLength = timingPoint.BeatLength / Divisor;
|
double beatLength = timingPoint.BeatLength / Divisor;
|
||||||
@ -116,17 +108,6 @@ namespace osu.Game.Graphics.Containers
|
|||||||
private void load(IBindable<WorkingBeatmap> beatmap)
|
private void load(IBindable<WorkingBeatmap> beatmap)
|
||||||
{
|
{
|
||||||
Beatmap.BindTo(beatmap);
|
Beatmap.BindTo(beatmap);
|
||||||
|
|
||||||
defaultTiming = new TimingControlPoint
|
|
||||||
{
|
|
||||||
BeatLength = default_beat_length,
|
|
||||||
};
|
|
||||||
|
|
||||||
defaultEffect = new EffectControlPoint
|
|
||||||
{
|
|
||||||
KiaiMode = false,
|
|
||||||
OmitFirstBarLine = false
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
protected virtual void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes)
|
||||||
|
@ -67,6 +67,8 @@ namespace osu.Game.Graphics.UserInterface
|
|||||||
|
|
||||||
public bool OnPressed(GlobalAction action)
|
public bool OnPressed(GlobalAction action)
|
||||||
{
|
{
|
||||||
|
if (!HasFocus) return false;
|
||||||
|
|
||||||
if (action == GlobalAction.Back)
|
if (action == GlobalAction.Back)
|
||||||
{
|
{
|
||||||
if (Text.Length > 0)
|
if (Text.Length > 0)
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
// 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 Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Game.Online.Multiplayer;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests.Responses
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class APICreatedRoom : Room
|
public class APICreatedRoom : Room
|
||||||
{
|
{
|
@ -6,7 +6,7 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
namespace osu.Game.Online.API
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class APIPlaylistBeatmap : APIBeatmap
|
public class APIPlaylistBeatmap : APIBeatmap
|
||||||
{
|
{
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests.Responses
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class APIScoreToken
|
public class APIScoreToken
|
||||||
{
|
{
|
@ -4,10 +4,9 @@
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Multiplayer;
|
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class CreateRoomRequest : APIRequest<APICreatedRoom>
|
public class CreateRoomRequest : APIRequest<APICreatedRoom>
|
||||||
{
|
{
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class CreateRoomScoreRequest : APIRequest<APIScoreToken>
|
public class CreateRoomScoreRequest : APIRequest<APIScoreToken>
|
||||||
{
|
{
|
@ -3,8 +3,9 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class GetRoomPlaylistScoresRequest : APIRequest<RoomPlaylistScores>
|
public class GetRoomPlaylistScoresRequest : APIRequest<RoomPlaylistScores>
|
||||||
{
|
{
|
||||||
@ -23,6 +24,6 @@ namespace osu.Game.Online.API.Requests
|
|||||||
public class RoomPlaylistScores
|
public class RoomPlaylistScores
|
||||||
{
|
{
|
||||||
[JsonProperty("scores")]
|
[JsonProperty("scores")]
|
||||||
public List<RoomScore> Scores { get; set; }
|
public List<MultiplayerScore> Scores { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
// 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.Game.Online.Multiplayer;
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class GetRoomRequest : APIRequest<Room>
|
public class GetRoomRequest : APIRequest<Room>
|
||||||
{
|
{
|
@ -2,9 +2,10 @@
|
|||||||
// 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.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class GetRoomScoresRequest : APIRequest<List<APIUserScoreAggregate>>
|
public class GetRoomScoresRequest : APIRequest<List<APIUserScoreAggregate>>
|
||||||
{
|
{
|
@ -4,10 +4,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Humanizer;
|
using Humanizer;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Screens.Multi.Lounge.Components;
|
using osu.Game.Screens.Multi.Lounge.Components;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class GetRoomsRequest : APIRequest<List<Room>>
|
public class GetRoomsRequest : APIRequest<List<Room>>
|
||||||
{
|
{
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class JoinRoomRequest : APIRequest
|
public class JoinRoomRequest : APIRequest
|
||||||
{
|
{
|
@ -6,15 +6,15 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Online.API
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class RoomScore
|
public class MultiplayerScore
|
||||||
{
|
{
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
public int ID { get; set; }
|
public int ID { get; set; }
|
@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.API;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class PartRoomRequest : APIRequest
|
public class PartRoomRequest : APIRequest
|
||||||
{
|
{
|
@ -4,11 +4,12 @@
|
|||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using osu.Framework.IO.Network;
|
using osu.Framework.IO.Network;
|
||||||
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Online.API.Requests
|
namespace osu.Game.Online.Multiplayer
|
||||||
{
|
{
|
||||||
public class SubmitRoomScoreRequest : APIRequest<RoomScore>
|
public class SubmitRoomScoreRequest : APIRequest<MultiplayerScore>
|
||||||
{
|
{
|
||||||
private readonly int scoreId;
|
private readonly int scoreId;
|
||||||
private readonly int roomId;
|
private readonly int roomId;
|
@ -63,7 +63,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
private ChannelManager channelManager;
|
private ChannelManager channelManager;
|
||||||
|
|
||||||
private NotificationOverlay notifications;
|
[NotNull]
|
||||||
|
private readonly NotificationOverlay notifications = new NotificationOverlay();
|
||||||
|
|
||||||
private NowPlayingOverlay nowPlaying;
|
private NowPlayingOverlay nowPlaying;
|
||||||
|
|
||||||
@ -82,7 +83,7 @@ namespace osu.Game
|
|||||||
|
|
||||||
public virtual Storage GetStorageForStableInstall() => null;
|
public virtual Storage GetStorageForStableInstall() => null;
|
||||||
|
|
||||||
public float ToolbarOffset => Toolbar.Position.Y + Toolbar.DrawHeight;
|
public float ToolbarOffset => (Toolbar?.Position.Y ?? 0) + (Toolbar?.DrawHeight ?? 0);
|
||||||
|
|
||||||
private IdleTracker idleTracker;
|
private IdleTracker idleTracker;
|
||||||
|
|
||||||
@ -250,7 +251,7 @@ namespace osu.Game
|
|||||||
case LinkAction.OpenEditorTimestamp:
|
case LinkAction.OpenEditorTimestamp:
|
||||||
case LinkAction.JoinMultiplayerMatch:
|
case LinkAction.JoinMultiplayerMatch:
|
||||||
case LinkAction.Spectate:
|
case LinkAction.Spectate:
|
||||||
waitForReady(() => notifications, _ => notifications?.Post(new SimpleNotification
|
waitForReady(() => notifications, _ => notifications.Post(new SimpleNotification
|
||||||
{
|
{
|
||||||
Text = @"This link type is not yet supported!",
|
Text = @"This link type is not yet supported!",
|
||||||
Icon = FontAwesome.Solid.LifeRing,
|
Icon = FontAwesome.Solid.LifeRing,
|
||||||
@ -536,14 +537,14 @@ namespace osu.Game
|
|||||||
MenuCursorContainer.CanShowCursor = menuScreen?.CursorVisible ?? false;
|
MenuCursorContainer.CanShowCursor = menuScreen?.CursorVisible ?? false;
|
||||||
|
|
||||||
// todo: all archive managers should be able to be looped here.
|
// todo: all archive managers should be able to be looped here.
|
||||||
SkinManager.PostNotification = n => notifications?.Post(n);
|
SkinManager.PostNotification = n => notifications.Post(n);
|
||||||
SkinManager.GetStableStorage = GetStorageForStableInstall;
|
SkinManager.GetStableStorage = GetStorageForStableInstall;
|
||||||
|
|
||||||
BeatmapManager.PostNotification = n => notifications?.Post(n);
|
BeatmapManager.PostNotification = n => notifications.Post(n);
|
||||||
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
BeatmapManager.GetStableStorage = GetStorageForStableInstall;
|
||||||
BeatmapManager.PresentImport = items => PresentBeatmap(items.First());
|
BeatmapManager.PresentImport = items => PresentBeatmap(items.First());
|
||||||
|
|
||||||
ScoreManager.PostNotification = n => notifications?.Post(n);
|
ScoreManager.PostNotification = n => notifications.Post(n);
|
||||||
ScoreManager.GetStableStorage = GetStorageForStableInstall;
|
ScoreManager.GetStableStorage = GetStorageForStableInstall;
|
||||||
ScoreManager.PresentImport = items => PresentScore(items.First());
|
ScoreManager.PresentImport = items => PresentScore(items.First());
|
||||||
|
|
||||||
@ -615,12 +616,12 @@ namespace osu.Game
|
|||||||
|
|
||||||
loadComponentSingleFile(MusicController = new MusicController(), Add, true);
|
loadComponentSingleFile(MusicController = new MusicController(), Add, true);
|
||||||
|
|
||||||
loadComponentSingleFile(notifications = new NotificationOverlay
|
loadComponentSingleFile(notifications.With(d =>
|
||||||
{
|
{
|
||||||
GetToolbarHeight = () => ToolbarOffset,
|
d.GetToolbarHeight = () => ToolbarOffset;
|
||||||
Anchor = Anchor.TopRight,
|
d.Anchor = Anchor.TopRight;
|
||||||
Origin = Anchor.TopRight,
|
d.Origin = Anchor.TopRight;
|
||||||
}, rightFloatingOverlayContent.Add, true);
|
}), rightFloatingOverlayContent.Add, true);
|
||||||
|
|
||||||
loadComponentSingleFile(screenshotManager, Add);
|
loadComponentSingleFile(screenshotManager, Add);
|
||||||
|
|
||||||
|
@ -225,6 +225,9 @@ namespace osu.Game.Overlays.Dashboard.Friends
|
|||||||
|
|
||||||
case OverlayPanelDisplayStyle.List:
|
case OverlayPanelDisplayStyle.List:
|
||||||
return new UserListPanel(user);
|
return new UserListPanel(user);
|
||||||
|
|
||||||
|
case OverlayPanelDisplayStyle.Brick:
|
||||||
|
return new UserBrickPanel(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,9 +12,26 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
public abstract class OverlayHeader : Container
|
public abstract class OverlayHeader : Container
|
||||||
{
|
{
|
||||||
public const int CONTENT_X_MARGIN = 50;
|
private float contentSidePadding;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Horizontal padding of the header content.
|
||||||
|
/// </summary>
|
||||||
|
protected float ContentSidePadding
|
||||||
|
{
|
||||||
|
get => contentSidePadding;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
contentSidePadding = value;
|
||||||
|
content.Padding = new MarginPadding
|
||||||
|
{
|
||||||
|
Horizontal = value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly Box titleBackground;
|
private readonly Box titleBackground;
|
||||||
|
private readonly Container content;
|
||||||
|
|
||||||
protected readonly FillFlowContainer HeaderInfo;
|
protected readonly FillFlowContainer HeaderInfo;
|
||||||
|
|
||||||
@ -50,14 +67,10 @@ namespace osu.Game.Overlays
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.Gray,
|
Colour = Color4.Gray,
|
||||||
},
|
},
|
||||||
new Container
|
content = new Container
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Padding = new MarginPadding
|
|
||||||
{
|
|
||||||
Horizontal = CONTENT_X_MARGIN,
|
|
||||||
},
|
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
CreateTitle().With(title =>
|
CreateTitle().With(title =>
|
||||||
@ -79,6 +92,8 @@ namespace osu.Game.Overlays
|
|||||||
CreateContent()
|
CreateContent()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ContentSidePadding = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -34,6 +34,10 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
Icon = FontAwesome.Solid.Bars
|
Icon = FontAwesome.Solid.Bars
|
||||||
});
|
});
|
||||||
|
AddTabItem(new PanelDisplayTabItem(OverlayPanelDisplayStyle.Brick)
|
||||||
|
{
|
||||||
|
Icon = FontAwesome.Solid.Th
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer
|
protected override TabFillFlowContainer CreateTabFlow() => new TabFillFlowContainer
|
||||||
@ -96,6 +100,7 @@ namespace osu.Game.Overlays
|
|||||||
public enum OverlayPanelDisplayStyle
|
public enum OverlayPanelDisplayStyle
|
||||||
{
|
{
|
||||||
Card,
|
Card,
|
||||||
List
|
List,
|
||||||
|
Brick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ namespace osu.Game.Overlays.Profile
|
|||||||
|
|
||||||
public ProfileHeader()
|
public ProfileHeader()
|
||||||
{
|
{
|
||||||
|
ContentSidePadding = UserProfileOverlay.CONTENT_X_MARGIN;
|
||||||
|
|
||||||
User.ValueChanged += e => updateDisplay(e.NewValue);
|
User.ValueChanged += e => updateDisplay(e.NewValue);
|
||||||
|
|
||||||
TabControl.AddItem("info");
|
TabControl.AddItem("info");
|
||||||
|
@ -18,10 +18,8 @@ using osu.Game.Online.API.Requests;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Rankings
|
namespace osu.Game.Overlays.Rankings
|
||||||
{
|
{
|
||||||
public class SpotlightSelector : VisibilityContainer, IHasCurrentValue<APISpotlight>
|
public class SpotlightSelector : CompositeDrawable, IHasCurrentValue<APISpotlight>
|
||||||
{
|
{
|
||||||
private const int duration = 300;
|
|
||||||
|
|
||||||
private readonly BindableWithCurrent<APISpotlight> current = new BindableWithCurrent<APISpotlight>();
|
private readonly BindableWithCurrent<APISpotlight> current = new BindableWithCurrent<APISpotlight>();
|
||||||
public readonly Bindable<RankingsSortCriteria> Sort = new Bindable<RankingsSortCriteria>();
|
public readonly Bindable<RankingsSortCriteria> Sort = new Bindable<RankingsSortCriteria>();
|
||||||
|
|
||||||
@ -37,10 +35,7 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
set => dropdown.Items = value;
|
set => dropdown.Items = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool StartHidden => true;
|
|
||||||
|
|
||||||
private readonly Box background;
|
private readonly Box background;
|
||||||
private readonly Container content;
|
|
||||||
private readonly SpotlightsDropdown dropdown;
|
private readonly SpotlightsDropdown dropdown;
|
||||||
private readonly InfoColumn startDateColumn;
|
private readonly InfoColumn startDateColumn;
|
||||||
private readonly InfoColumn endDateColumn;
|
private readonly InfoColumn endDateColumn;
|
||||||
@ -51,73 +46,68 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
Add(content = new Container
|
InternalChildren = new Drawable[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
background = new Box
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
background = new Box
|
RelativeSizeAxes = Axes.Both,
|
||||||
{
|
},
|
||||||
RelativeSizeAxes = Axes.Both,
|
new Container
|
||||||
},
|
{
|
||||||
new Container
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN },
|
||||||
|
Child = new FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN },
|
Direction = FillDirection.Vertical,
|
||||||
Child = new FillFlowContainer
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
new Container
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
new Container
|
Margin = new MarginPadding { Vertical = 20 },
|
||||||
{
|
RelativeSizeAxes = Axes.X,
|
||||||
Margin = new MarginPadding { Vertical = 20 },
|
Height = 40,
|
||||||
RelativeSizeAxes = Axes.X,
|
Depth = -float.MaxValue,
|
||||||
Height = 40,
|
Child = dropdown = new SpotlightsDropdown
|
||||||
Depth = -float.MaxValue,
|
|
||||||
Child = dropdown = new SpotlightsDropdown
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Current = Current
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Container
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
AutoSizeAxes = Axes.Y,
|
Current = Current
|
||||||
Children = new Drawable[]
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
new FillFlowContainer
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(10, 0),
|
||||||
|
Margin = new MarginPadding { Bottom = 5 },
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both,
|
startDateColumn = new InfoColumn(@"Start Date"),
|
||||||
Direction = FillDirection.Horizontal,
|
endDateColumn = new InfoColumn(@"End Date"),
|
||||||
Spacing = new Vector2(10, 0),
|
mapCountColumn = new InfoColumn(@"Map Count"),
|
||||||
Margin = new MarginPadding { Bottom = 5 },
|
participantsColumn = new InfoColumn(@"Participants")
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
startDateColumn = new InfoColumn(@"Start Date"),
|
|
||||||
endDateColumn = new InfoColumn(@"End Date"),
|
|
||||||
mapCountColumn = new InfoColumn(@"Map Count"),
|
|
||||||
participantsColumn = new InfoColumn(@"Participants")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new RankingsSortTabControl
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
Current = Sort
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
new RankingsSortTabControl
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Current = Sort
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -134,10 +124,6 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
participantsColumn.Value = response.Spotlight.Participants?.ToString("N0");
|
participantsColumn.Value = response.Spotlight.Participants?.ToString("N0");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PopIn() => content.FadeIn(duration, Easing.OutQuint);
|
|
||||||
|
|
||||||
protected override void PopOut() => content.FadeOut(duration, Easing.OutQuint);
|
|
||||||
|
|
||||||
private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd");
|
private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd");
|
||||||
|
|
||||||
private class InfoColumn : FillFlowContainer
|
private class InfoColumn : FillFlowContainer
|
||||||
|
@ -81,8 +81,6 @@ namespace osu.Game.Overlays.Rankings
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
selector.Show();
|
|
||||||
|
|
||||||
selectedSpotlight.BindValueChanged(_ => onSpotlightChanged());
|
selectedSpotlight.BindValueChanged(_ => onSpotlightChanged());
|
||||||
sort.BindValueChanged(_ => onSpotlightChanged());
|
sort.BindValueChanged(_ => onSpotlightChanged());
|
||||||
Ruleset.BindValueChanged(onRulesetChanged);
|
Ruleset.BindValueChanged(onRulesetChanged);
|
||||||
|
@ -33,7 +33,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuColour colours { get; set; }
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
private UserPanel panel;
|
private UserGridPanel panel;
|
||||||
private UserDropdown dropdown;
|
private UserDropdown dropdown;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -1,33 +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 osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Game.Overlays.SearchableList;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Social
|
|
||||||
{
|
|
||||||
public class FilterControl : SearchableListFilterControl<SocialSortCriteria, SortDirection>
|
|
||||||
{
|
|
||||||
protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"47253a");
|
|
||||||
protected override SocialSortCriteria DefaultTab => SocialSortCriteria.Rank;
|
|
||||||
protected override SortDirection DefaultCategory => SortDirection.Ascending;
|
|
||||||
|
|
||||||
public FilterControl()
|
|
||||||
{
|
|
||||||
Tabs.Margin = new MarginPadding { Top = 10 };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SocialSortCriteria
|
|
||||||
{
|
|
||||||
Rank,
|
|
||||||
Name,
|
|
||||||
Location,
|
|
||||||
//[Description("Time Zone")]
|
|
||||||
//TimeZone,
|
|
||||||
//[Description("World Map")]
|
|
||||||
//WorldMap,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +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 osu.Game.Overlays.SearchableList;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Social
|
|
||||||
{
|
|
||||||
public class Header : SearchableListHeader<SocialTab>
|
|
||||||
{
|
|
||||||
private OsuSpriteText browser;
|
|
||||||
|
|
||||||
protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"38202e");
|
|
||||||
|
|
||||||
protected override SocialTab DefaultTab => SocialTab.AllPlayers;
|
|
||||||
protected override IconUsage Icon => FontAwesome.Solid.Users;
|
|
||||||
|
|
||||||
protected override Drawable CreateHeaderText()
|
|
||||||
{
|
|
||||||
return new FillFlowContainer
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Children = new[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = "social ",
|
|
||||||
Font = OsuFont.GetFont(size: 25),
|
|
||||||
},
|
|
||||||
browser = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = "browser",
|
|
||||||
Font = OsuFont.GetFont(size: 25, weight: FontWeight.Light),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuColour colours)
|
|
||||||
{
|
|
||||||
browser.Colour = colours.Pink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SocialTab
|
|
||||||
{
|
|
||||||
[Description("All Players")]
|
|
||||||
AllPlayers,
|
|
||||||
|
|
||||||
[Description("Friends")]
|
|
||||||
Friends,
|
|
||||||
//[Description("Team Members")]
|
|
||||||
//TeamMembers,
|
|
||||||
//[Description("Chat Channels")]
|
|
||||||
//ChatChannels,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,242 +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 System.Linq;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Overlays.SearchableList;
|
|
||||||
using osu.Game.Overlays.Social;
|
|
||||||
using osu.Game.Users;
|
|
||||||
using System.Threading;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
|
||||||
using osu.Framework.Threading;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays
|
|
||||||
{
|
|
||||||
public class SocialOverlay : SearchableListOverlay<SocialTab, SocialSortCriteria, SortDirection>
|
|
||||||
{
|
|
||||||
private readonly LoadingSpinner loading;
|
|
||||||
private FillFlowContainer<UserPanel> panels;
|
|
||||||
|
|
||||||
protected override Color4 BackgroundColour => Color4Extensions.FromHex(@"60284b");
|
|
||||||
protected override Color4 TrianglesColourLight => Color4Extensions.FromHex(@"672b51");
|
|
||||||
protected override Color4 TrianglesColourDark => Color4Extensions.FromHex(@"5c2648");
|
|
||||||
|
|
||||||
protected override SearchableListHeader<SocialTab> CreateHeader() => new Header();
|
|
||||||
protected override SearchableListFilterControl<SocialSortCriteria, SortDirection> CreateFilterControl() => new FilterControl();
|
|
||||||
|
|
||||||
private User[] users = Array.Empty<User>();
|
|
||||||
|
|
||||||
public User[] Users
|
|
||||||
{
|
|
||||||
get => users;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (users == value)
|
|
||||||
return;
|
|
||||||
|
|
||||||
users = value ?? Array.Empty<User>();
|
|
||||||
|
|
||||||
if (LoadState >= LoadState.Ready)
|
|
||||||
recreatePanels();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SocialOverlay()
|
|
||||||
: base(OverlayColourScheme.Pink)
|
|
||||||
{
|
|
||||||
Add(loading = new LoadingSpinner());
|
|
||||||
|
|
||||||
Filter.Search.Current.ValueChanged += text =>
|
|
||||||
{
|
|
||||||
if (!string.IsNullOrEmpty(text.NewValue))
|
|
||||||
{
|
|
||||||
// force searching in players until searching for friends is supported
|
|
||||||
Header.Tabs.Current.Value = SocialTab.AllPlayers;
|
|
||||||
|
|
||||||
if (Filter.Tabs.Current.Value != SocialSortCriteria.Rank)
|
|
||||||
Filter.Tabs.Current.Value = SocialSortCriteria.Rank;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Header.Tabs.Current.ValueChanged += _ => queueUpdate();
|
|
||||||
Filter.Tabs.Current.ValueChanged += _ => onFilterUpdate();
|
|
||||||
|
|
||||||
Filter.DisplayStyleControl.DisplayStyle.ValueChanged += _ => recreatePanels();
|
|
||||||
Filter.Dropdown.Current.ValueChanged += _ => recreatePanels();
|
|
||||||
|
|
||||||
currentQuery.BindTo(Filter.Search.Current);
|
|
||||||
currentQuery.ValueChanged += query =>
|
|
||||||
{
|
|
||||||
queryChangedDebounce?.Cancel();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(query.NewValue))
|
|
||||||
queueUpdate();
|
|
||||||
else
|
|
||||||
queryChangedDebounce = Scheduler.AddDelayed(updateSearch, 500);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load()
|
|
||||||
{
|
|
||||||
recreatePanels();
|
|
||||||
}
|
|
||||||
|
|
||||||
private APIRequest getUsersRequest;
|
|
||||||
|
|
||||||
private readonly Bindable<string> currentQuery = new Bindable<string>();
|
|
||||||
|
|
||||||
private ScheduledDelegate queryChangedDebounce;
|
|
||||||
|
|
||||||
private void queueUpdate() => Scheduler.AddOnce(updateSearch);
|
|
||||||
|
|
||||||
private CancellationTokenSource loadCancellation;
|
|
||||||
|
|
||||||
private void updateSearch()
|
|
||||||
{
|
|
||||||
queryChangedDebounce?.Cancel();
|
|
||||||
|
|
||||||
if (!IsLoaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Users = null;
|
|
||||||
clearPanels();
|
|
||||||
getUsersRequest?.Cancel();
|
|
||||||
|
|
||||||
if (API?.IsLoggedIn != true)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (Header.Tabs.Current.Value)
|
|
||||||
{
|
|
||||||
case SocialTab.Friends:
|
|
||||||
var friendRequest = new GetFriendsRequest(); // TODO filter arguments?
|
|
||||||
friendRequest.Success += users => Users = users.ToArray();
|
|
||||||
API.Queue(getUsersRequest = friendRequest);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
var userRequest = new GetUsersRequest(); // TODO filter arguments!
|
|
||||||
userRequest.Success += res => Users = res.Users.Select(r => r.User).ToArray();
|
|
||||||
API.Queue(getUsersRequest = userRequest);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void recreatePanels()
|
|
||||||
{
|
|
||||||
clearPanels();
|
|
||||||
|
|
||||||
if (Users == null)
|
|
||||||
{
|
|
||||||
loading.Hide();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerable<User> sortedUsers = Users;
|
|
||||||
|
|
||||||
switch (Filter.Tabs.Current.Value)
|
|
||||||
{
|
|
||||||
case SocialSortCriteria.Location:
|
|
||||||
sortedUsers = sortedUsers.OrderBy(u => u.Country.FullName);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SocialSortCriteria.Name:
|
|
||||||
sortedUsers = sortedUsers.OrderBy(u => u.Username);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Filter.Dropdown.Current.Value == SortDirection.Descending)
|
|
||||||
sortedUsers = sortedUsers.Reverse();
|
|
||||||
|
|
||||||
var newPanels = new FillFlowContainer<UserPanel>
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
Spacing = new Vector2(10f),
|
|
||||||
Margin = new MarginPadding { Top = 10 },
|
|
||||||
ChildrenEnumerable = sortedUsers.Select(u =>
|
|
||||||
{
|
|
||||||
UserPanel panel;
|
|
||||||
|
|
||||||
switch (Filter.DisplayStyleControl.DisplayStyle.Value)
|
|
||||||
{
|
|
||||||
case PanelDisplayStyle.Grid:
|
|
||||||
panel = new UserGridPanel(u)
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Width = 290,
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
panel = new UserListPanel(u);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
panel.Status.BindTo(u.Status);
|
|
||||||
panel.Activity.BindTo(u.Activity);
|
|
||||||
return panel;
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
LoadComponentAsync(newPanels, f =>
|
|
||||||
{
|
|
||||||
if (panels != null)
|
|
||||||
ScrollFlow.Remove(panels);
|
|
||||||
|
|
||||||
loading.Hide();
|
|
||||||
ScrollFlow.Add(panels = newPanels);
|
|
||||||
}, (loadCancellation = new CancellationTokenSource()).Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFilterUpdate()
|
|
||||||
{
|
|
||||||
if (Filter.Tabs.Current.Value == SocialSortCriteria.Rank)
|
|
||||||
{
|
|
||||||
queueUpdate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
recreatePanels();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void clearPanels()
|
|
||||||
{
|
|
||||||
loading.Show();
|
|
||||||
|
|
||||||
loadCancellation?.Cancel();
|
|
||||||
|
|
||||||
if (panels != null)
|
|
||||||
{
|
|
||||||
panels.Expire();
|
|
||||||
panels = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void APIStateChanged(IAPIProvider api, APIState state)
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case APIState.Online:
|
|
||||||
queueUpdate();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Users = null;
|
|
||||||
clearPanels();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,6 +22,7 @@ namespace osu.Game.Overlays
|
|||||||
protected OsuTabControl<T> TabControl;
|
protected OsuTabControl<T> TabControl;
|
||||||
|
|
||||||
private readonly Box controlBackground;
|
private readonly Box controlBackground;
|
||||||
|
private readonly Container tabControlContainer;
|
||||||
private readonly BindableWithCurrent<T> current = new BindableWithCurrent<T>();
|
private readonly BindableWithCurrent<T> current = new BindableWithCurrent<T>();
|
||||||
|
|
||||||
public Bindable<T> Current
|
public Bindable<T> Current
|
||||||
@ -30,6 +31,16 @@ namespace osu.Game.Overlays
|
|||||||
set => current.Current = value;
|
set => current.Current = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected new float ContentSidePadding
|
||||||
|
{
|
||||||
|
get => base.ContentSidePadding;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
base.ContentSidePadding = value;
|
||||||
|
tabControlContainer.Padding = new MarginPadding { Horizontal = value };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected TabControlOverlayHeader()
|
protected TabControlOverlayHeader()
|
||||||
{
|
{
|
||||||
HeaderInfo.Add(new Container
|
HeaderInfo.Add(new Container
|
||||||
@ -42,11 +53,16 @@ namespace osu.Game.Overlays
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
},
|
||||||
TabControl = CreateTabControl().With(control =>
|
tabControlContainer = new Container
|
||||||
{
|
{
|
||||||
control.Margin = new MarginPadding { Left = CONTENT_X_MARGIN };
|
RelativeSizeAxes = Axes.X,
|
||||||
control.Current = Current;
|
AutoSizeAxes = Axes.Y,
|
||||||
})
|
Padding = new MarginPadding { Horizontal = ContentSidePadding },
|
||||||
|
Child = TabControl = CreateTabControl().With(control =>
|
||||||
|
{
|
||||||
|
control.Current = Current;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Mods
|
|||||||
|
|
||||||
protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
|
protected override bool FailCondition(HealthProcessor healthProcessor, JudgementResult result)
|
||||||
=> !(result.Judgement is IgnoreJudgement)
|
=> !(result.Judgement is IgnoreJudgement)
|
||||||
|
&& result.Judgement.AffectsCombo
|
||||||
&& result.Type != result.Judgement.MaxResult;
|
&& result.Type != result.Judgement.MaxResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
if (Result == null)
|
if (Result == null)
|
||||||
throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}.");
|
throw new InvalidOperationException($"{GetType().ReadableName()} must provide a {nameof(JudgementResult)} through {nameof(CreateResult)}.");
|
||||||
|
|
||||||
loadSamples();
|
LoadSamples();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -145,14 +145,14 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
}
|
}
|
||||||
|
|
||||||
samplesBindable = HitObject.SamplesBindable.GetBoundCopy();
|
samplesBindable = HitObject.SamplesBindable.GetBoundCopy();
|
||||||
samplesBindable.CollectionChanged += (_, __) => loadSamples();
|
samplesBindable.CollectionChanged += (_, __) => LoadSamples();
|
||||||
|
|
||||||
apply(HitObject);
|
apply(HitObject);
|
||||||
|
|
||||||
updateState(ArmedState.Idle, true);
|
updateState(ArmedState.Idle, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSamples()
|
protected virtual void LoadSamples()
|
||||||
{
|
{
|
||||||
if (Samples != null)
|
if (Samples != null)
|
||||||
{
|
{
|
||||||
@ -353,17 +353,32 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
|||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private GameplayClock gameplayClock { get; set; }
|
private GameplayClock gameplayClock { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate the position to be used for sample playback at a specified X position (0..1).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">The lookup X position. Generally should be <see cref="SamplePlaybackPosition"/>.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected double CalculateSamplePlaybackBalance(double position)
|
||||||
|
{
|
||||||
|
const float balance_adjust_amount = 0.4f;
|
||||||
|
|
||||||
|
return balance_adjust_amount * (userPositionalHitSounds.Value ? position - 0.5f : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether samples should currently be playing. Will be false during seek operations.
|
||||||
|
/// </summary>
|
||||||
|
protected bool ShouldPlaySamples => gameplayClock?.IsSeeking != true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Plays all the hit sounds for this <see cref="DrawableHitObject"/>.
|
/// Plays all the hit sounds for this <see cref="DrawableHitObject"/>.
|
||||||
/// This is invoked automatically when this <see cref="DrawableHitObject"/> is hit.
|
/// This is invoked automatically when this <see cref="DrawableHitObject"/> is hit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void PlaySamples()
|
public virtual void PlaySamples()
|
||||||
{
|
{
|
||||||
const float balance_adjust_amount = 0.4f;
|
if (Samples != null && ShouldPlaySamples)
|
||||||
|
|
||||||
if (Samples != null && gameplayClock?.IsSeeking != true)
|
|
||||||
{
|
{
|
||||||
Samples.Balance.Value = balance_adjust_amount * (userPositionalHitSounds.Value ? SamplePlaybackPosition - 0.5f : 0);
|
Samples.Balance.Value = CalculateSamplePlaybackBalance(SamplePlaybackPosition);
|
||||||
Samples.Play();
|
Samples.Play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Input.StateChanges;
|
|
||||||
using osu.Game.Input.Handlers;
|
using osu.Game.Input.Handlers;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
|
|
||||||
@ -69,8 +68,6 @@ namespace osu.Game.Rulesets.Replays
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override List<IInput> GetPendingInputs() => new List<IInput>();
|
|
||||||
|
|
||||||
private const double sixty_frame_time = 1000.0 / 60;
|
private const double sixty_frame_time = 1000.0 / 60;
|
||||||
|
|
||||||
protected virtual double AllowedImportantTimeSpan => sixty_frame_time * 1.2;
|
protected virtual double AllowedImportantTimeSpan => sixty_frame_time * 1.2;
|
||||||
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Leaderboards;
|
using osu.Game.Online.Leaderboards;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
|
@ -10,7 +10,6 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Ranking;
|
using osu.Game.Screens.Ranking;
|
||||||
|
@ -14,7 +14,6 @@ using osu.Framework.Logging;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online;
|
using osu.Game.Online;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Multi.Lounge.Components;
|
using osu.Game.Screens.Multi.Lounge.Components;
|
||||||
|
@ -13,6 +13,7 @@ using osu.Framework.Input.Events;
|
|||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Screens.Ranking.Contracted;
|
using osu.Game.Screens.Ranking.Contracted;
|
||||||
using osu.Game.Screens.Ranking.Expanded;
|
using osu.Game.Screens.Ranking.Expanded;
|
||||||
|
using osu.Game.Users;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -142,7 +143,16 @@ namespace osu.Game.Screens.Ranking
|
|||||||
CornerRadius = 20,
|
CornerRadius = 20,
|
||||||
CornerExponent = 2.5f,
|
CornerExponent = 2.5f,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Child = middleLayerBackground = new Box { RelativeSizeAxes = Axes.Both }
|
Children = new[]
|
||||||
|
{
|
||||||
|
middleLayerBackground = new Box { RelativeSizeAxes = Axes.Both },
|
||||||
|
new UserCoverBackground
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
User = Score.User,
|
||||||
|
Colour = ColourInfo.GradientVertical(Color4.White.Opacity(0.5f), Color4Extensions.FromHex("#444").Opacity(0))
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
middleLayerContentContainer = new Container { RelativeSizeAxes = Axes.Both }
|
middleLayerContentContainer = new Container { RelativeSizeAxes = Axes.Both }
|
||||||
}
|
}
|
||||||
@ -155,18 +165,10 @@ namespace osu.Game.Screens.Ranking
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
if (state == PanelState.Expanded)
|
|
||||||
{
|
|
||||||
topLayerBackground.FadeColour(expanded_top_layer_colour);
|
|
||||||
middleLayerBackground.FadeColour(expanded_middle_layer_colour);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
topLayerBackground.FadeColour(contracted_top_layer_colour);
|
|
||||||
middleLayerBackground.FadeColour(contracted_middle_layer_colour);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateState();
|
updateState();
|
||||||
|
|
||||||
|
topLayerBackground.FinishTransforms(false, nameof(Colour));
|
||||||
|
middleLayerBackground.FinishTransforms(false, nameof(Colour));
|
||||||
}
|
}
|
||||||
|
|
||||||
private PanelState state = PanelState.Contracted;
|
private PanelState state = PanelState.Contracted;
|
||||||
|
@ -98,6 +98,8 @@ namespace osu.Game.Skinning
|
|||||||
|
|
||||||
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
|
||||||
{
|
{
|
||||||
|
bool wasPlaying = samplesContainer.Any(s => s.Playing);
|
||||||
|
|
||||||
var channels = hitSamples.Select(s =>
|
var channels = hitSamples.Select(s =>
|
||||||
{
|
{
|
||||||
var ch = skin.GetSample(s);
|
var ch = skin.GetSample(s);
|
||||||
@ -121,6 +123,9 @@ namespace osu.Game.Skinning
|
|||||||
}).Where(c => c != null);
|
}).Where(c => c != null);
|
||||||
|
|
||||||
samplesContainer.ChildrenEnumerable = channels.Select(c => new DrawableSample(c));
|
samplesContainer.ChildrenEnumerable = channels.Select(c => new DrawableSample(c));
|
||||||
|
|
||||||
|
if (wasPlaying)
|
||||||
|
Play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
148
osu.Game/Users/ExtendedUserPanel.cs
Normal file
148
osu.Game/Users/ExtendedUserPanel.cs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
// 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 osuTK;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Game.Users.Drawables;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
|
||||||
|
namespace osu.Game.Users
|
||||||
|
{
|
||||||
|
public abstract class ExtendedUserPanel : UserPanel
|
||||||
|
{
|
||||||
|
public readonly Bindable<UserStatus> Status = new Bindable<UserStatus>();
|
||||||
|
|
||||||
|
public readonly IBindable<UserActivity> Activity = new Bindable<UserActivity>();
|
||||||
|
|
||||||
|
protected TextFlowContainer LastVisitMessage { get; private set; }
|
||||||
|
|
||||||
|
private SpriteIcon statusIcon;
|
||||||
|
private OsuSpriteText statusMessage;
|
||||||
|
|
||||||
|
protected ExtendedUserPanel(User user)
|
||||||
|
: base(user)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
BorderColour = ColourProvider?.Light1 ?? Colours.GreyVioletLighter;
|
||||||
|
|
||||||
|
Status.ValueChanged += status => displayStatus(status.NewValue, Activity.Value);
|
||||||
|
Activity.ValueChanged += activity => displayStatus(Status.Value, activity.NewValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
Status.TriggerChange();
|
||||||
|
|
||||||
|
// Colour should be applied immediately on first load.
|
||||||
|
statusIcon.FinishTransforms();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar
|
||||||
|
{
|
||||||
|
User = User,
|
||||||
|
OpenOnClick = { Value = false }
|
||||||
|
};
|
||||||
|
|
||||||
|
protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.Country)
|
||||||
|
{
|
||||||
|
Size = new Vector2(39, 26)
|
||||||
|
};
|
||||||
|
|
||||||
|
protected SpriteIcon CreateStatusIcon() => statusIcon = new SpriteIcon
|
||||||
|
{
|
||||||
|
Icon = FontAwesome.Regular.Circle,
|
||||||
|
Size = new Vector2(25)
|
||||||
|
};
|
||||||
|
|
||||||
|
protected FillFlowContainer CreateStatusMessage(bool rightAlignedChildren)
|
||||||
|
{
|
||||||
|
var statusContainer = new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical
|
||||||
|
};
|
||||||
|
|
||||||
|
var alignment = rightAlignedChildren ? Anchor.CentreRight : Anchor.CentreLeft;
|
||||||
|
|
||||||
|
statusContainer.Add(LastVisitMessage = new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)).With(text =>
|
||||||
|
{
|
||||||
|
text.Anchor = alignment;
|
||||||
|
text.Origin = alignment;
|
||||||
|
text.AutoSizeAxes = Axes.Both;
|
||||||
|
text.Alpha = 0;
|
||||||
|
|
||||||
|
if (User.LastVisit.HasValue)
|
||||||
|
{
|
||||||
|
text.AddText(@"Last seen ");
|
||||||
|
text.AddText(new DrawableDate(User.LastVisit.Value, italic: false)
|
||||||
|
{
|
||||||
|
Shadow = false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
statusContainer.Add(statusMessage = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = alignment,
|
||||||
|
Origin = alignment,
|
||||||
|
Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold)
|
||||||
|
});
|
||||||
|
|
||||||
|
return statusContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void displayStatus(UserStatus status, UserActivity activity = null)
|
||||||
|
{
|
||||||
|
if (status != null)
|
||||||
|
{
|
||||||
|
LastVisitMessage.FadeTo(status is UserStatusOffline && User.LastVisit.HasValue ? 1 : 0);
|
||||||
|
|
||||||
|
// Set status message based on activity (if we have one) and status is not offline
|
||||||
|
if (activity != null && !(status is UserStatusOffline))
|
||||||
|
{
|
||||||
|
statusMessage.Text = activity.Status;
|
||||||
|
statusIcon.FadeColour(activity.GetAppropriateColour(Colours), 500, Easing.OutQuint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise use only status
|
||||||
|
statusMessage.Text = status.Message;
|
||||||
|
statusIcon.FadeColour(status.GetAppropriateColour(Colours), 500, Easing.OutQuint);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to web status if local one is null
|
||||||
|
if (User.IsOnline)
|
||||||
|
{
|
||||||
|
Status.Value = new UserStatusOnline();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status.Value = new UserStatusOffline();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
BorderThickness = 2;
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
BorderThickness = 0;
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
osu.Game/Users/UserBrickPanel.cs
Normal file
65
osu.Game/Users/UserBrickPanel.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// 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.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Users
|
||||||
|
{
|
||||||
|
public class UserBrickPanel : UserPanel
|
||||||
|
{
|
||||||
|
public UserBrickPanel(User user)
|
||||||
|
: base(user)
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both;
|
||||||
|
CornerRadius = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Background.FadeTo(0.2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateLayout() => new FillFlowContainer
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Spacing = new Vector2(5, 0),
|
||||||
|
Margin = new MarginPadding
|
||||||
|
{
|
||||||
|
Horizontal = 10,
|
||||||
|
Vertical = 3,
|
||||||
|
},
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new CircularContainer
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Masking = true,
|
||||||
|
Width = 4,
|
||||||
|
Height = 13,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = string.IsNullOrEmpty(User.Colour) ? Color4Extensions.FromHex("0087ca") : Color4Extensions.FromHex(User.Colour)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CreateUsername().With(u =>
|
||||||
|
{
|
||||||
|
u.Anchor = Anchor.CentreLeft;
|
||||||
|
u.Origin = Anchor.CentreLeft;
|
||||||
|
u.Font = OsuFont.GetFont(size: 13, weight: FontWeight.Bold);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Users
|
namespace osu.Game.Users
|
||||||
{
|
{
|
||||||
public class UserGridPanel : UserPanel
|
public class UserGridPanel : ExtendedUserPanel
|
||||||
{
|
{
|
||||||
private const int margin = 10;
|
private const int margin = 10;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ using osu.Game.Overlays.Profile.Header.Components;
|
|||||||
|
|
||||||
namespace osu.Game.Users
|
namespace osu.Game.Users
|
||||||
{
|
{
|
||||||
public class UserListPanel : UserPanel
|
public class UserListPanel : ExtendedUserPanel
|
||||||
{
|
{
|
||||||
public UserListPanel(User user)
|
public UserListPanel(User user)
|
||||||
: base(user)
|
: base(user)
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
// 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;
|
||||||
using osuTK;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
@ -14,11 +12,8 @@ using osu.Game.Overlays;
|
|||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Graphics.Sprites;
|
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Users.Drawables;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
|
|
||||||
namespace osu.Game.Users
|
namespace osu.Game.Users
|
||||||
{
|
{
|
||||||
@ -26,21 +21,12 @@ namespace osu.Game.Users
|
|||||||
{
|
{
|
||||||
public readonly User User;
|
public readonly User User;
|
||||||
|
|
||||||
public readonly Bindable<UserStatus> Status = new Bindable<UserStatus>();
|
|
||||||
|
|
||||||
public readonly IBindable<UserActivity> Activity = new Bindable<UserActivity>();
|
|
||||||
|
|
||||||
public new Action Action;
|
public new Action Action;
|
||||||
|
|
||||||
protected Action ViewProfile { get; private set; }
|
protected Action ViewProfile { get; private set; }
|
||||||
|
|
||||||
protected DelayedLoadUnloadWrapper Background { get; private set; }
|
protected DelayedLoadUnloadWrapper Background { get; private set; }
|
||||||
|
|
||||||
protected TextFlowContainer LastVisitMessage { get; private set; }
|
|
||||||
|
|
||||||
private SpriteIcon statusIcon;
|
|
||||||
private OsuSpriteText statusMessage;
|
|
||||||
|
|
||||||
protected UserPanel(User user)
|
protected UserPanel(User user)
|
||||||
{
|
{
|
||||||
if (user == null)
|
if (user == null)
|
||||||
@ -53,23 +39,22 @@ namespace osu.Game.Users
|
|||||||
private UserProfileOverlay profileOverlay { get; set; }
|
private UserProfileOverlay profileOverlay { get; set; }
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private OverlayColourProvider colourProvider { get; set; }
|
protected OverlayColourProvider ColourProvider { get; private set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuColour colours { get; set; }
|
protected OsuColour Colours { get; private set; }
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
Masking = true;
|
Masking = true;
|
||||||
BorderColour = colourProvider?.Light1 ?? colours.GreyVioletLighter;
|
|
||||||
|
|
||||||
AddRange(new[]
|
AddRange(new[]
|
||||||
{
|
{
|
||||||
new Box
|
new Box
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = colourProvider?.Background5 ?? colours.Gray1
|
Colour = ColourProvider?.Background5 ?? Colours.Gray1
|
||||||
},
|
},
|
||||||
Background = new DelayedLoadUnloadWrapper(() => new UserCoverBackground
|
Background = new DelayedLoadUnloadWrapper(() => new UserCoverBackground
|
||||||
{
|
{
|
||||||
@ -86,9 +71,6 @@ namespace osu.Game.Users
|
|||||||
CreateLayout()
|
CreateLayout()
|
||||||
});
|
});
|
||||||
|
|
||||||
Status.ValueChanged += status => displayStatus(status.NewValue, Activity.Value);
|
|
||||||
Activity.ValueChanged += activity => displayStatus(Status.Value, activity.NewValue);
|
|
||||||
|
|
||||||
base.Action = ViewProfile = () =>
|
base.Action = ViewProfile = () =>
|
||||||
{
|
{
|
||||||
Action?.Invoke();
|
Action?.Invoke();
|
||||||
@ -96,41 +78,9 @@ namespace osu.Game.Users
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
Status.TriggerChange();
|
|
||||||
|
|
||||||
// Colour should be applied immediately on first load.
|
|
||||||
statusIcon.FinishTransforms();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
|
||||||
{
|
|
||||||
BorderThickness = 2;
|
|
||||||
return base.OnHover(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
|
||||||
{
|
|
||||||
BorderThickness = 0;
|
|
||||||
base.OnHoverLost(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
[NotNull]
|
[NotNull]
|
||||||
protected abstract Drawable CreateLayout();
|
protected abstract Drawable CreateLayout();
|
||||||
|
|
||||||
protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar
|
|
||||||
{
|
|
||||||
User = User,
|
|
||||||
OpenOnClick = { Value = false }
|
|
||||||
};
|
|
||||||
|
|
||||||
protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.Country)
|
|
||||||
{
|
|
||||||
Size = new Vector2(39, 26)
|
|
||||||
};
|
|
||||||
|
|
||||||
protected OsuSpriteText CreateUsername() => new OsuSpriteText
|
protected OsuSpriteText CreateUsername() => new OsuSpriteText
|
||||||
{
|
{
|
||||||
Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold),
|
Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold),
|
||||||
@ -138,80 +88,6 @@ namespace osu.Game.Users
|
|||||||
Text = User.Username,
|
Text = User.Username,
|
||||||
};
|
};
|
||||||
|
|
||||||
protected SpriteIcon CreateStatusIcon() => statusIcon = new SpriteIcon
|
|
||||||
{
|
|
||||||
Icon = FontAwesome.Regular.Circle,
|
|
||||||
Size = new Vector2(25)
|
|
||||||
};
|
|
||||||
|
|
||||||
protected FillFlowContainer CreateStatusMessage(bool rightAlignedChildren)
|
|
||||||
{
|
|
||||||
var statusContainer = new FillFlowContainer
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Direction = FillDirection.Vertical
|
|
||||||
};
|
|
||||||
|
|
||||||
var alignment = rightAlignedChildren ? Anchor.CentreRight : Anchor.CentreLeft;
|
|
||||||
|
|
||||||
statusContainer.Add(LastVisitMessage = new TextFlowContainer(t => t.Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)).With(text =>
|
|
||||||
{
|
|
||||||
text.Anchor = alignment;
|
|
||||||
text.Origin = alignment;
|
|
||||||
text.AutoSizeAxes = Axes.Both;
|
|
||||||
text.Alpha = 0;
|
|
||||||
|
|
||||||
if (User.LastVisit.HasValue)
|
|
||||||
{
|
|
||||||
text.AddText(@"Last seen ");
|
|
||||||
text.AddText(new DrawableDate(User.LastVisit.Value, italic: false)
|
|
||||||
{
|
|
||||||
Shadow = false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
statusContainer.Add(statusMessage = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = alignment,
|
|
||||||
Origin = alignment,
|
|
||||||
Font = OsuFont.GetFont(size: 14, weight: FontWeight.SemiBold)
|
|
||||||
});
|
|
||||||
|
|
||||||
return statusContainer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displayStatus(UserStatus status, UserActivity activity = null)
|
|
||||||
{
|
|
||||||
if (status != null)
|
|
||||||
{
|
|
||||||
LastVisitMessage.FadeTo(status is UserStatusOffline && User.LastVisit.HasValue ? 1 : 0);
|
|
||||||
|
|
||||||
// Set status message based on activity (if we have one) and status is not offline
|
|
||||||
if (activity != null && !(status is UserStatusOffline))
|
|
||||||
{
|
|
||||||
statusMessage.Text = activity.Status;
|
|
||||||
statusIcon.FadeColour(activity.GetAppropriateColour(colours), 500, Easing.OutQuint);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise use only status
|
|
||||||
statusMessage.Text = status.Message;
|
|
||||||
statusIcon.FadeColour(status.GetAppropriateColour(colours), 500, Easing.OutQuint);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to web status if local one is null
|
|
||||||
if (User.IsOnline)
|
|
||||||
{
|
|
||||||
Status.Value = new UserStatusOnline();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status.Value = new UserStatusOffline();
|
|
||||||
}
|
|
||||||
|
|
||||||
public MenuItem[] ContextMenuItems => new MenuItem[]
|
public MenuItem[] ContextMenuItems => new MenuItem[]
|
||||||
{
|
{
|
||||||
new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile),
|
new OsuMenuItem("View Profile", MenuItemType.Highlighted, ViewProfile),
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.714.1" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.723.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
|
||||||
<PackageReference Include="Sentry" Version="2.1.4" />
|
<PackageReference Include="Sentry" Version="2.1.4" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.25.1" />
|
<PackageReference Include="SharpCompress" Version="0.25.1" />
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.714.1" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2020.723.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2020.715.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
<!-- Xamarin.iOS does not automatically handle transitive dependencies from NuGet packages. -->
|
||||||
@ -80,7 +80,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2020.714.1" />
|
<PackageReference Include="ppy.osu.Framework" Version="2020.723.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.25.1" />
|
<PackageReference Include="SharpCompress" Version="0.25.1" />
|
||||||
<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" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user