mirror of
https://github.com/ppy/osu.git
synced 2025-01-06 06:13:04 +08:00
Merge branch 'master' into comment-editor-1
This commit is contained in:
commit
4a747182b4
@ -52,7 +52,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1127.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1127.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.1126.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2022.1130.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||||
|
@ -7,12 +7,14 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
using osu.Game.Graphics.Backgrounds;
|
using osu.Game.Graphics.Backgrounds;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Background
|
namespace osu.Game.Tests.Visual.Background
|
||||||
{
|
{
|
||||||
public partial class TestSceneTrianglesV2Background : OsuTestScene
|
public partial class TestSceneTrianglesV2Background : OsuTestScene
|
||||||
{
|
{
|
||||||
private readonly TrianglesV2 triangles;
|
private readonly TrianglesV2 triangles;
|
||||||
|
private readonly Box box;
|
||||||
|
|
||||||
public TestSceneTrianglesV2Background()
|
public TestSceneTrianglesV2Background()
|
||||||
{
|
{
|
||||||
@ -23,10 +25,17 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4.Gray
|
Colour = Color4.Gray
|
||||||
},
|
},
|
||||||
new Container
|
new FillFlowContainer
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
Spacing = new Vector2(0, 5),
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new Container
|
||||||
|
{
|
||||||
Size = new Vector2(500, 100),
|
Size = new Vector2(500, 100),
|
||||||
Masking = true,
|
Masking = true,
|
||||||
CornerRadius = 40,
|
CornerRadius = 40,
|
||||||
@ -41,9 +50,19 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both
|
||||||
ColourTop = Color4.White,
|
}
|
||||||
ColourBottom = Color4.Red
|
}
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
Size = new Vector2(500, 100),
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = 40,
|
||||||
|
Child = box = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,8 +73,16 @@ namespace osu.Game.Tests.Visual.Background
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
AddSliderStep("Spawn ratio", 0f, 2f, 1f, s => triangles.SpawnRatio = s);
|
AddSliderStep("Spawn ratio", 0f, 10f, 1f, s =>
|
||||||
|
{
|
||||||
|
triangles.SpawnRatio = s;
|
||||||
|
triangles.Reset(1234);
|
||||||
|
});
|
||||||
AddSliderStep("Thickness", 0f, 1f, 0.02f, t => triangles.Thickness = t);
|
AddSliderStep("Thickness", 0f, 1f, 0.02f, t => triangles.Thickness = t);
|
||||||
|
|
||||||
|
AddStep("White colour", () => box.Colour = triangles.Colour = Color4.White);
|
||||||
|
AddStep("Vertical gradient", () => box.Colour = triangles.Colour = ColourInfo.GradientVertical(Color4.White, Color4.Red));
|
||||||
|
AddStep("Horizontal gradient", () => box.Colour = triangles.Colour = ColourInfo.GradientHorizontal(Color4.White, Color4.Red));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Screens.Edit;
|
using osu.Game.Screens.Edit;
|
||||||
@ -26,6 +28,7 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
|
||||||
|
|
||||||
private TimingScreen timingScreen;
|
private TimingScreen timingScreen;
|
||||||
|
private EditorBeatmap editorBeatmap;
|
||||||
|
|
||||||
protected override bool ScrollUsingMouseWheel => false;
|
protected override bool ScrollUsingMouseWheel => false;
|
||||||
|
|
||||||
@ -35,8 +38,11 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
|
|
||||||
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
|
Beatmap.Value = CreateWorkingBeatmap(Ruleset.Value);
|
||||||
Beatmap.Disabled = true;
|
Beatmap.Disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
var editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(Ruleset.Value));
|
private void reloadEditorBeatmap()
|
||||||
|
{
|
||||||
|
editorBeatmap = new EditorBeatmap(Beatmap.Value.GetPlayableBeatmap(Ruleset.Value));
|
||||||
|
|
||||||
Child = new DependencyProvidingContainer
|
Child = new DependencyProvidingContainer
|
||||||
{
|
{
|
||||||
@ -58,7 +64,9 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
{
|
{
|
||||||
AddStep("Stop clock", () => EditorClock.Stop());
|
AddStep("Stop clock", () => EditorClock.Stop());
|
||||||
|
|
||||||
AddUntilStep("wait for rows to load", () => Child.ChildrenOfType<EffectRowAttribute>().Any());
|
AddStep("Reload Editor Beatmap", reloadEditorBeatmap);
|
||||||
|
|
||||||
|
AddUntilStep("Wait for rows to load", () => Child.ChildrenOfType<EffectRowAttribute>().Any());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@ -95,6 +103,37 @@ namespace osu.Game.Tests.Visual.Editing
|
|||||||
AddUntilStep("Selection changed", () => timingScreen.SelectedGroup.Value.Time == 69670);
|
AddUntilStep("Selection changed", () => timingScreen.SelectedGroup.Value.Time == 69670);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestScrollControlGroupIntoView()
|
||||||
|
{
|
||||||
|
AddStep("Add many control points", () =>
|
||||||
|
{
|
||||||
|
editorBeatmap.ControlPointInfo.Clear();
|
||||||
|
|
||||||
|
editorBeatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
editorBeatmap.ControlPointInfo.Add((i + 1) * 1000, new EffectControlPoint
|
||||||
|
{
|
||||||
|
KiaiMode = Convert.ToBoolean(i % 2),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Select first effect point", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(Child.ChildrenOfType<EffectRowAttribute>().First());
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Seek to beginning", () => EditorClock.Seek(0));
|
||||||
|
|
||||||
|
AddStep("Seek to last point", () => EditorClock.Seek(101 * 1000));
|
||||||
|
|
||||||
|
AddUntilStep("Scrolled to end", () => timingScreen.ChildrenOfType<OsuScrollContainer>().First().IsScrolledToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
Beatmap.Disabled = false;
|
Beatmap.Disabled = false;
|
||||||
|
@ -130,11 +130,11 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White;
|
Color4 textColour = isAction && hasBackground ? Color4Extensions.FromHex(newLine.Message.Sender.Colour) : Color4.White;
|
||||||
|
|
||||||
var linkCompilers = newLine.ContentFlow.Where(d => d is DrawableLinkCompiler).ToList();
|
var linkCompilers = newLine.DrawableContentFlow.Where(d => d is DrawableLinkCompiler).ToList();
|
||||||
var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts);
|
var linkSprites = linkCompilers.SelectMany(comp => ((DrawableLinkCompiler)comp).Parts);
|
||||||
|
|
||||||
return linkSprites.All(d => d.Colour == linkColour)
|
return linkSprites.All(d => d.Colour == linkColour)
|
||||||
&& newLine.ContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour);
|
&& newLine.DrawableContentFlow.Except(linkSprites.Concat(linkCompilers)).All(d => d.Colour == textColour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
@ -33,7 +34,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
{
|
{
|
||||||
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null));
|
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InLobby(null));
|
||||||
|
|
||||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
|
||||||
|
|
||||||
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is listening"));
|
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is listening"));
|
||||||
}
|
}
|
||||||
@ -43,7 +44,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
{
|
{
|
||||||
AddStep("Set activity", () => api.Activity.Value = new UserActivity.Editing(new BeatmapInfo()));
|
AddStep("Set activity", () => api.Activity.Value = new UserActivity.Editing(new BeatmapInfo()));
|
||||||
|
|
||||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
|
||||||
|
|
||||||
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is editing"));
|
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is editing"));
|
||||||
}
|
}
|
||||||
@ -53,7 +54,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
{
|
{
|
||||||
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new RulesetInfo()));
|
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new RulesetInfo()));
|
||||||
|
|
||||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
|
||||||
|
|
||||||
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is playing"));
|
AddAssert("Check correct response", () => postTarget.LastMessage.Contains("is playing"));
|
||||||
}
|
}
|
||||||
@ -69,7 +70,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : -1 }
|
BeatmapInfo = { OnlineID = hasOnlineId ? 1234 : -1 }
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("Run command", () => Add(new NowPlayingCommand()));
|
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
|
||||||
|
|
||||||
if (hasOnlineId)
|
if (hasOnlineId)
|
||||||
AddAssert("Check link presence", () => postTarget.LastMessage.Contains("/b/1234"));
|
AddAssert("Check link presence", () => postTarget.LastMessage.Contains("/b/1234"));
|
||||||
@ -77,6 +78,18 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
AddAssert("Check link not present", () => !postTarget.LastMessage.Contains("https://"));
|
AddAssert("Check link not present", () => !postTarget.LastMessage.Contains("https://"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestModPresence()
|
||||||
|
{
|
||||||
|
AddStep("Set activity", () => api.Activity.Value = new UserActivity.InSoloGame(new BeatmapInfo(), new RulesetInfo()));
|
||||||
|
|
||||||
|
AddStep("Add Hidden mod", () => SelectedMods.Value = new[] { Ruleset.Value.CreateInstance().CreateMod<ModHidden>() });
|
||||||
|
|
||||||
|
AddStep("Run command", () => Add(new NowPlayingCommand(new Channel())));
|
||||||
|
|
||||||
|
AddAssert("Check mod is present", () => postTarget.LastMessage.Contains("+HD"));
|
||||||
|
}
|
||||||
|
|
||||||
public partial class PostTarget : Component, IChannelPostTarget
|
public partial class PostTarget : Component, IChannelPostTarget
|
||||||
{
|
{
|
||||||
public void PostMessage(string text, bool isAction = false, Channel target = null)
|
public void PostMessage(string text, bool isAction = false, Channel target = null)
|
||||||
|
@ -62,7 +62,6 @@ namespace osu.Game.Tests.Visual.Settings
|
|||||||
section.Children.Where(f => f.IsPresent)
|
section.Children.Where(f => f.IsPresent)
|
||||||
.OfType<ISettingsItem>()
|
.OfType<ISettingsItem>()
|
||||||
.OfType<IFilterable>()
|
.OfType<IFilterable>()
|
||||||
.Where(f => !(f is IHasFilterableChildren))
|
|
||||||
.All(f => f.FilterTerms.Any(t => t.ToString().Contains("scaling")))
|
.All(f => f.FilterTerms.Any(t => t.ToString().Contains("scaling")))
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -1,28 +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.Framework.Graphics;
|
|
||||||
using osu.Game.Screens.Select;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.SongSelect
|
|
||||||
{
|
|
||||||
public partial class TestSceneDifficultyRangeFilterControl : OsuTestScene
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void TestBasic()
|
|
||||||
{
|
|
||||||
AddStep("create control", () =>
|
|
||||||
{
|
|
||||||
Child = new DifficultyRangeFilterControl
|
|
||||||
{
|
|
||||||
Width = 200,
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Scale = new Vector2(3),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
79
osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs
Normal file
79
osu.Game.Tests/Visual/UserInterface/TestSceneRangeSlider.cs
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.UserInterface
|
||||||
|
{
|
||||||
|
public partial class TestSceneRangeSlider : OsuTestScene
|
||||||
|
{
|
||||||
|
[Cached]
|
||||||
|
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Red);
|
||||||
|
|
||||||
|
private readonly BindableNumber<double> customStart = new BindableNumber<double>
|
||||||
|
{
|
||||||
|
MinValue = 0,
|
||||||
|
MaxValue = 100,
|
||||||
|
Precision = 0.1f
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly BindableNumber<double> customEnd = new BindableNumber<double>(100)
|
||||||
|
{
|
||||||
|
MinValue = 0,
|
||||||
|
MaxValue = 100,
|
||||||
|
Precision = 0.1f
|
||||||
|
};
|
||||||
|
|
||||||
|
private RangeSlider rangeSlider = null!;
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public void SetUpSteps()
|
||||||
|
{
|
||||||
|
AddStep("create control", () => Child = rangeSlider = new RangeSlider
|
||||||
|
{
|
||||||
|
Width = 200,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Scale = new Vector2(3),
|
||||||
|
LowerBound = customStart,
|
||||||
|
UpperBound = customEnd,
|
||||||
|
TooltipSuffix = "suffix",
|
||||||
|
NubWidth = Nub.HEIGHT * 2,
|
||||||
|
DefaultStringLowerBound = "Start",
|
||||||
|
DefaultStringUpperBound = "End",
|
||||||
|
MinRange = 10
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestAdjustRange()
|
||||||
|
{
|
||||||
|
AddAssert("Initial lower bound is correct", () => rangeSlider.LowerBound.Value, () => Is.EqualTo(0).Within(0.1f));
|
||||||
|
AddAssert("Initial upper bound is correct", () => rangeSlider.UpperBound.Value, () => Is.EqualTo(100).Within(0.1f));
|
||||||
|
|
||||||
|
AddStep("Adjust range", () =>
|
||||||
|
{
|
||||||
|
customStart.Value = 50;
|
||||||
|
customEnd.Value = 75;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Adjusted lower bound is correct", () => rangeSlider.LowerBound.Value, () => Is.EqualTo(50).Within(0.1f));
|
||||||
|
AddAssert("Adjusted upper bound is correct", () => rangeSlider.UpperBound.Value, () => Is.EqualTo(75).Within(0.1f));
|
||||||
|
|
||||||
|
AddStep("Test nub pushing", () =>
|
||||||
|
{
|
||||||
|
customStart.Value = 90;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Pushed lower bound is correct", () => rangeSlider.LowerBound.Value, () => Is.EqualTo(90).Within(0.1f));
|
||||||
|
AddAssert("Pushed upper bound is correct", () => rangeSlider.UpperBound.Value, () => Is.EqualTo(100).Within(0.1f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,9 +11,7 @@ using osu.Framework.Allocation;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Graphics.Rendering;
|
using osu.Framework.Graphics.Rendering;
|
||||||
using osu.Framework.Graphics.Rendering.Vertices;
|
using osu.Framework.Graphics.Rendering.Vertices;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using osu.Framework.Graphics.Colour;
|
||||||
using SixLabors.ImageSharp;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
|
||||||
@ -23,28 +21,12 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
{
|
{
|
||||||
private const float triangle_size = 100;
|
private const float triangle_size = 100;
|
||||||
private const float base_velocity = 50;
|
private const float base_velocity = 50;
|
||||||
private const int texture_height = 128;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// sqrt(3) / 2
|
/// sqrt(3) / 2
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const float equilateral_triangle_ratio = 0.866f;
|
private const float equilateral_triangle_ratio = 0.866f;
|
||||||
|
|
||||||
private readonly Bindable<Color4> colourTop = new Bindable<Color4>(Color4.White);
|
|
||||||
private readonly Bindable<Color4> colourBottom = new Bindable<Color4>(Color4.Black);
|
|
||||||
|
|
||||||
public Color4 ColourTop
|
|
||||||
{
|
|
||||||
get => colourTop.Value;
|
|
||||||
set => colourTop.Value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color4 ColourBottom
|
|
||||||
{
|
|
||||||
get => colourBottom.Value;
|
|
||||||
set => colourBottom.Value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float Thickness { get; set; } = 0.02f; // No need for invalidation since it's happening in Update()
|
public float Thickness { get; set; } = 0.02f; // No need for invalidation since it's happening in Update()
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -70,9 +52,6 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
|
|
||||||
private readonly List<TriangleParticle> parts = new List<TriangleParticle>();
|
private readonly List<TriangleParticle> parts = new List<TriangleParticle>();
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private IRenderer renderer { get; set; } = null!;
|
|
||||||
|
|
||||||
private Random? stableRandom;
|
private Random? stableRandom;
|
||||||
|
|
||||||
private IShader shader = null!;
|
private IShader shader = null!;
|
||||||
@ -89,42 +68,19 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ShaderManager shaders)
|
private void load(ShaderManager shaders, IRenderer renderer)
|
||||||
{
|
{
|
||||||
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "TriangleBorder");
|
shader = shaders.Load(VertexShaderDescriptor.TEXTURE_2, "TriangleBorder");
|
||||||
|
texture = renderer.WhitePixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
colourTop.BindValueChanged(_ => updateTexture());
|
|
||||||
colourBottom.BindValueChanged(_ => updateTexture(), true);
|
|
||||||
|
|
||||||
spawnRatio.BindValueChanged(_ => Reset(), true);
|
spawnRatio.BindValueChanged(_ => Reset(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTexture()
|
|
||||||
{
|
|
||||||
var image = new Image<Rgba32>(texture_height, 1);
|
|
||||||
|
|
||||||
texture = renderer.CreateTexture(1, texture_height, true);
|
|
||||||
|
|
||||||
for (int i = 0; i < texture_height; i++)
|
|
||||||
{
|
|
||||||
float ratio = (float)i / texture_height;
|
|
||||||
|
|
||||||
image[i, 0] = new Rgba32(
|
|
||||||
colourBottom.Value.R * ratio + colourTop.Value.R * (1f - ratio),
|
|
||||||
colourBottom.Value.G * ratio + colourTop.Value.G * (1f - ratio),
|
|
||||||
colourBottom.Value.B * ratio + colourTop.Value.B * (1f - ratio)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
texture.SetData(new TextureUpload(image));
|
|
||||||
Invalidate(Invalidation.DrawNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
base.Update();
|
base.Update();
|
||||||
@ -227,6 +183,9 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
private Texture texture = null!;
|
private Texture texture = null!;
|
||||||
|
|
||||||
private readonly List<TriangleParticle> parts = new List<TriangleParticle>();
|
private readonly List<TriangleParticle> parts = new List<TriangleParticle>();
|
||||||
|
|
||||||
|
private readonly Vector2 triangleSize = new Vector2(1f, equilateral_triangle_ratio) * triangle_size;
|
||||||
|
|
||||||
private Vector2 size;
|
private Vector2 size;
|
||||||
private float thickness;
|
private float thickness;
|
||||||
private float texelSize;
|
private float texelSize;
|
||||||
@ -246,7 +205,15 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
texture = Source.texture;
|
texture = Source.texture;
|
||||||
size = Source.DrawSize;
|
size = Source.DrawSize;
|
||||||
thickness = Source.Thickness;
|
thickness = Source.Thickness;
|
||||||
texelSize = Math.Max(1.5f / Source.ScreenSpaceDrawQuad.Size.X, 1.5f / Source.ScreenSpaceDrawQuad.Size.Y);
|
|
||||||
|
Quad triangleQuad = new Quad(
|
||||||
|
Vector2Extensions.Transform(Vector2.Zero, DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(new Vector2(triangle_size, 0f), DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(new Vector2(0f, triangleSize.Y), DrawInfo.Matrix),
|
||||||
|
Vector2Extensions.Transform(triangleSize, DrawInfo.Matrix)
|
||||||
|
);
|
||||||
|
|
||||||
|
texelSize = 1.5f / triangleQuad.Height;
|
||||||
|
|
||||||
parts.Clear();
|
parts.Clear();
|
||||||
parts.AddRange(Source.parts);
|
parts.AddRange(Source.parts);
|
||||||
@ -256,7 +223,7 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
{
|
{
|
||||||
base.Draw(renderer);
|
base.Draw(renderer);
|
||||||
|
|
||||||
if (Source.AimCount == 0)
|
if (Source.AimCount == 0 || thickness == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (vertexBatch == null || vertexBatch.Size != Source.AimCount)
|
if (vertexBatch == null || vertexBatch.Size != Source.AimCount)
|
||||||
@ -269,35 +236,42 @@ namespace osu.Game.Graphics.Backgrounds
|
|||||||
shader.GetUniform<float>("thickness").UpdateValue(ref thickness);
|
shader.GetUniform<float>("thickness").UpdateValue(ref thickness);
|
||||||
shader.GetUniform<float>("texelSize").UpdateValue(ref texelSize);
|
shader.GetUniform<float>("texelSize").UpdateValue(ref texelSize);
|
||||||
|
|
||||||
|
float relativeHeight = triangleSize.Y / size.Y;
|
||||||
|
float relativeWidth = triangleSize.X / size.X;
|
||||||
|
|
||||||
foreach (TriangleParticle particle in parts)
|
foreach (TriangleParticle particle in parts)
|
||||||
{
|
{
|
||||||
var offset = triangle_size * new Vector2(0.5f, equilateral_triangle_ratio);
|
Vector2 topLeft = particle.Position - new Vector2(relativeWidth * 0.5f, 0f);
|
||||||
|
Vector2 topRight = topLeft + new Vector2(relativeWidth, 0f);
|
||||||
Vector2 topLeft = particle.Position * size + new Vector2(-offset.X, 0f);
|
Vector2 bottomLeft = topLeft + new Vector2(0f, relativeHeight);
|
||||||
Vector2 topRight = particle.Position * size + new Vector2(offset.X, 0);
|
Vector2 bottomRight = bottomLeft + new Vector2(relativeWidth, 0f);
|
||||||
Vector2 bottomLeft = particle.Position * size + new Vector2(-offset.X, offset.Y);
|
|
||||||
Vector2 bottomRight = particle.Position * size + new Vector2(offset.X, offset.Y);
|
|
||||||
|
|
||||||
var drawQuad = new Quad(
|
var drawQuad = new Quad(
|
||||||
Vector2Extensions.Transform(topLeft, DrawInfo.Matrix),
|
Vector2Extensions.Transform(topLeft * size, DrawInfo.Matrix),
|
||||||
Vector2Extensions.Transform(topRight, DrawInfo.Matrix),
|
Vector2Extensions.Transform(topRight * size, DrawInfo.Matrix),
|
||||||
Vector2Extensions.Transform(bottomLeft, DrawInfo.Matrix),
|
Vector2Extensions.Transform(bottomLeft * size, DrawInfo.Matrix),
|
||||||
Vector2Extensions.Transform(bottomRight, DrawInfo.Matrix)
|
Vector2Extensions.Transform(bottomRight * size, DrawInfo.Matrix)
|
||||||
);
|
);
|
||||||
|
|
||||||
var tRect = new Quad(
|
ColourInfo colourInfo = triangleColourInfo(DrawColourInfo.Colour, new Quad(topLeft, topRight, bottomLeft, bottomRight));
|
||||||
topLeft.X / size.X,
|
|
||||||
topLeft.Y / size.Y * texture_height,
|
|
||||||
(topRight.X - topLeft.X) / size.X,
|
|
||||||
(bottomRight.Y - topRight.Y) / size.Y * texture_height
|
|
||||||
).AABBFloat;
|
|
||||||
|
|
||||||
renderer.DrawQuad(texture, drawQuad, DrawColourInfo.Colour, tRect, vertexBatch.AddAction, textureCoords: tRect);
|
renderer.DrawQuad(texture, drawQuad, colourInfo, vertexAction: vertexBatch.AddAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
shader.Unbind();
|
shader.Unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ColourInfo triangleColourInfo(ColourInfo source, Quad quad)
|
||||||
|
{
|
||||||
|
return new ColourInfo
|
||||||
|
{
|
||||||
|
TopLeft = source.Interpolate(quad.TopLeft),
|
||||||
|
TopRight = source.Interpolate(quad.TopRight),
|
||||||
|
BottomLeft = source.Interpolate(quad.BottomLeft),
|
||||||
|
BottomRight = source.Interpolate(quad.BottomRight)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
{
|
{
|
||||||
base.Dispose(isDisposing);
|
base.Dispose(isDisposing);
|
||||||
|
212
osu.Game/Graphics/UserInterface/RangeSlider.cs
Normal file
212
osu.Game/Graphics/UserInterface/RangeSlider.cs
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Overlays;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Graphics.UserInterface
|
||||||
|
{
|
||||||
|
public partial class RangeSlider : CompositeDrawable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The lower limiting value
|
||||||
|
/// </summary>
|
||||||
|
public Bindable<double> LowerBound
|
||||||
|
{
|
||||||
|
get => lowerBound.Current;
|
||||||
|
set => lowerBound.Current = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The upper limiting value
|
||||||
|
/// </summary>
|
||||||
|
public Bindable<double> UpperBound
|
||||||
|
{
|
||||||
|
get => upperBound.Current;
|
||||||
|
set => upperBound.Current = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text that describes this RangeSlider's functionality
|
||||||
|
/// </summary>
|
||||||
|
public string Label
|
||||||
|
{
|
||||||
|
set => label.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float NubWidth
|
||||||
|
{
|
||||||
|
set => lowerBound.NubWidth = upperBound.NubWidth = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum difference between the lower bound and higher bound
|
||||||
|
/// </summary>
|
||||||
|
public float MinRange
|
||||||
|
{
|
||||||
|
set => minRange = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// lower bound display for when it is set to its default value
|
||||||
|
/// </summary>
|
||||||
|
public string DefaultStringLowerBound
|
||||||
|
{
|
||||||
|
set => lowerBound.DefaultString = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// upper bound display for when it is set to its default value
|
||||||
|
/// </summary>
|
||||||
|
public string DefaultStringUpperBound
|
||||||
|
{
|
||||||
|
set => upperBound.DefaultString = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalisableString DefaultTooltipLowerBound
|
||||||
|
{
|
||||||
|
set => lowerBound.DefaultTooltip = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalisableString DefaultTooltipUpperBound
|
||||||
|
{
|
||||||
|
set => upperBound.DefaultTooltip = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TooltipSuffix
|
||||||
|
{
|
||||||
|
set => upperBound.TooltipSuffix = lowerBound.TooltipSuffix = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float minRange = 0.1f;
|
||||||
|
|
||||||
|
private readonly OsuSpriteText label;
|
||||||
|
|
||||||
|
private readonly LowerBoundSlider lowerBound;
|
||||||
|
private readonly UpperBoundSlider upperBound;
|
||||||
|
|
||||||
|
public RangeSlider()
|
||||||
|
{
|
||||||
|
const float vertical_offset = 13;
|
||||||
|
|
||||||
|
InternalChildren = new Drawable[]
|
||||||
|
{
|
||||||
|
label = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Font = OsuFont.GetFont(size: 14),
|
||||||
|
},
|
||||||
|
upperBound = new UpperBoundSlider
|
||||||
|
{
|
||||||
|
KeyboardStep = 0.1f,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Y = vertical_offset,
|
||||||
|
},
|
||||||
|
lowerBound = new LowerBoundSlider
|
||||||
|
{
|
||||||
|
KeyboardStep = 0.1f,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Y = vertical_offset,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
lowerBound.Current.ValueChanged += min => upperBound.Current.Value = Math.Max(min.NewValue + minRange, upperBound.Current.Value);
|
||||||
|
upperBound.Current.ValueChanged += max => lowerBound.Current.Value = Math.Min(max.NewValue - minRange, lowerBound.Current.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class LowerBoundSlider : BoundSlider
|
||||||
|
{
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
LeftBox.Height = 6; // hide any colour bleeding from overlap
|
||||||
|
|
||||||
|
AccentColour = BackgroundColour;
|
||||||
|
BackgroundColour = Color4.Transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
||||||
|
base.ReceivePositionalInputAt(screenSpacePos)
|
||||||
|
&& screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class UpperBoundSlider : BoundSlider
|
||||||
|
{
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
RightBox.Height = 6; // just to match the left bar height really
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
||||||
|
base.ReceivePositionalInputAt(screenSpacePos)
|
||||||
|
&& screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected partial class BoundSlider : OsuSliderBar<double>
|
||||||
|
{
|
||||||
|
public string? DefaultString;
|
||||||
|
public LocalisableString? DefaultTooltip;
|
||||||
|
public string? TooltipSuffix;
|
||||||
|
public float NubWidth { get; set; } = Nub.HEIGHT;
|
||||||
|
|
||||||
|
public override LocalisableString TooltipText =>
|
||||||
|
(Current.IsDefault ? DefaultTooltip : Current.Value.ToString($@"0.## {TooltipSuffix}")) ?? Current.Value.ToString($@"0.## {TooltipSuffix}");
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
base.OnHover(e);
|
||||||
|
return true; // Make sure only one nub shows hover effect at once.
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
Nub.Width = NubWidth;
|
||||||
|
RangePadding = Nub.Width / 2;
|
||||||
|
|
||||||
|
OsuSpriteText currentDisplay;
|
||||||
|
|
||||||
|
Nub.Add(currentDisplay = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Y = -0.5f,
|
||||||
|
Colour = Color4.White,
|
||||||
|
Font = OsuFont.Torus.With(size: 10),
|
||||||
|
});
|
||||||
|
|
||||||
|
Current.BindValueChanged(current =>
|
||||||
|
{
|
||||||
|
currentDisplay.Text = (current.NewValue != Current.Default ? current.NewValue.ToString("N1") : DefaultString) ?? current.NewValue.ToString("N1");
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OverlayColourProvider? colourProvider)
|
||||||
|
{
|
||||||
|
if (colourProvider == null) return;
|
||||||
|
|
||||||
|
AccentColour = colourProvider.Background2;
|
||||||
|
Nub.AccentColour = colourProvider.Background2;
|
||||||
|
Nub.GlowingAccentColour = colourProvider.Background1;
|
||||||
|
Nub.GlowColour = colourProvider.Background2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ using System.Diagnostics;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
@ -79,8 +80,7 @@ namespace osu.Game.Graphics.UserInterfaceV2
|
|||||||
|
|
||||||
Debug.Assert(triangleGradientSecondColour != null);
|
Debug.Assert(triangleGradientSecondColour != null);
|
||||||
|
|
||||||
Triangles.ColourTop = triangleGradientSecondColour.Value;
|
Triangles.Colour = ColourInfo.GradientVertical(triangleGradientSecondColour.Value, BackgroundColour);
|
||||||
Triangles.ColourBottom = BackgroundColour;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
@ -25,6 +25,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
var req = base.CreateWebRequest();
|
var req = base.CreateWebRequest();
|
||||||
if (channel != null) req.AddParameter(@"channel", channel.Id.ToString());
|
if (channel != null) req.AddParameter(@"channel", channel.Id.ToString());
|
||||||
req.AddParameter(@"since", since.ToString());
|
req.AddParameter(@"since", since.ToString());
|
||||||
|
req.AddParameter(@"includes[]", "presence");
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,7 @@ namespace osu.Game.Online.API.Requests
|
|||||||
|
|
||||||
[JsonProperty]
|
[JsonProperty]
|
||||||
public List<Message> Messages;
|
public List<Message> Messages;
|
||||||
|
|
||||||
|
// TODO: Handle Silences here (will need to add to includes[] in the request).
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Online.Chat
|
namespace osu.Game.Online.Chat
|
||||||
@ -15,21 +19,30 @@ namespace osu.Game.Online.Chat
|
|||||||
public partial class NowPlayingCommand : Component
|
public partial class NowPlayingCommand : Component
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IChannelPostTarget channelManager { get; set; }
|
private IChannelPostTarget channelManager { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IAPIProvider api { get; set; }
|
private IAPIProvider api { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Bindable<WorkingBeatmap> currentBeatmap { get; set; }
|
private Bindable<WorkingBeatmap> currentBeatmap { get; set; } = null!;
|
||||||
|
|
||||||
private readonly Channel target;
|
[Resolved]
|
||||||
|
private Bindable<IReadOnlyList<Mod>> selectedMods { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IBindable<RulesetInfo> currentRuleset { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private LocalisationManager localisation { get; set; } = null!;
|
||||||
|
|
||||||
|
private readonly Channel? target;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="NowPlayingCommand"/> to post the currently-playing beatmap to a parenting <see cref="IChannelPostTarget"/>.
|
/// Creates a new <see cref="NowPlayingCommand"/> to post the currently-playing beatmap to a parenting <see cref="IChannelPostTarget"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="target">The target channel to post to. If <c>null</c>, the currently-selected channel will be posted to.</param>
|
/// <param name="target">The target channel to post to. If <c>null</c>, the currently-selected channel will be posted to.</param>
|
||||||
public NowPlayingCommand(Channel target = null)
|
public NowPlayingCommand(Channel target)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
}
|
}
|
||||||
@ -59,10 +72,55 @@ namespace osu.Game.Online.Chat
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
string beatmapString = beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfo}]" : beatmapInfo.ToString();
|
string[] pieces =
|
||||||
|
{
|
||||||
|
"is",
|
||||||
|
verb,
|
||||||
|
getBeatmapPart(),
|
||||||
|
getRulesetPart(),
|
||||||
|
getModPart(),
|
||||||
|
};
|
||||||
|
|
||||||
channelManager.PostMessage($"is {verb} {beatmapString}", true, target);
|
channelManager.PostMessage(string.Join(' ', pieces.Where(p => !string.IsNullOrEmpty(p))), true, target);
|
||||||
Expire();
|
Expire();
|
||||||
|
|
||||||
|
string getBeatmapPart()
|
||||||
|
{
|
||||||
|
string beatmapInfoString = localisation.GetLocalisedBindableString(beatmapInfo.GetDisplayTitleRomanisable()).Value;
|
||||||
|
|
||||||
|
return beatmapInfo.OnlineID > 0 ? $"[{api.WebsiteRootUrl}/b/{beatmapInfo.OnlineID} {beatmapInfoString}]" : beatmapInfoString;
|
||||||
|
}
|
||||||
|
|
||||||
|
string getRulesetPart()
|
||||||
|
{
|
||||||
|
if (api.Activity.Value is not UserActivity.InGame) return string.Empty;
|
||||||
|
|
||||||
|
return $"<{currentRuleset.Value.Name}>";
|
||||||
|
}
|
||||||
|
|
||||||
|
string getModPart()
|
||||||
|
{
|
||||||
|
if (api.Activity.Value is not UserActivity.InGame) return string.Empty;
|
||||||
|
|
||||||
|
if (selectedMods.Value.Count == 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder modsString = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (var mod in selectedMods.Value.Where(mod => mod.Type == ModType.DifficultyIncrease))
|
||||||
|
{
|
||||||
|
modsString.Append($"+{mod.Acronym} ");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var mod in selectedMods.Value.Where(mod => mod.Type != ModType.DifficultyIncrease))
|
||||||
|
{
|
||||||
|
modsString.Append($"-{mod.Acronym} ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return modsString.ToString().Trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ namespace osu.Game.Online.Chat
|
|||||||
|
|
||||||
protected partial class StandAloneMessage : ChatLine
|
protected partial class StandAloneMessage : ChatLine
|
||||||
{
|
{
|
||||||
protected override float TextSize => 15;
|
protected override float FontSize => 15;
|
||||||
protected override float Spacing => 5;
|
protected override float Spacing => 5;
|
||||||
protected override float UsernameWidth => 75;
|
protected override float UsernameWidth => 75;
|
||||||
|
|
||||||
|
@ -33,11 +33,11 @@ namespace osu.Game.Online.Notifications
|
|||||||
|
|
||||||
public override Task ConnectAsync(CancellationToken cancellationToken)
|
public override Task ConnectAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
API.Queue(CreateFetchMessagesRequest(0));
|
API.Queue(CreateInitialFetchRequest(0));
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected APIRequest CreateFetchMessagesRequest(long? lastMessageId = null)
|
protected APIRequest CreateInitialFetchRequest(long? lastMessageId = null)
|
||||||
{
|
{
|
||||||
var fetchReq = new GetUpdatesRequest(lastMessageId ?? this.lastMessageId);
|
var fetchReq = new GetUpdatesRequest(lastMessageId ?? this.lastMessageId);
|
||||||
|
|
||||||
@ -67,8 +67,11 @@ namespace osu.Game.Online.Notifications
|
|||||||
|
|
||||||
protected void HandleChannelParted(Channel channel) => ChannelParted?.Invoke(channel);
|
protected void HandleChannelParted(Channel channel) => ChannelParted?.Invoke(channel);
|
||||||
|
|
||||||
protected void HandleMessages(List<Message> messages)
|
protected void HandleMessages(List<Message>? messages)
|
||||||
{
|
{
|
||||||
|
if (messages == null)
|
||||||
|
return;
|
||||||
|
|
||||||
NewMessages?.Invoke(messages);
|
NewMessages?.Invoke(messages);
|
||||||
lastMessageId = Math.Max(lastMessageId, messages.LastOrDefault()?.Id ?? 0);
|
lastMessageId = Math.Max(lastMessageId, messages.LastOrDefault()?.Id ?? 0);
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ using Newtonsoft.Json;
|
|||||||
|
|
||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
{
|
{
|
||||||
// TODO: Remove disable below after merging https://github.com/ppy/osu-framework/pull/5548 and applying follow-up changes game-side.
|
|
||||||
// ReSharper disable once PartialTypeWithSinglePart
|
|
||||||
public partial class APICreatedRoom : Room
|
public partial class APICreatedRoom : Room
|
||||||
{
|
{
|
||||||
[JsonProperty("error")]
|
[JsonProperty("error")]
|
||||||
|
@ -16,7 +16,7 @@ using osu.Game.Online.Rooms.RoomStatuses;
|
|||||||
namespace osu.Game.Online.Rooms
|
namespace osu.Game.Online.Rooms
|
||||||
{
|
{
|
||||||
[JsonObject(MemberSerialization.OptIn)]
|
[JsonObject(MemberSerialization.OptIn)]
|
||||||
public partial class Room
|
public partial class Room : IDependencyInjectionCandidate
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
[JsonProperty("id")]
|
[JsonProperty("id")]
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -9,25 +8,20 @@ using osu.Framework.Bindables;
|
|||||||
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;
|
||||||
using osu.Framework.Graphics.Cursor;
|
|
||||||
using osu.Framework.Graphics.Effects;
|
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
|
||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
using osuTK;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Chat
|
namespace osu.Game.Overlays.Chat
|
||||||
{
|
{
|
||||||
public partial class ChatLine : CompositeDrawable
|
public partial class ChatLine : CompositeDrawable
|
||||||
{
|
{
|
||||||
|
private Message message = null!;
|
||||||
|
|
||||||
public Message Message
|
public Message Message
|
||||||
{
|
{
|
||||||
get => message;
|
get => message;
|
||||||
@ -44,49 +38,35 @@ namespace osu.Game.Overlays.Chat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LinkFlowContainer ContentFlow { get; private set; } = null!;
|
public IReadOnlyCollection<Drawable> DrawableContentFlow => drawableContentFlow;
|
||||||
|
|
||||||
protected virtual float TextSize => 20;
|
protected virtual float FontSize => 20;
|
||||||
|
|
||||||
protected virtual float Spacing => 15;
|
protected virtual float Spacing => 15;
|
||||||
|
|
||||||
protected virtual float UsernameWidth => 130;
|
protected virtual float UsernameWidth => 130;
|
||||||
|
|
||||||
private Color4 usernameColour;
|
|
||||||
|
|
||||||
private OsuSpriteText timestamp = null!;
|
|
||||||
|
|
||||||
private Message message = null!;
|
|
||||||
|
|
||||||
private OsuSpriteText username = null!;
|
|
||||||
|
|
||||||
private Container? highlight;
|
|
||||||
|
|
||||||
private readonly Bindable<bool> prefer24HourTime = new Bindable<bool>();
|
|
||||||
|
|
||||||
private bool senderHasColour => !string.IsNullOrEmpty(message.Sender.Colour);
|
|
||||||
|
|
||||||
private bool messageHasColour => Message.IsAction && senderHasColour;
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private ChannelManager? chatManager { get; set; }
|
private ChannelManager? chatManager { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuColour colours { get; set; } = null!;
|
private OverlayColourProvider? colourProvider { get; set; }
|
||||||
|
|
||||||
|
private readonly OsuSpriteText drawableTimestamp;
|
||||||
|
|
||||||
|
private readonly DrawableUsername drawableUsername;
|
||||||
|
|
||||||
|
private readonly LinkFlowContainer drawableContentFlow;
|
||||||
|
|
||||||
|
private readonly Bindable<bool> prefer24HourTime = new Bindable<bool>();
|
||||||
|
|
||||||
|
private Container? highlight;
|
||||||
|
|
||||||
public ChatLine(Message message)
|
public ChatLine(Message message)
|
||||||
{
|
{
|
||||||
Message = message;
|
Message = message;
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
AutoSizeAxes = Axes.Y;
|
AutoSizeAxes = Axes.Y;
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OverlayColourProvider? colourProvider, OsuConfigManager configManager)
|
|
||||||
{
|
|
||||||
usernameColour = senderHasColour
|
|
||||||
? Color4Extensions.FromHex(message.Sender.Colour)
|
|
||||||
: username_colours[message.Sender.Id % username_colours.Length];
|
|
||||||
|
|
||||||
InternalChild = new GridContainer
|
InternalChild = new GridContainer
|
||||||
{
|
{
|
||||||
@ -103,30 +83,24 @@ namespace osu.Game.Overlays.Chat
|
|||||||
{
|
{
|
||||||
new Drawable[]
|
new Drawable[]
|
||||||
{
|
{
|
||||||
timestamp = new OsuSpriteText
|
drawableTimestamp = new OsuSpriteText
|
||||||
{
|
{
|
||||||
Shadow = false,
|
Shadow = false,
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Font = OsuFont.GetFont(size: TextSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true),
|
Font = OsuFont.GetFont(size: FontSize * 0.75f, weight: FontWeight.SemiBold, fixedWidth: true),
|
||||||
Colour = colourProvider?.Background1 ?? Colour4.White,
|
|
||||||
AlwaysPresent = true,
|
AlwaysPresent = true,
|
||||||
},
|
},
|
||||||
new MessageSender(message.Sender)
|
drawableUsername = new DrawableUsername(message.Sender)
|
||||||
{
|
{
|
||||||
Width = UsernameWidth,
|
Width = UsernameWidth,
|
||||||
|
FontSize = FontSize,
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
Origin = Anchor.TopRight,
|
Origin = Anchor.TopRight,
|
||||||
Anchor = Anchor.TopRight,
|
Anchor = Anchor.TopRight,
|
||||||
Child = createUsername(),
|
|
||||||
Margin = new MarginPadding { Horizontal = Spacing },
|
Margin = new MarginPadding { Horizontal = Spacing },
|
||||||
},
|
},
|
||||||
ContentFlow = new LinkFlowContainer(t =>
|
drawableContentFlow = new LinkFlowContainer(styleMessageContent)
|
||||||
{
|
|
||||||
t.Shadow = false;
|
|
||||||
t.Font = t.Font.With(size: TextSize, italics: Message.IsAction);
|
|
||||||
t.Colour = messageHasColour ? Color4Extensions.FromHex(message.Sender.Colour) : colourProvider?.Content1 ?? Colour4.White;
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
@ -134,18 +108,23 @@ namespace osu.Game.Overlays.Chat
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(OsuConfigManager configManager)
|
||||||
|
{
|
||||||
configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime);
|
configManager.BindWith(OsuSetting.Prefer24HourTime, prefer24HourTime);
|
||||||
|
prefer24HourTime.BindValueChanged(_ => updateTimestamp());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
|
drawableTimestamp.Colour = colourProvider?.Background1 ?? Colour4.White;
|
||||||
|
|
||||||
updateMessageContent();
|
updateMessageContent();
|
||||||
FinishTransforms(true);
|
FinishTransforms(true);
|
||||||
|
|
||||||
prefer24HourTime.BindValueChanged(_ => updateTimestamp());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -160,7 +139,7 @@ namespace osu.Game.Overlays.Chat
|
|||||||
CornerRadius = 2f,
|
CornerRadius = 2f,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = usernameColour.Darken(1f),
|
Colour = drawableUsername.AccentColour.Darken(1f),
|
||||||
Depth = float.MaxValue,
|
Depth = float.MaxValue,
|
||||||
Child = new Box { RelativeSizeAxes = Axes.Both }
|
Child = new Box { RelativeSizeAxes = Axes.Both }
|
||||||
});
|
});
|
||||||
@ -170,166 +149,35 @@ namespace osu.Game.Overlays.Chat
|
|||||||
highlight.Expire();
|
highlight.Expire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void styleMessageContent(SpriteText text)
|
||||||
|
{
|
||||||
|
text.Shadow = false;
|
||||||
|
text.Font = text.Font.With(size: FontSize, italics: Message.IsAction);
|
||||||
|
|
||||||
|
bool messageHasColour = Message.IsAction && !string.IsNullOrEmpty(message.Sender.Colour);
|
||||||
|
text.Colour = messageHasColour ? Color4Extensions.FromHex(message.Sender.Colour) : colourProvider?.Content1 ?? Colour4.White;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateMessageContent()
|
private void updateMessageContent()
|
||||||
{
|
{
|
||||||
this.FadeTo(message is LocalEchoMessage ? 0.4f : 1.0f, 500, Easing.OutQuint);
|
this.FadeTo(message is LocalEchoMessage ? 0.4f : 1.0f, 500, Easing.OutQuint);
|
||||||
timestamp.FadeTo(message is LocalEchoMessage ? 0 : 1, 500, Easing.OutQuint);
|
drawableTimestamp.FadeTo(message is LocalEchoMessage ? 0 : 1, 500, Easing.OutQuint);
|
||||||
|
|
||||||
updateTimestamp();
|
updateTimestamp();
|
||||||
username.Text = $@"{message.Sender.Username}";
|
drawableUsername.Text = $@"{message.Sender.Username}";
|
||||||
|
|
||||||
// remove non-existent channels from the link list
|
// remove non-existent channels from the link list
|
||||||
message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chatManager?.AvailableChannels.Any(c => c.Name == link.Argument.ToString()) != true);
|
message.Links.RemoveAll(link => link.Action == LinkAction.OpenChannel && chatManager?.AvailableChannels.Any(c => c.Name == link.Argument.ToString()) != true);
|
||||||
|
|
||||||
ContentFlow.Clear();
|
drawableContentFlow.Clear();
|
||||||
ContentFlow.AddLinks(message.DisplayContent, message.Links);
|
drawableContentFlow.AddLinks(message.DisplayContent, message.Links);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTimestamp()
|
private void updateTimestamp()
|
||||||
{
|
{
|
||||||
timestamp.Text = prefer24HourTime.Value
|
drawableTimestamp.Text = prefer24HourTime.Value
|
||||||
? $@"{message.Timestamp.LocalDateTime:HH:mm:ss}"
|
? $@"{message.Timestamp.LocalDateTime:HH:mm:ss}"
|
||||||
: $@"{message.Timestamp.LocalDateTime:hh:mm:ss tt}";
|
: $@"{message.Timestamp.LocalDateTime:hh:mm:ss tt}";
|
||||||
}
|
}
|
||||||
|
|
||||||
private Drawable createUsername()
|
|
||||||
{
|
|
||||||
username = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Shadow = false,
|
|
||||||
Colour = senderHasColour ? colours.ChatBlue : usernameColour,
|
|
||||||
Truncate = true,
|
|
||||||
EllipsisString = "…",
|
|
||||||
Font = OsuFont.GetFont(size: TextSize, weight: FontWeight.Bold, italics: true),
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
MaxWidth = UsernameWidth,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!senderHasColour)
|
|
||||||
return username;
|
|
||||||
|
|
||||||
// Background effect
|
|
||||||
return new Container
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
CornerRadius = 4,
|
|
||||||
EdgeEffect = new EdgeEffectParameters
|
|
||||||
{
|
|
||||||
Roundness = 1,
|
|
||||||
Radius = 1,
|
|
||||||
Colour = Color4.Black.Opacity(0.3f),
|
|
||||||
Offset = new Vector2(0, 1),
|
|
||||||
Type = EdgeEffectType.Shadow,
|
|
||||||
},
|
|
||||||
Child = new Container
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Masking = true,
|
|
||||||
CornerRadius = 4,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new Box
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Colour = usernameColour,
|
|
||||||
},
|
|
||||||
new Container
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Padding = new MarginPadding { Left = 4, Right = 4, Bottom = 1, Top = -2 },
|
|
||||||
Child = username
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private partial class MessageSender : OsuClickableContainer, IHasContextMenu
|
|
||||||
{
|
|
||||||
private readonly APIUser sender;
|
|
||||||
|
|
||||||
private Action startChatAction = null!;
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private IAPIProvider api { get; set; } = null!;
|
|
||||||
|
|
||||||
public MessageSender(APIUser sender)
|
|
||||||
{
|
|
||||||
this.sender = sender;
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(UserProfileOverlay? profile, ChannelManager? chatManager, ChatOverlay? chatOverlay)
|
|
||||||
{
|
|
||||||
Action = () => profile?.ShowUser(sender);
|
|
||||||
startChatAction = () =>
|
|
||||||
{
|
|
||||||
chatManager?.OpenPrivateChannel(sender);
|
|
||||||
chatOverlay?.Show();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public MenuItem[] ContextMenuItems
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (sender.Equals(APIUser.SYSTEM_USER))
|
|
||||||
return Array.Empty<MenuItem>();
|
|
||||||
|
|
||||||
List<MenuItem> items = new List<MenuItem>
|
|
||||||
{
|
|
||||||
new OsuMenuItem("View Profile", MenuItemType.Highlighted, Action)
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!sender.Equals(api.LocalUser.Value))
|
|
||||||
items.Add(new OsuMenuItem("Start Chat", MenuItemType.Standard, startChatAction));
|
|
||||||
|
|
||||||
return items.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly Color4[] username_colours =
|
|
||||||
{
|
|
||||||
Color4Extensions.FromHex("588c7e"),
|
|
||||||
Color4Extensions.FromHex("b2a367"),
|
|
||||||
Color4Extensions.FromHex("c98f65"),
|
|
||||||
Color4Extensions.FromHex("bc5151"),
|
|
||||||
Color4Extensions.FromHex("5c8bd6"),
|
|
||||||
Color4Extensions.FromHex("7f6ab7"),
|
|
||||||
Color4Extensions.FromHex("a368ad"),
|
|
||||||
Color4Extensions.FromHex("aa6880"),
|
|
||||||
|
|
||||||
Color4Extensions.FromHex("6fad9b"),
|
|
||||||
Color4Extensions.FromHex("f2e394"),
|
|
||||||
Color4Extensions.FromHex("f2ae72"),
|
|
||||||
Color4Extensions.FromHex("f98f8a"),
|
|
||||||
Color4Extensions.FromHex("7daef4"),
|
|
||||||
Color4Extensions.FromHex("a691f2"),
|
|
||||||
Color4Extensions.FromHex("c894d3"),
|
|
||||||
Color4Extensions.FromHex("d895b0"),
|
|
||||||
|
|
||||||
Color4Extensions.FromHex("53c4a1"),
|
|
||||||
Color4Extensions.FromHex("eace5c"),
|
|
||||||
Color4Extensions.FromHex("ea8c47"),
|
|
||||||
Color4Extensions.FromHex("fc4f4f"),
|
|
||||||
Color4Extensions.FromHex("3d94ea"),
|
|
||||||
Color4Extensions.FromHex("7760ea"),
|
|
||||||
Color4Extensions.FromHex("af52c6"),
|
|
||||||
Color4Extensions.FromHex("e25696"),
|
|
||||||
|
|
||||||
Color4Extensions.FromHex("677c66"),
|
|
||||||
Color4Extensions.FromHex("9b8732"),
|
|
||||||
Color4Extensions.FromHex("8c5129"),
|
|
||||||
Color4Extensions.FromHex("8c3030"),
|
|
||||||
Color4Extensions.FromHex("1f5d91"),
|
|
||||||
Color4Extensions.FromHex("4335a5"),
|
|
||||||
Color4Extensions.FromHex("812a96"),
|
|
||||||
Color4Extensions.FromHex("992861"),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
225
osu.Game/Overlays/Chat/DrawableUsername.cs
Normal file
225
osu.Game/Overlays/Chat/DrawableUsername.cs
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Cursor;
|
||||||
|
using osu.Framework.Graphics.Effects;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Input.Events;
|
||||||
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
|
using osu.Game.Online.Chat;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Chat
|
||||||
|
{
|
||||||
|
public partial class DrawableUsername : OsuClickableContainer, IHasContextMenu
|
||||||
|
{
|
||||||
|
public Color4 AccentColour { get; }
|
||||||
|
|
||||||
|
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
||||||
|
Child.ReceivePositionalInputAt(screenSpacePos);
|
||||||
|
|
||||||
|
public float FontSize
|
||||||
|
{
|
||||||
|
set => drawableText.Font = OsuFont.GetFont(size: value, weight: FontWeight.Bold, italics: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalisableString Text
|
||||||
|
{
|
||||||
|
set => drawableText.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override float Width
|
||||||
|
{
|
||||||
|
get => base.Width;
|
||||||
|
set => base.Width = drawableText.MaxWidth = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IAPIProvider api { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private ChannelManager? chatManager { get; set; }
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private ChatOverlay? chatOverlay { get; set; }
|
||||||
|
|
||||||
|
[Resolved(canBeNull: true)]
|
||||||
|
private UserProfileOverlay? profileOverlay { get; set; }
|
||||||
|
|
||||||
|
private readonly APIUser user;
|
||||||
|
private readonly OsuSpriteText drawableText;
|
||||||
|
|
||||||
|
private readonly Drawable colouredDrawable;
|
||||||
|
|
||||||
|
public DrawableUsername(APIUser user)
|
||||||
|
{
|
||||||
|
this.user = user;
|
||||||
|
|
||||||
|
Action = openUserProfile;
|
||||||
|
|
||||||
|
drawableText = new OsuSpriteText
|
||||||
|
{
|
||||||
|
Shadow = false,
|
||||||
|
Truncate = true,
|
||||||
|
EllipsisString = "…",
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(user.Colour))
|
||||||
|
{
|
||||||
|
AccentColour = default_colours[user.Id % default_colours.Length];
|
||||||
|
|
||||||
|
Child = colouredDrawable = drawableText;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AccentColour = Color4Extensions.FromHex(user.Colour);
|
||||||
|
|
||||||
|
Child = new Container
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = 4,
|
||||||
|
EdgeEffect = new EdgeEffectParameters
|
||||||
|
{
|
||||||
|
Roundness = 1,
|
||||||
|
Radius = 1,
|
||||||
|
Colour = Color4.Black.Opacity(0.3f),
|
||||||
|
Offset = new Vector2(0, 1),
|
||||||
|
Type = EdgeEffectType.Shadow,
|
||||||
|
},
|
||||||
|
Child = new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = 4,
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
colouredDrawable = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
},
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Padding = new MarginPadding { Left = 4, Right = 4, Bottom = 1, Top = -2 },
|
||||||
|
Child = drawableText,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void LoadComplete()
|
||||||
|
{
|
||||||
|
base.LoadComplete();
|
||||||
|
|
||||||
|
drawableText.Colour = colours.ChatBlue;
|
||||||
|
colouredDrawable.Colour = AccentColour;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuItem[] ContextMenuItems
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (user.Equals(APIUser.SYSTEM_USER))
|
||||||
|
return Array.Empty<MenuItem>();
|
||||||
|
|
||||||
|
List<MenuItem> items = new List<MenuItem>
|
||||||
|
{
|
||||||
|
new OsuMenuItem("View Profile", MenuItemType.Highlighted, openUserProfile)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!user.Equals(api.LocalUser.Value))
|
||||||
|
items.Add(new OsuMenuItem("Start Chat", MenuItemType.Standard, openUserChannel));
|
||||||
|
|
||||||
|
return items.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openUserChannel()
|
||||||
|
{
|
||||||
|
chatManager?.OpenPrivateChannel(user);
|
||||||
|
chatOverlay?.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openUserProfile()
|
||||||
|
{
|
||||||
|
profileOverlay?.ShowUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool OnHover(HoverEvent e)
|
||||||
|
{
|
||||||
|
colouredDrawable.FadeColour(AccentColour.Lighten(0.6f), 30, Easing.OutQuint);
|
||||||
|
|
||||||
|
return base.OnHover(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
|
{
|
||||||
|
base.OnHoverLost(e);
|
||||||
|
|
||||||
|
colouredDrawable.FadeColour(AccentColour, 800, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly Color4[] default_colours =
|
||||||
|
{
|
||||||
|
Color4Extensions.FromHex("588c7e"),
|
||||||
|
Color4Extensions.FromHex("b2a367"),
|
||||||
|
Color4Extensions.FromHex("c98f65"),
|
||||||
|
Color4Extensions.FromHex("bc5151"),
|
||||||
|
Color4Extensions.FromHex("5c8bd6"),
|
||||||
|
Color4Extensions.FromHex("7f6ab7"),
|
||||||
|
Color4Extensions.FromHex("a368ad"),
|
||||||
|
Color4Extensions.FromHex("aa6880"),
|
||||||
|
|
||||||
|
Color4Extensions.FromHex("6fad9b"),
|
||||||
|
Color4Extensions.FromHex("f2e394"),
|
||||||
|
Color4Extensions.FromHex("f2ae72"),
|
||||||
|
Color4Extensions.FromHex("f98f8a"),
|
||||||
|
Color4Extensions.FromHex("7daef4"),
|
||||||
|
Color4Extensions.FromHex("a691f2"),
|
||||||
|
Color4Extensions.FromHex("c894d3"),
|
||||||
|
Color4Extensions.FromHex("d895b0"),
|
||||||
|
|
||||||
|
Color4Extensions.FromHex("53c4a1"),
|
||||||
|
Color4Extensions.FromHex("eace5c"),
|
||||||
|
Color4Extensions.FromHex("ea8c47"),
|
||||||
|
Color4Extensions.FromHex("fc4f4f"),
|
||||||
|
Color4Extensions.FromHex("3d94ea"),
|
||||||
|
Color4Extensions.FromHex("7760ea"),
|
||||||
|
Color4Extensions.FromHex("af52c6"),
|
||||||
|
Color4Extensions.FromHex("e25696"),
|
||||||
|
|
||||||
|
Color4Extensions.FromHex("677c66"),
|
||||||
|
Color4Extensions.FromHex("9b8732"),
|
||||||
|
Color4Extensions.FromHex("8c5129"),
|
||||||
|
Color4Extensions.FromHex("8c3030"),
|
||||||
|
Color4Extensions.FromHex("1f5d91"),
|
||||||
|
Color4Extensions.FromHex("4335a5"),
|
||||||
|
Color4Extensions.FromHex("812a96"),
|
||||||
|
Color4Extensions.FromHex("992861"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -331,11 +331,11 @@ namespace osu.Game.Overlays.Comments
|
|||||||
if (WasDeleted)
|
if (WasDeleted)
|
||||||
makeDeleted();
|
makeDeleted();
|
||||||
|
|
||||||
actionsContainer.AddLink("Copy link", copyUrl);
|
actionsContainer.AddLink(CommonStrings.ButtonsPermalink, copyUrl);
|
||||||
actionsContainer.AddArbitraryDrawable(Empty().With(d => d.Width = 10));
|
actionsContainer.AddArbitraryDrawable(Empty().With(d => d.Width = 10));
|
||||||
|
|
||||||
if (Comment.UserId.HasValue && Comment.UserId.Value == api.LocalUser.Value.Id)
|
if (Comment.UserId.HasValue && Comment.UserId.Value == api.LocalUser.Value.Id)
|
||||||
actionsContainer.AddLink("Delete", deleteComment);
|
actionsContainer.AddLink(CommonStrings.ButtonsDelete, deleteComment);
|
||||||
else
|
else
|
||||||
actionsContainer.AddArbitraryDrawable(new CommentReportButton(Comment));
|
actionsContainer.AddArbitraryDrawable(new CommentReportButton(Comment));
|
||||||
|
|
||||||
@ -553,12 +553,12 @@ namespace osu.Game.Overlays.Comments
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string getParentMessage()
|
private LocalisableString getParentMessage()
|
||||||
{
|
{
|
||||||
if (parentComment == null)
|
if (parentComment == null)
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
||||||
return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? "deleted" : string.Empty;
|
return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? CommentsStrings.Deleted : string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,7 @@ namespace osu.Game.Overlays.FirstRunSetup
|
|||||||
return parentDependencies.Get(type, info);
|
return parentDependencies.Get(type, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inject<T>(T instance) where T : class
|
public void Inject<T>(T instance) where T : class, IDependencyInjectionCandidate
|
||||||
{
|
{
|
||||||
parentDependencies.Inject(instance);
|
parentDependencies.Inject(instance);
|
||||||
}
|
}
|
||||||
|
@ -177,13 +177,7 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
|||||||
updateScreenModeWarning();
|
updateScreenModeWarning();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
windowModes.BindCollectionChanged((_, _) =>
|
windowModes.BindCollectionChanged((_, _) => updateDisplaySettingsVisibility());
|
||||||
{
|
|
||||||
if (windowModes.Count > 1)
|
|
||||||
windowModeDropdown.Show();
|
|
||||||
else
|
|
||||||
windowModeDropdown.Hide();
|
|
||||||
}, true);
|
|
||||||
|
|
||||||
currentDisplay.BindValueChanged(display => Schedule(() =>
|
currentDisplay.BindValueChanged(display => Schedule(() =>
|
||||||
{
|
{
|
||||||
@ -219,7 +213,11 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
|||||||
scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint);
|
scalingSettings.ResizeHeightTo(0, transition_duration, Easing.OutQuint);
|
||||||
|
|
||||||
scalingSettings.AutoSizeAxes = scalingMode.Value != ScalingMode.Off ? Axes.Y : Axes.None;
|
scalingSettings.AutoSizeAxes = scalingMode.Value != ScalingMode.Off ? Axes.Y : Axes.None;
|
||||||
scalingSettings.ForEach(s => s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything);
|
scalingSettings.ForEach(s =>
|
||||||
|
{
|
||||||
|
s.TransferValueOnCommit = scalingMode.Value == ScalingMode.Everything;
|
||||||
|
s.CanBeShown.Value = scalingMode.Value != ScalingMode.Off;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,20 +232,10 @@ namespace osu.Game.Overlays.Settings.Sections.Graphics
|
|||||||
|
|
||||||
private void updateDisplaySettingsVisibility()
|
private void updateDisplaySettingsVisibility()
|
||||||
{
|
{
|
||||||
if (resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen)
|
windowModeDropdown.CanBeShown.Value = windowModes.Count > 1;
|
||||||
resolutionDropdown.Show();
|
resolutionDropdown.CanBeShown.Value = resolutions.Count > 1 && windowModeDropdown.Current.Value == WindowMode.Fullscreen;
|
||||||
else
|
displayDropdown.CanBeShown.Value = displayDropdown.Items.Count() > 1;
|
||||||
resolutionDropdown.Hide();
|
safeAreaConsiderationsCheckbox.CanBeShown.Value = host.Window?.SafeAreaPadding.Value.Total != Vector2.Zero;
|
||||||
|
|
||||||
if (displayDropdown.Items.Count() > 1)
|
|
||||||
displayDropdown.Show();
|
|
||||||
else
|
|
||||||
displayDropdown.Hide();
|
|
||||||
|
|
||||||
if (host.Window?.SafeAreaPadding.Value.Total != Vector2.Zero)
|
|
||||||
safeAreaConsiderationsCheckbox.Show();
|
|
||||||
else
|
|
||||||
safeAreaConsiderationsCheckbox.Hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateScreenModeWarning()
|
private void updateScreenModeWarning()
|
||||||
|
@ -143,6 +143,7 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
areaOffset.SetDefault();
|
areaOffset.SetDefault();
|
||||||
areaSize.SetDefault();
|
areaSize.SetDefault();
|
||||||
},
|
},
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new SettingsButton
|
new SettingsButton
|
||||||
{
|
{
|
||||||
@ -150,25 +151,29 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
Action = () =>
|
Action = () =>
|
||||||
{
|
{
|
||||||
forceAspectRatio((float)host.Window.ClientSize.Width / host.Window.ClientSize.Height);
|
forceAspectRatio((float)host.Window.ClientSize.Width / host.Window.ClientSize.Height);
|
||||||
}
|
},
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new SettingsSlider<float>
|
new SettingsSlider<float>
|
||||||
{
|
{
|
||||||
TransferValueOnCommit = true,
|
TransferValueOnCommit = true,
|
||||||
LabelText = TabletSettingsStrings.XOffset,
|
LabelText = TabletSettingsStrings.XOffset,
|
||||||
Current = offsetX
|
Current = offsetX,
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new SettingsSlider<float>
|
new SettingsSlider<float>
|
||||||
{
|
{
|
||||||
TransferValueOnCommit = true,
|
TransferValueOnCommit = true,
|
||||||
LabelText = TabletSettingsStrings.YOffset,
|
LabelText = TabletSettingsStrings.YOffset,
|
||||||
Current = offsetY
|
Current = offsetY,
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new SettingsSlider<float>
|
new SettingsSlider<float>
|
||||||
{
|
{
|
||||||
TransferValueOnCommit = true,
|
TransferValueOnCommit = true,
|
||||||
LabelText = TabletSettingsStrings.Rotation,
|
LabelText = TabletSettingsStrings.Rotation,
|
||||||
Current = rotation
|
Current = rotation,
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new RotationPresetButtons(tabletHandler)
|
new RotationPresetButtons(tabletHandler)
|
||||||
{
|
{
|
||||||
@ -181,24 +186,28 @@ namespace osu.Game.Overlays.Settings.Sections.Input
|
|||||||
{
|
{
|
||||||
TransferValueOnCommit = true,
|
TransferValueOnCommit = true,
|
||||||
LabelText = TabletSettingsStrings.AspectRatio,
|
LabelText = TabletSettingsStrings.AspectRatio,
|
||||||
Current = aspectRatio
|
Current = aspectRatio,
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new SettingsCheckbox
|
new SettingsCheckbox
|
||||||
{
|
{
|
||||||
LabelText = TabletSettingsStrings.LockAspectRatio,
|
LabelText = TabletSettingsStrings.LockAspectRatio,
|
||||||
Current = aspectLock
|
Current = aspectLock,
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new SettingsSlider<float>
|
new SettingsSlider<float>
|
||||||
{
|
{
|
||||||
TransferValueOnCommit = true,
|
TransferValueOnCommit = true,
|
||||||
LabelText = CommonStrings.Width,
|
LabelText = CommonStrings.Width,
|
||||||
Current = sizeX
|
Current = sizeX,
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
new SettingsSlider<float>
|
new SettingsSlider<float>
|
||||||
{
|
{
|
||||||
TransferValueOnCommit = true,
|
TransferValueOnCommit = true,
|
||||||
LabelText = CommonStrings.Height,
|
LabelText = CommonStrings.Height,
|
||||||
Current = sizeY
|
Current = sizeY,
|
||||||
|
CanBeShown = { BindTarget = enabled }
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3,14 +3,16 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Cursor;
|
using osu.Framework.Graphics.Cursor;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Settings
|
namespace osu.Game.Overlays.Settings
|
||||||
{
|
{
|
||||||
public partial class SettingsButton : RoundedButton, IHasTooltip
|
public partial class SettingsButton : RoundedButton, IHasTooltip, IConditionalFilterable
|
||||||
{
|
{
|
||||||
public SettingsButton()
|
public SettingsButton()
|
||||||
{
|
{
|
||||||
@ -20,6 +22,9 @@ namespace osu.Game.Overlays.Settings
|
|||||||
|
|
||||||
public LocalisableString TooltipText { get; set; }
|
public LocalisableString TooltipText { get; set; }
|
||||||
|
|
||||||
|
public BindableBool CanBeShown { get; } = new BindableBool(true);
|
||||||
|
IBindable<bool> IConditionalFilterable.CanBeShown => CanBeShown;
|
||||||
|
|
||||||
public override IEnumerable<LocalisableString> FilterTerms
|
public override IEnumerable<LocalisableString> FilterTerms
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -22,7 +22,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Settings
|
namespace osu.Game.Overlays.Settings
|
||||||
{
|
{
|
||||||
public abstract partial class SettingsItem<T> : Container, IFilterable, ISettingsItem, IHasCurrentValue<T>, IHasTooltip
|
public abstract partial class SettingsItem<T> : Container, IConditionalFilterable, ISettingsItem, IHasCurrentValue<T>, IHasTooltip
|
||||||
{
|
{
|
||||||
protected abstract Drawable CreateControl();
|
protected abstract Drawable CreateControl();
|
||||||
|
|
||||||
@ -144,6 +144,9 @@ namespace osu.Game.Overlays.Settings
|
|||||||
|
|
||||||
public bool FilteringActive { get; set; }
|
public bool FilteringActive { get; set; }
|
||||||
|
|
||||||
|
public BindableBool CanBeShown { get; } = new BindableBool(true);
|
||||||
|
IBindable<bool> IConditionalFilterable.CanBeShown => CanBeShown;
|
||||||
|
|
||||||
public event Action SettingChanged;
|
public event Action SettingChanged;
|
||||||
|
|
||||||
private T classicDefault;
|
private T classicDefault;
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -19,7 +18,7 @@ using osuTK;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays.Settings
|
namespace osu.Game.Overlays.Settings
|
||||||
{
|
{
|
||||||
public abstract partial class SettingsSection : Container, IHasFilterableChildren
|
public abstract partial class SettingsSection : Container, IFilterable
|
||||||
{
|
{
|
||||||
protected FillFlowContainer FlowContent;
|
protected FillFlowContainer FlowContent;
|
||||||
protected override Container<Drawable> Content => FlowContent;
|
protected override Container<Drawable> Content => FlowContent;
|
||||||
@ -33,7 +32,6 @@ namespace osu.Game.Overlays.Settings
|
|||||||
public abstract Drawable CreateIcon();
|
public abstract Drawable CreateIcon();
|
||||||
public abstract LocalisableString Header { get; }
|
public abstract LocalisableString Header { get; }
|
||||||
|
|
||||||
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
|
||||||
public virtual IEnumerable<LocalisableString> FilterTerms => new[] { Header };
|
public virtual IEnumerable<LocalisableString> FilterTerms => new[] { Header };
|
||||||
|
|
||||||
public const int ITEM_SPACING = 14;
|
public const int ITEM_SPACING = 14;
|
||||||
|
@ -8,7 +8,6 @@ using osu.Framework.Graphics;
|
|||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
@ -17,7 +16,7 @@ using osu.Game.Graphics;
|
|||||||
namespace osu.Game.Overlays.Settings
|
namespace osu.Game.Overlays.Settings
|
||||||
{
|
{
|
||||||
[ExcludeFromDynamicCompile]
|
[ExcludeFromDynamicCompile]
|
||||||
public abstract partial class SettingsSubsection : FillFlowContainer, IHasFilterableChildren
|
public abstract partial class SettingsSubsection : FillFlowContainer, IFilterable
|
||||||
{
|
{
|
||||||
protected override Container<Drawable> Content => FlowContent;
|
protected override Container<Drawable> Content => FlowContent;
|
||||||
|
|
||||||
@ -25,8 +24,6 @@ namespace osu.Game.Overlays.Settings
|
|||||||
|
|
||||||
protected abstract LocalisableString Header { get; }
|
protected abstract LocalisableString Header { get; }
|
||||||
|
|
||||||
public IEnumerable<IFilterable> FilterableChildren => Children.OfType<IFilterable>();
|
|
||||||
|
|
||||||
public virtual IEnumerable<LocalisableString> FilterTerms => new[] { Header };
|
public virtual IEnumerable<LocalisableString> FilterTerms => new[] { Header };
|
||||||
|
|
||||||
public bool MatchingFilter
|
public bool MatchingFilter
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
#nullable disable
|
using System;
|
||||||
|
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.LocalisationExtensions;
|
using osu.Framework.Extensions.LocalisationExtensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -20,6 +19,8 @@ namespace osu.Game.Screens.Edit
|
|||||||
{
|
{
|
||||||
public abstract partial class EditorTable : TableContainer
|
public abstract partial class EditorTable : TableContainer
|
||||||
{
|
{
|
||||||
|
public event Action<Drawable>? OnRowSelected;
|
||||||
|
|
||||||
private const float horizontal_inset = 20;
|
private const float horizontal_inset = 20;
|
||||||
|
|
||||||
protected const float ROW_HEIGHT = 25;
|
protected const float ROW_HEIGHT = 25;
|
||||||
@ -45,7 +46,18 @@ namespace osu.Game.Screens.Edit
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Drawable CreateHeader(int index, TableColumn column) => new HeaderText(column?.Header ?? default);
|
protected void SetSelectedRow(object? item)
|
||||||
|
{
|
||||||
|
foreach (var b in BackgroundFlow)
|
||||||
|
{
|
||||||
|
b.Selected = ReferenceEquals(b.Item, item);
|
||||||
|
|
||||||
|
if (b.Selected)
|
||||||
|
OnRowSelected?.Invoke(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Drawable CreateHeader(int index, TableColumn? column) => new HeaderText(column?.Header ?? default);
|
||||||
|
|
||||||
private partial class HeaderText : OsuSpriteText
|
private partial class HeaderText : OsuSpriteText
|
||||||
{
|
{
|
||||||
@ -84,11 +96,6 @@ namespace osu.Game.Screens.Edit
|
|||||||
Alpha = 0,
|
Alpha = 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo delete
|
|
||||||
Action = () =>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color4 colourHover;
|
private Color4 colourHover;
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -23,10 +21,10 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
public partial class ControlPointTable : EditorTable
|
public partial class ControlPointTable : EditorTable
|
||||||
{
|
{
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Bindable<ControlPointGroup> selectedGroup { get; set; }
|
private Bindable<ControlPointGroup> selectedGroup { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private EditorClock clock { get; set; }
|
private EditorClock clock { get; set; } = null!;
|
||||||
|
|
||||||
public const float TIMING_COLUMN_WIDTH = 230;
|
public const float TIMING_COLUMN_WIDTH = 230;
|
||||||
|
|
||||||
@ -37,7 +35,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
Content = null;
|
Content = null;
|
||||||
BackgroundFlow.Clear();
|
BackgroundFlow.Clear();
|
||||||
|
|
||||||
if (value?.Any() != true)
|
if (!value.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var group in value)
|
foreach (var group in value)
|
||||||
@ -63,19 +61,10 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
{
|
{
|
||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
selectedGroup.BindValueChanged(_ =>
|
selectedGroup.BindValueChanged(_ => updateSelectedGroup(), true);
|
||||||
{
|
|
||||||
// TODO: This should scroll the selected row into view.
|
|
||||||
updateSelectedGroup();
|
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSelectedGroup()
|
private void updateSelectedGroup() => SetSelectedRow(selectedGroup.Value);
|
||||||
{
|
|
||||||
// TODO: This should scroll the selected row into view.
|
|
||||||
foreach (var b in BackgroundFlow)
|
|
||||||
b.Selected = ReferenceEquals(b.Item, selectedGroup?.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private TableColumn[] createHeaders()
|
private TableColumn[] createHeaders()
|
||||||
{
|
{
|
||||||
@ -92,11 +81,19 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
{
|
{
|
||||||
return new Drawable[]
|
return new Drawable[]
|
||||||
{
|
{
|
||||||
new FillFlowContainer
|
new ControlGroupTiming(group),
|
||||||
|
new ControlGroupAttributes(group, c => c is not TimingControlPoint)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private partial class ControlGroupTiming : FillFlowContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Y,
|
public ControlGroupTiming(ControlPointGroup group)
|
||||||
Width = TIMING_COLUMN_WIDTH,
|
{
|
||||||
Spacing = new Vector2(5),
|
Name = @"ControlGroupTiming";
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
Width = TIMING_COLUMN_WIDTH;
|
||||||
|
Spacing = new Vector2(5);
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
@ -112,11 +109,9 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
new ControlGroupAttributes(group, c => !(c is TimingControlPoint))
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private partial class ControlGroupAttributes : CompositeDrawable
|
private partial class ControlGroupAttributes : CompositeDrawable
|
||||||
{
|
{
|
||||||
@ -132,6 +127,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
|
|
||||||
AutoSizeAxes = Axes.X;
|
AutoSizeAxes = Axes.X;
|
||||||
RelativeSizeAxes = Axes.Y;
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
Name = @"ControlGroupAttributes";
|
||||||
|
|
||||||
InternalChild = fill = new FillFlowContainer
|
InternalChild = fill = new FillFlowContainer
|
||||||
{
|
{
|
||||||
@ -161,7 +157,6 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
fill.ChildrenEnumerable = controlPoints
|
fill.ChildrenEnumerable = controlPoints
|
||||||
.Where(matchFunction)
|
.Where(matchFunction)
|
||||||
.Select(createAttribute)
|
.Select(createAttribute)
|
||||||
.Where(c => c != null)
|
|
||||||
// arbitrary ordering to make timing points first.
|
// arbitrary ordering to make timing points first.
|
||||||
// probably want to explicitly define order in the future.
|
// probably want to explicitly define order in the future.
|
||||||
.OrderByDescending(c => c.GetType().Name);
|
.OrderByDescending(c => c.GetType().Name);
|
||||||
@ -184,7 +179,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
return new SampleRowAttribute(sample);
|
return new SampleRowAttribute(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
throw new ArgumentOutOfRangeException(nameof(controlPoint), $"Control point type {controlPoint.GetType()} is not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -50,24 +48,24 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
|
|
||||||
public partial class ControlPointList : CompositeDrawable
|
public partial class ControlPointList : CompositeDrawable
|
||||||
{
|
{
|
||||||
private OsuButton deleteButton;
|
private OsuButton deleteButton = null!;
|
||||||
private ControlPointTable table;
|
private ControlPointTable table = null!;
|
||||||
|
private OsuScrollContainer scroll = null!;
|
||||||
|
private RoundedButton addButton = null!;
|
||||||
|
|
||||||
private readonly IBindableList<ControlPointGroup> controlPointGroups = new BindableList<ControlPointGroup>();
|
private readonly IBindableList<ControlPointGroup> controlPointGroups = new BindableList<ControlPointGroup>();
|
||||||
|
|
||||||
private RoundedButton addButton;
|
[Resolved]
|
||||||
|
private EditorClock clock { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private EditorClock clock { get; set; }
|
protected EditorBeatmap Beatmap { get; private set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
protected EditorBeatmap Beatmap { get; private set; }
|
private Bindable<ControlPointGroup?> selectedGroup { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Bindable<ControlPointGroup> selectedGroup { get; set; }
|
private IEditorChangeHandler? changeHandler { get; set; }
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
|
||||||
private IEditorChangeHandler changeHandler { get; set; }
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OverlayColourProvider colours)
|
private void load(OverlayColourProvider colours)
|
||||||
@ -88,7 +86,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
RelativeSizeAxes = Axes.Y,
|
RelativeSizeAxes = Axes.Y,
|
||||||
Width = ControlPointTable.TIMING_COLUMN_WIDTH + margins,
|
Width = ControlPointTable.TIMING_COLUMN_WIDTH + margins,
|
||||||
},
|
},
|
||||||
new OsuScrollContainer
|
scroll = new OsuScrollContainer
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = table = new ControlPointTable(),
|
Child = table = new ControlPointTable(),
|
||||||
@ -142,6 +140,8 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
table.ControlGroups = controlPointGroups;
|
table.ControlGroups = controlPointGroups;
|
||||||
changeHandler?.SaveState();
|
changeHandler?.SaveState();
|
||||||
}, true);
|
}, true);
|
||||||
|
|
||||||
|
table.OnRowSelected += drawable => scroll.ScrollIntoView(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnClick(ClickEvent e)
|
protected override bool OnClick(ClickEvent e)
|
||||||
@ -159,7 +159,7 @@ namespace osu.Game.Screens.Edit.Timing
|
|||||||
addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time;
|
addButton.Enabled.Value = clock.CurrentTimeAccurate != selectedGroup.Value?.Time;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type trackedType;
|
private Type? trackedType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Given the user has selected a control point group, we want to track any group which is
|
/// Given the user has selected a control point group, we want to track any group which is
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@ -20,19 +18,19 @@ namespace osu.Game.Screens.Edit.Verify
|
|||||||
{
|
{
|
||||||
public partial class IssueTable : EditorTable
|
public partial class IssueTable : EditorTable
|
||||||
{
|
{
|
||||||
[Resolved]
|
private Bindable<Issue> selectedIssue = null!;
|
||||||
private VerifyScreen verify { get; set; }
|
|
||||||
|
|
||||||
private Bindable<Issue> selectedIssue;
|
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private EditorClock clock { get; set; }
|
private VerifyScreen verify { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private EditorBeatmap editorBeatmap { get; set; }
|
private EditorClock clock { get; set; } = null!;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private Editor editor { get; set; }
|
private EditorBeatmap editorBeatmap { get; set; } = null!;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private Editor editor { get; set; } = null!;
|
||||||
|
|
||||||
public IEnumerable<Issue> Issues
|
public IEnumerable<Issue> Issues
|
||||||
{
|
{
|
||||||
@ -41,7 +39,7 @@ namespace osu.Game.Screens.Edit.Verify
|
|||||||
Content = null;
|
Content = null;
|
||||||
BackgroundFlow.Clear();
|
BackgroundFlow.Clear();
|
||||||
|
|
||||||
if (value == null)
|
if (!value.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var issue in value)
|
foreach (var issue in value)
|
||||||
@ -79,7 +77,7 @@ namespace osu.Game.Screens.Edit.Verify
|
|||||||
selectedIssue = verify.SelectedIssue.GetBoundCopy();
|
selectedIssue = verify.SelectedIssue.GetBoundCopy();
|
||||||
selectedIssue.BindValueChanged(issue =>
|
selectedIssue.BindValueChanged(issue =>
|
||||||
{
|
{
|
||||||
foreach (var b in BackgroundFlow) b.Selected = b.Item == issue.NewValue;
|
SetSelectedRow(issue.NewValue);
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,152 +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 osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Framework.Input.Events;
|
|
||||||
using osu.Framework.Localisation;
|
|
||||||
using osu.Game.Configuration;
|
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Localisation;
|
|
||||||
using osuTK;
|
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Select
|
|
||||||
{
|
|
||||||
internal partial class DifficultyRangeFilterControl : CompositeDrawable
|
|
||||||
{
|
|
||||||
private Bindable<double> lowerStars = null!;
|
|
||||||
private Bindable<double> upperStars = null!;
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(OsuConfigManager config)
|
|
||||||
{
|
|
||||||
const float vertical_offset = 13;
|
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = "Difficulty range",
|
|
||||||
Font = OsuFont.GetFont(size: 14),
|
|
||||||
},
|
|
||||||
new MaximumStarsSlider
|
|
||||||
{
|
|
||||||
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
|
|
||||||
KeyboardStep = 0.1f,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Y = vertical_offset,
|
|
||||||
},
|
|
||||||
new MinimumStarsSlider
|
|
||||||
{
|
|
||||||
Current = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
|
|
||||||
KeyboardStep = 0.1f,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Y = vertical_offset,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
lowerStars = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum);
|
|
||||||
upperStars = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
lowerStars.ValueChanged += min => upperStars.Value = Math.Max(min.NewValue + 0.1, upperStars.Value);
|
|
||||||
upperStars.ValueChanged += max => lowerStars.Value = Math.Min(max.NewValue - 0.1, lowerStars.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private partial class MinimumStarsSlider : StarsSlider
|
|
||||||
{
|
|
||||||
public MinimumStarsSlider()
|
|
||||||
: base("0")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public override LocalisableString TooltipText => Current.Value.ToString(@"0.## stars");
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
LeftBox.Height = 6; // hide any colour bleeding from overlap
|
|
||||||
|
|
||||||
AccentColour = BackgroundColour;
|
|
||||||
BackgroundColour = Color4.Transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
|
||||||
base.ReceivePositionalInputAt(screenSpacePos)
|
|
||||||
&& screenSpacePos.X <= Nub.ScreenSpaceDrawQuad.TopRight.X;
|
|
||||||
}
|
|
||||||
|
|
||||||
private partial class MaximumStarsSlider : StarsSlider
|
|
||||||
{
|
|
||||||
public MaximumStarsSlider()
|
|
||||||
: base("∞")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
|
|
||||||
RightBox.Height = 6; // just to match the left bar height really
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) =>
|
|
||||||
base.ReceivePositionalInputAt(screenSpacePos)
|
|
||||||
&& screenSpacePos.X >= Nub.ScreenSpaceDrawQuad.TopLeft.X;
|
|
||||||
}
|
|
||||||
|
|
||||||
private partial class StarsSlider : OsuSliderBar<double>
|
|
||||||
{
|
|
||||||
private readonly string defaultString;
|
|
||||||
|
|
||||||
public override LocalisableString TooltipText => Current.IsDefault
|
|
||||||
? UserInterfaceStrings.NoLimit
|
|
||||||
: Current.Value.ToString(@"0.## stars");
|
|
||||||
|
|
||||||
protected StarsSlider(string defaultString)
|
|
||||||
{
|
|
||||||
this.defaultString = defaultString;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
|
||||||
{
|
|
||||||
base.OnHover(e);
|
|
||||||
return true; // Make sure only one nub shows hover effect at once.
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void LoadComplete()
|
|
||||||
{
|
|
||||||
base.LoadComplete();
|
|
||||||
Nub.Width = Nub.HEIGHT;
|
|
||||||
RangePadding = Nub.Width / 2;
|
|
||||||
|
|
||||||
OsuSpriteText currentDisplay;
|
|
||||||
|
|
||||||
Nub.Add(currentDisplay = new OsuSpriteText
|
|
||||||
{
|
|
||||||
Anchor = Anchor.Centre,
|
|
||||||
Origin = Anchor.Centre,
|
|
||||||
Y = -0.5f,
|
|
||||||
Colour = Color4.White,
|
|
||||||
Font = OsuFont.Torus.With(size: 10),
|
|
||||||
});
|
|
||||||
|
|
||||||
Current.BindValueChanged(current =>
|
|
||||||
{
|
|
||||||
currentDisplay.Text = current.NewValue != Current.Default ? current.NewValue.ToString("N1") : defaultString;
|
|
||||||
}, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,6 +16,7 @@ using osu.Game.Graphics;
|
|||||||
using osu.Game.Graphics.Containers;
|
using osu.Game.Graphics.Containers;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Localisation;
|
||||||
using osu.Game.Resources.Localisation.Web;
|
using osu.Game.Resources.Localisation.Web;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Select.Filter;
|
using osu.Game.Screens.Select.Filter;
|
||||||
@ -172,12 +173,19 @@ namespace osu.Game.Screens.Select
|
|||||||
Height = 40,
|
Height = 40,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new DifficultyRangeFilterControl
|
new RangeSlider
|
||||||
{
|
{
|
||||||
Anchor = Anchor.TopLeft,
|
Anchor = Anchor.TopLeft,
|
||||||
Origin = Anchor.TopLeft,
|
Origin = Anchor.TopLeft,
|
||||||
|
Label = "Difficulty range",
|
||||||
|
LowerBound = config.GetBindable<double>(OsuSetting.DisplayStarsMinimum),
|
||||||
|
UpperBound = config.GetBindable<double>(OsuSetting.DisplayStarsMaximum),
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Width = 0.48f,
|
Width = 0.48f,
|
||||||
|
DefaultStringLowerBound = "0",
|
||||||
|
DefaultStringUpperBound = "∞",
|
||||||
|
DefaultTooltipUpperBound = UserInterfaceStrings.NoLimit,
|
||||||
|
TooltipSuffix = "stars"
|
||||||
},
|
},
|
||||||
collectionDropdown = new CollectionDropdown
|
collectionDropdown = new CollectionDropdown
|
||||||
{
|
{
|
||||||
|
@ -164,7 +164,7 @@ namespace osu.Game.Tests.Beatmaps
|
|||||||
return fallback.Get(type, info);
|
return fallback.Get(type, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Inject<T>(T instance) where T : class
|
public void Inject<T>(T instance) where T : class, IDependencyInjectionCandidate
|
||||||
{
|
{
|
||||||
// Never used directly
|
// Never used directly
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ namespace osu.Game.Tests
|
|||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
await API.PerformAsync(CreateFetchMessagesRequest());
|
await API.PerformAsync(CreateInitialFetchRequest());
|
||||||
await Task.Delay(1000, cancellationToken);
|
await Task.Delay(1000, cancellationToken);
|
||||||
}
|
}
|
||||||
}, cancellationToken);
|
}, cancellationToken);
|
||||||
|
@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
|||||||
=> OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info);
|
=> OnlinePlayDependencies?.Get(type, info) ?? parent.Get(type, info);
|
||||||
|
|
||||||
public void Inject<T>(T instance)
|
public void Inject<T>(T instance)
|
||||||
where T : class
|
where T : class, IDependencyInjectionCandidate
|
||||||
=> injectableDependencies.Inject(instance);
|
=> injectableDependencies.Inject(instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ namespace osu.Game.Tests.Visual.OnlinePlay
|
|||||||
=> dependencies.Get(type, info);
|
=> dependencies.Get(type, info);
|
||||||
|
|
||||||
public void Inject<T>(T instance)
|
public void Inject<T>(T instance)
|
||||||
where T : class
|
where T : class, IDependencyInjectionCandidate
|
||||||
=> dependencies.Inject(instance);
|
=> dependencies.Inject(instance);
|
||||||
|
|
||||||
protected void Cache(object instance)
|
protected void Cache(object instance)
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Realm" Version="10.18.0" />
|
<PackageReference Include="Realm" Version="10.18.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2022.1126.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2022.1130.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1127.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1127.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.23.1" />
|
<PackageReference Include="Sentry" Version="3.23.1" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1127.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2022.1127.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.1126.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2022.1130.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net6.0) -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
@ -82,7 +82,7 @@
|
|||||||
<PackageReference Include="DiffPlex" Version="1.7.1" />
|
<PackageReference Include="DiffPlex" Version="1.7.1" />
|
||||||
<PackageReference Include="Humanizer" Version="2.14.1" />
|
<PackageReference Include="Humanizer" Version="2.14.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2022.1126.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2022.1130.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
<PackageReference Include="SharpCompress" Version="0.32.2" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||||
|
Loading…
Reference in New Issue
Block a user