mirror of
https://github.com/ppy/osu.git
synced 2025-01-31 20:12:55 +08:00
Merge branch 'master' into daily-challenge-intro-audio-auto-download
This commit is contained in:
commit
d2c1d83567
@ -10,7 +10,7 @@
|
|||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.802.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.809.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||||
|
@ -11,14 +11,14 @@ namespace osu.Game.Rulesets.Osu.Edit
|
|||||||
{
|
{
|
||||||
public partial class OsuHitObjectInspector : HitObjectInspector
|
public partial class OsuHitObjectInspector : HitObjectInspector
|
||||||
{
|
{
|
||||||
protected override void AddInspectorValues()
|
protected override void AddInspectorValues(HitObject[] objects)
|
||||||
{
|
{
|
||||||
base.AddInspectorValues();
|
base.AddInspectorValues(objects);
|
||||||
|
|
||||||
if (EditorBeatmap.SelectedHitObjects.Count > 0)
|
if (objects.Length > 0)
|
||||||
{
|
{
|
||||||
var firstInSelection = (OsuHitObject)EditorBeatmap.SelectedHitObjects.MinBy(ho => ho.StartTime)!;
|
var firstInSelection = (OsuHitObject)objects.MinBy(ho => ho.StartTime)!;
|
||||||
var lastInSelection = (OsuHitObject)EditorBeatmap.SelectedHitObjects.MaxBy(ho => ho.GetEndTime())!;
|
var lastInSelection = (OsuHitObject)objects.MaxBy(ho => ho.GetEndTime())!;
|
||||||
|
|
||||||
Debug.Assert(firstInSelection != null && lastInSelection != null);
|
Debug.Assert(firstInSelection != null && lastInSelection != null);
|
||||||
|
|
||||||
|
@ -468,6 +468,40 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDecodeBeatmapHitObjectCoordinatesLegacy()
|
||||||
|
{
|
||||||
|
var decoder = new LegacyBeatmapDecoder();
|
||||||
|
|
||||||
|
using (var resStream = TestResources.OpenResource("hitobject-coordinates-legacy.osu"))
|
||||||
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
|
{
|
||||||
|
var hitObjects = decoder.Decode(stream).HitObjects;
|
||||||
|
|
||||||
|
var positionData = hitObjects[0] as IHasPosition;
|
||||||
|
|
||||||
|
Assert.IsNotNull(positionData);
|
||||||
|
Assert.AreEqual(new Vector2(256, 256), positionData!.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDecodeBeatmapHitObjectCoordinatesLazer()
|
||||||
|
{
|
||||||
|
var decoder = new LegacyBeatmapDecoder(LegacyBeatmapEncoder.FIRST_LAZER_VERSION);
|
||||||
|
|
||||||
|
using (var resStream = TestResources.OpenResource("hitobject-coordinates-lazer.osu"))
|
||||||
|
using (var stream = new LineBufferedReader(resStream))
|
||||||
|
{
|
||||||
|
var hitObjects = decoder.Decode(stream).HitObjects;
|
||||||
|
|
||||||
|
var positionData = hitObjects[0] as IHasPosition;
|
||||||
|
|
||||||
|
Assert.IsNotNull(positionData);
|
||||||
|
Assert.AreEqual(new Vector2(256.99853f, 256.001f), positionData!.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestDecodeBeatmapHitObjects()
|
public void TestDecodeBeatmapHitObjects()
|
||||||
{
|
{
|
||||||
|
@ -73,7 +73,12 @@ namespace osu.Game.Tests.Resources
|
|||||||
|
|
||||||
private static string getTempFilename() => temp_storage.GetFullPath(Guid.NewGuid() + ".osz");
|
private static string getTempFilename() => temp_storage.GetFullPath(Guid.NewGuid() + ".osz");
|
||||||
|
|
||||||
private static int importId;
|
private static int testId = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a unique int value which is incremented each call.
|
||||||
|
/// </summary>
|
||||||
|
public static int GetNextTestID() => Interlocked.Increment(ref testId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a test beatmap set model.
|
/// Create a test beatmap set model.
|
||||||
@ -88,7 +93,7 @@ namespace osu.Game.Tests.Resources
|
|||||||
|
|
||||||
RulesetInfo getRuleset() => rulesets?[j++ % rulesets.Length];
|
RulesetInfo getRuleset() => rulesets?[j++ % rulesets.Length];
|
||||||
|
|
||||||
int setId = Interlocked.Increment(ref importId);
|
int setId = GetNextTestID();
|
||||||
|
|
||||||
var metadata = new BeatmapMetadata
|
var metadata = new BeatmapMetadata
|
||||||
{
|
{
|
||||||
|
6
osu.Game.Tests/Resources/hitobject-coordinates-lazer.osu
Normal file
6
osu.Game.Tests/Resources/hitobject-coordinates-lazer.osu
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
osu file format v128
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
// Coordinates should be preserves in lazer beatmaps.
|
||||||
|
|
||||||
|
256.99853,256.001,1000,49,0,0:0:0:0:
|
@ -0,0 +1,5 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
// Coordinates should be truncated to int values in legacy beatmaps.
|
||||||
|
256.99853,256.001,1000,49,0,0:0:0:0:
|
@ -139,8 +139,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private void addRandomPlayer()
|
private void addRandomPlayer()
|
||||||
{
|
{
|
||||||
int randomUser = RNG.Next(200000, 500000);
|
int id = TestResources.GetNextTestID();
|
||||||
multiplayerClient.AddUser(new APIUser { Id = randomUser, Username = $"user {randomUser}" });
|
multiplayerClient.AddUser(new APIUser { Id = id, Username = $"user {id}" });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeLastUser()
|
private void removeLastUser()
|
||||||
|
@ -9,13 +9,13 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Online.API.Requests.Responses;
|
using osu.Game.Online.API.Requests.Responses;
|
||||||
using osu.Game.Online.Chat;
|
using osu.Game.Online.Chat;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Chat.ChannelList;
|
using osu.Game.Overlays.Chat.ChannelList;
|
||||||
using osu.Game.Overlays.Chat.Listing;
|
using osu.Game.Overlays.Chat.Listing;
|
||||||
|
using osu.Game.Tests.Resources;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
@ -160,7 +160,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private Channel createRandomPublicChannel()
|
private Channel createRandomPublicChannel()
|
||||||
{
|
{
|
||||||
int id = RNG.Next(0, 10000);
|
int id = TestResources.GetNextTestID();
|
||||||
return new Channel
|
return new Channel
|
||||||
{
|
{
|
||||||
Name = $"#channel-{id}",
|
Name = $"#channel-{id}",
|
||||||
@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private Channel createRandomPrivateChannel()
|
private Channel createRandomPrivateChannel()
|
||||||
{
|
{
|
||||||
int id = RNG.Next(0, 10000);
|
int id = TestResources.GetNextTestID();
|
||||||
return new Channel(new APIUser
|
return new Channel(new APIUser
|
||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
@ -181,7 +181,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private Channel createRandomAnnounceChannel()
|
private Channel createRandomAnnounceChannel()
|
||||||
{
|
{
|
||||||
int id = RNG.Next(0, 10000);
|
int id = TestResources.GetNextTestID();
|
||||||
return new Channel
|
return new Channel
|
||||||
{
|
{
|
||||||
Name = $"Announce {id}",
|
Name = $"Announce {id}",
|
||||||
|
@ -19,7 +19,6 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
@ -33,6 +32,7 @@ using osu.Game.Overlays.Chat.ChannelList;
|
|||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
using osu.Game.Graphics.UserInterfaceV2;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
|
using osu.Game.Tests.Resources;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Online
|
namespace osu.Game.Tests.Visual.Online
|
||||||
{
|
{
|
||||||
@ -122,7 +122,7 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case PostMessageRequest postMessage:
|
case PostMessageRequest postMessage:
|
||||||
postMessage.TriggerSuccess(new Message(RNG.Next(0, 10000000))
|
postMessage.TriggerSuccess(new Message(TestResources.GetNextTestID())
|
||||||
{
|
{
|
||||||
Content = postMessage.Message.Content,
|
Content = postMessage.Message.Content,
|
||||||
ChannelId = postMessage.Message.ChannelId,
|
ChannelId = postMessage.Message.ChannelId,
|
||||||
@ -719,7 +719,8 @@ namespace osu.Game.Tests.Visual.Online
|
|||||||
|
|
||||||
private Channel createPrivateChannel()
|
private Channel createPrivateChannel()
|
||||||
{
|
{
|
||||||
int id = RNG.Next(0, DummyAPIAccess.DUMMY_USER_ID - 1);
|
int id = TestResources.GetNextTestID();
|
||||||
|
|
||||||
return new Channel(new APIUser
|
return new Channel(new APIUser
|
||||||
{
|
{
|
||||||
Id = id,
|
Id = id,
|
||||||
|
@ -18,6 +18,12 @@ namespace osu.Game.Beatmaps.Formats
|
|||||||
{
|
{
|
||||||
public const int LATEST_VERSION = 14;
|
public const int LATEST_VERSION = 14;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The .osu format (beatmap) version.
|
||||||
|
///
|
||||||
|
/// osu!stable's versions end at <see cref="LATEST_VERSION"/>.
|
||||||
|
/// osu!lazer's versions starts at <see cref="LegacyBeatmapEncoder.FIRST_LAZER_VERSION"/>.
|
||||||
|
/// </summary>
|
||||||
protected readonly int FormatVersion;
|
protected readonly int FormatVersion;
|
||||||
|
|
||||||
protected LegacyDecoder(int version)
|
protected LegacyDecoder(int version)
|
||||||
|
@ -782,7 +782,21 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
throw new AggregateException($"Item: {JsonConvert.SerializeObject(createPlaylistItem(item))}\n\nRoom:{JsonConvert.SerializeObject(APIRoom)}", ex);
|
// Temporary code to attempt to figure out long-term failing tests.
|
||||||
|
bool success = true;
|
||||||
|
int indexOf = -1234;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
indexOf = Room.Playlist.IndexOf(Room.Playlist.Single(existing => existing.ID == item.ID));
|
||||||
|
Room.Playlist[indexOf] = item;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AggregateException($"Index: {indexOf} Length: {Room.Playlist.Count} Retry success: {success} Item: {JsonConvert.SerializeObject(createPlaylistItem(item))}\n\nRoom:{JsonConvert.SerializeObject(APIRoom)}", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemChanged?.Invoke(item);
|
ItemChanged?.Invoke(item);
|
||||||
|
54
osu.Game/Overlays/Volume/MasterVolumeMeter.cs
Normal file
54
osu.Game/Overlays/Volume/MasterVolumeMeter.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Volume
|
||||||
|
{
|
||||||
|
public partial class MasterVolumeMeter : VolumeMeter
|
||||||
|
{
|
||||||
|
private MuteButton muteButton = null!;
|
||||||
|
|
||||||
|
public Bindable<bool> IsMuted { get; } = new Bindable<bool>();
|
||||||
|
|
||||||
|
private readonly BindableDouble muteAdjustment = new BindableDouble();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private VolumeOverlay volumeOverlay { get; set; } = null!;
|
||||||
|
|
||||||
|
public MasterVolumeMeter(string name, float circleSize, Color4 meterColour)
|
||||||
|
: base(name, circleSize, meterColour)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(AudioManager audio)
|
||||||
|
{
|
||||||
|
IsMuted.BindValueChanged(muted =>
|
||||||
|
{
|
||||||
|
if (muted.NewValue)
|
||||||
|
audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment);
|
||||||
|
else
|
||||||
|
audio.RemoveAdjustment(AdjustableProperty.Volume, muteAdjustment);
|
||||||
|
});
|
||||||
|
|
||||||
|
Add(muteButton = new MuteButton
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Blending = BlendingParameters.Additive,
|
||||||
|
X = CircleSize / 2,
|
||||||
|
Y = CircleSize * 0.23f,
|
||||||
|
Current = { BindTarget = IsMuted }
|
||||||
|
});
|
||||||
|
|
||||||
|
muteButton.Current.ValueChanged += _ => volumeOverlay.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ToggleMute() => muteButton.Current.Value = !muteButton.Current.Value;
|
||||||
|
}
|
||||||
|
}
|
@ -7,13 +7,13 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Volume
|
namespace osu.Game.Overlays.Volume
|
||||||
{
|
{
|
||||||
@ -33,18 +33,18 @@ namespace osu.Game.Overlays.Volume
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Color4 hoveredColour, unhoveredColour;
|
private ColourInfo hoveredBorderColour;
|
||||||
|
private ColourInfo unhoveredBorderColour;
|
||||||
private const float width = 100;
|
private CompositeDrawable border = null!;
|
||||||
public const float HEIGHT = 35;
|
|
||||||
|
|
||||||
public MuteButton()
|
public MuteButton()
|
||||||
{
|
{
|
||||||
Content.BorderThickness = 3;
|
const float width = 30;
|
||||||
Content.CornerRadius = HEIGHT / 2;
|
const float height = 30;
|
||||||
Content.CornerExponent = 2;
|
|
||||||
|
|
||||||
Size = new Vector2(width, HEIGHT);
|
Size = new Vector2(width, height);
|
||||||
|
Content.CornerRadius = height / 2;
|
||||||
|
Content.CornerExponent = 2;
|
||||||
|
|
||||||
Action = () => Current.Value = !Current.Value;
|
Action = () => Current.Value = !Current.Value;
|
||||||
}
|
}
|
||||||
@ -52,10 +52,9 @@ namespace osu.Game.Overlays.Volume
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colours)
|
private void load(OsuColour colours)
|
||||||
{
|
{
|
||||||
hoveredColour = colours.YellowDark;
|
|
||||||
|
|
||||||
Content.BorderColour = unhoveredColour = colours.Gray1;
|
|
||||||
BackgroundColour = colours.Gray1;
|
BackgroundColour = colours.Gray1;
|
||||||
|
hoveredBorderColour = colours.PinkLight;
|
||||||
|
unhoveredBorderColour = colours.Gray1;
|
||||||
|
|
||||||
SpriteIcon icon;
|
SpriteIcon icon;
|
||||||
|
|
||||||
@ -65,26 +64,39 @@ namespace osu.Game.Overlays.Volume
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
},
|
||||||
|
border = new CircularContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
BorderThickness = 3,
|
||||||
|
BorderColour = unhoveredBorderColour,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Alpha = 0,
|
||||||
|
AlwaysPresent = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Current.BindValueChanged(muted =>
|
Current.BindValueChanged(muted =>
|
||||||
{
|
{
|
||||||
icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeMute : FontAwesome.Solid.VolumeUp;
|
icon.Icon = muted.NewValue ? FontAwesome.Solid.VolumeMute : FontAwesome.Solid.VolumeUp;
|
||||||
icon.Size = new Vector2(muted.NewValue ? 18 : 20);
|
icon.Size = new Vector2(muted.NewValue ? 12 : 16);
|
||||||
icon.Margin = new MarginPadding { Right = muted.NewValue ? 2 : 0 };
|
icon.Margin = new MarginPadding { Right = muted.NewValue ? 2 : 0 };
|
||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnHover(HoverEvent e)
|
protected override bool OnHover(HoverEvent e)
|
||||||
{
|
{
|
||||||
Content.TransformTo<Container<Drawable>, ColourInfo>("BorderColour", hoveredColour, 500, Easing.OutQuint);
|
border.TransformTo(nameof(BorderColour), hoveredBorderColour, 500, Easing.OutQuint);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHoverLost(HoverLostEvent e)
|
protected override void OnHoverLost(HoverLostEvent e)
|
||||||
{
|
{
|
||||||
Content.TransformTo<Container<Drawable>, ColourInfo>("BorderColour", unhoveredColour, 500, Easing.OutQuint);
|
border.TransformTo(nameof(BorderColour), unhoveredBorderColour, 500, Easing.OutQuint);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool OnMouseDown(MouseDownEvent e)
|
protected override bool OnMouseDown(MouseDownEvent e)
|
||||||
|
@ -35,8 +35,12 @@ namespace osu.Game.Overlays.Volume
|
|||||||
private CircularProgress volumeCircle;
|
private CircularProgress volumeCircle;
|
||||||
private CircularProgress volumeCircleGlow;
|
private CircularProgress volumeCircleGlow;
|
||||||
|
|
||||||
|
protected static readonly Vector2 LABEL_SIZE = new Vector2(120, 20);
|
||||||
|
|
||||||
public BindableDouble Bindable { get; } = new BindableDouble { MinValue = 0, MaxValue = 1, Precision = 0.01 };
|
public BindableDouble Bindable { get; } = new BindableDouble { MinValue = 0, MaxValue = 1, Precision = 0.01 };
|
||||||
private readonly float circleSize;
|
|
||||||
|
protected readonly float CircleSize;
|
||||||
|
|
||||||
private readonly Color4 meterColour;
|
private readonly Color4 meterColour;
|
||||||
private readonly string name;
|
private readonly string name;
|
||||||
|
|
||||||
@ -73,7 +77,7 @@ namespace osu.Game.Overlays.Volume
|
|||||||
|
|
||||||
public VolumeMeter(string name, float circleSize, Color4 meterColour)
|
public VolumeMeter(string name, float circleSize, Color4 meterColour)
|
||||||
{
|
{
|
||||||
this.circleSize = circleSize;
|
CircleSize = circleSize;
|
||||||
this.meterColour = meterColour;
|
this.meterColour = meterColour;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
|
||||||
@ -101,7 +105,7 @@ namespace osu.Game.Overlays.Volume
|
|||||||
{
|
{
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
Size = new Vector2(circleSize),
|
Size = new Vector2(CircleSize),
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new BufferedContainer
|
new BufferedContainer
|
||||||
@ -199,7 +203,7 @@ namespace osu.Game.Overlays.Volume
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Font = OsuFont.Numeric.With(size: 0.16f * circleSize)
|
Font = OsuFont.Numeric.With(size: 0.16f * CircleSize)
|
||||||
}).WithEffect(new GlowEffect
|
}).WithEffect(new GlowEffect
|
||||||
{
|
{
|
||||||
Colour = Color4.Transparent,
|
Colour = Color4.Transparent,
|
||||||
@ -209,10 +213,10 @@ namespace osu.Game.Overlays.Volume
|
|||||||
},
|
},
|
||||||
new Container
|
new Container
|
||||||
{
|
{
|
||||||
Size = new Vector2(120, 20),
|
Size = LABEL_SIZE,
|
||||||
CornerRadius = 10,
|
CornerRadius = 10,
|
||||||
Masking = true,
|
Masking = true,
|
||||||
Margin = new MarginPadding { Left = circleSize + 10 },
|
Margin = new MarginPadding { Left = CircleSize + 10 },
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
@ -20,21 +21,19 @@ using osuTK.Graphics;
|
|||||||
|
|
||||||
namespace osu.Game.Overlays
|
namespace osu.Game.Overlays
|
||||||
{
|
{
|
||||||
|
[Cached]
|
||||||
public partial class VolumeOverlay : VisibilityContainer
|
public partial class VolumeOverlay : VisibilityContainer
|
||||||
{
|
{
|
||||||
|
public Bindable<bool> IsMuted { get; } = new Bindable<bool>();
|
||||||
|
|
||||||
private const float offset = 10;
|
private const float offset = 10;
|
||||||
|
|
||||||
private VolumeMeter volumeMeterMaster = null!;
|
private VolumeMeter volumeMeterMaster = null!;
|
||||||
private VolumeMeter volumeMeterEffect = null!;
|
private VolumeMeter volumeMeterEffect = null!;
|
||||||
private VolumeMeter volumeMeterMusic = null!;
|
private VolumeMeter volumeMeterMusic = null!;
|
||||||
private MuteButton muteButton = null!;
|
|
||||||
|
|
||||||
private SelectionCycleFillFlowContainer<VolumeMeter> volumeMeters = null!;
|
private SelectionCycleFillFlowContainer<VolumeMeter> volumeMeters = null!;
|
||||||
|
|
||||||
private readonly BindableDouble muteAdjustment = new BindableDouble();
|
|
||||||
|
|
||||||
public Bindable<bool> IsMuted { get; } = new Bindable<bool>();
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(AudioManager audio, OsuColour colours)
|
private void load(AudioManager audio, OsuColour colours)
|
||||||
{
|
{
|
||||||
@ -49,14 +48,7 @@ namespace osu.Game.Overlays
|
|||||||
Width = 300,
|
Width = 300,
|
||||||
Colour = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.75f), Color4.Black.Opacity(0))
|
Colour = ColourInfo.GradientHorizontal(Color4.Black.Opacity(0.75f), Color4.Black.Opacity(0))
|
||||||
},
|
},
|
||||||
muteButton = new MuteButton
|
new FillFlowContainer
|
||||||
{
|
|
||||||
Anchor = Anchor.BottomLeft,
|
|
||||||
Origin = Anchor.BottomLeft,
|
|
||||||
Margin = new MarginPadding(10),
|
|
||||||
Current = { BindTarget = IsMuted }
|
|
||||||
},
|
|
||||||
volumeMeters = new SelectionCycleFillFlowContainer<VolumeMeter>
|
|
||||||
{
|
{
|
||||||
Direction = FillDirection.Vertical,
|
Direction = FillDirection.Vertical,
|
||||||
AutoSizeAxes = Axes.Both,
|
AutoSizeAxes = Axes.Both,
|
||||||
@ -64,26 +56,29 @@ namespace osu.Game.Overlays
|
|||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Spacing = new Vector2(0, offset),
|
Spacing = new Vector2(0, offset),
|
||||||
Margin = new MarginPadding { Left = offset },
|
Margin = new MarginPadding { Left = offset },
|
||||||
Children = new[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
volumeMeterEffect = new VolumeMeter("EFFECTS", 125, colours.BlueDarker),
|
volumeMeters = new SelectionCycleFillFlowContainer<VolumeMeter>
|
||||||
volumeMeterMaster = new VolumeMeter("MASTER", 150, colours.PinkDarker),
|
{
|
||||||
volumeMeterMusic = new VolumeMeter("MUSIC", 125, colours.BlueDarker),
|
Direction = FillDirection.Vertical,
|
||||||
}
|
AutoSizeAxes = Axes.Both,
|
||||||
}
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Spacing = new Vector2(0, offset),
|
||||||
|
Children = new[]
|
||||||
|
{
|
||||||
|
volumeMeterEffect = new VolumeMeter("EFFECTS", 125, colours.BlueDarker),
|
||||||
|
volumeMeterMaster = new MasterVolumeMeter("MASTER", 150, colours.PinkDarker) { IsMuted = { BindTarget = IsMuted }, },
|
||||||
|
volumeMeterMusic = new VolumeMeter("MUSIC", 125, colours.BlueDarker),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
volumeMeterMaster.Bindable.BindTo(audio.Volume);
|
volumeMeterMaster.Bindable.BindTo(audio.Volume);
|
||||||
volumeMeterEffect.Bindable.BindTo(audio.VolumeSample);
|
volumeMeterEffect.Bindable.BindTo(audio.VolumeSample);
|
||||||
volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack);
|
volumeMeterMusic.Bindable.BindTo(audio.VolumeTrack);
|
||||||
|
|
||||||
IsMuted.BindValueChanged(muted =>
|
|
||||||
{
|
|
||||||
if (muted.NewValue)
|
|
||||||
audio.AddAdjustment(AdjustableProperty.Volume, muteAdjustment);
|
|
||||||
else
|
|
||||||
audio.RemoveAdjustment(AdjustableProperty.Volume, muteAdjustment);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
@ -92,8 +87,6 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
foreach (var volumeMeter in volumeMeters)
|
foreach (var volumeMeter in volumeMeters)
|
||||||
volumeMeter.Bindable.ValueChanged += _ => Show();
|
volumeMeter.Bindable.ValueChanged += _ => Show();
|
||||||
|
|
||||||
muteButton.Current.ValueChanged += _ => Show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Adjust(GlobalAction action, float amount = 1, bool isPrecise = false)
|
public bool Adjust(GlobalAction action, float amount = 1, bool isPrecise = false)
|
||||||
@ -130,7 +123,7 @@ namespace osu.Game.Overlays
|
|||||||
|
|
||||||
case GlobalAction.ToggleMute:
|
case GlobalAction.ToggleMute:
|
||||||
Show();
|
Show();
|
||||||
muteButton.Current.Value = !muteButton.Current.Value;
|
volumeMeters.OfType<MasterVolumeMeter>().First().ToggleMute();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
protected readonly double Offset;
|
protected readonly double Offset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The beatmap version.
|
/// The .osu format (beatmap) version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly int FormatVersion;
|
protected readonly int FormatVersion;
|
||||||
|
|
||||||
@ -48,7 +48,10 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
{
|
{
|
||||||
string[] split = text.Split(',');
|
string[] split = text.Split(',');
|
||||||
|
|
||||||
Vector2 pos = new Vector2((int)Parsing.ParseFloat(split[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE));
|
Vector2 pos =
|
||||||
|
FormatVersion >= LegacyBeatmapEncoder.FIRST_LAZER_VERSION
|
||||||
|
? new Vector2(Parsing.ParseFloat(split[0], Parsing.MAX_COORDINATE_VALUE), Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE))
|
||||||
|
: new Vector2((int)Parsing.ParseFloat(split[0], Parsing.MAX_COORDINATE_VALUE), (int)Parsing.ParseFloat(split[1], Parsing.MAX_COORDINATE_VALUE));
|
||||||
|
|
||||||
double startTime = Parsing.ParseDouble(split[2]) + Offset;
|
double startTime = Parsing.ParseDouble(split[2]) + Offset;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Extensions.TypeExtensions;
|
using osu.Framework.Extensions.TypeExtensions;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
@ -16,6 +17,7 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
base.LoadComplete();
|
base.LoadComplete();
|
||||||
|
|
||||||
EditorBeatmap.SelectedHitObjects.CollectionChanged += (_, _) => updateInspectorText();
|
EditorBeatmap.SelectedHitObjects.CollectionChanged += (_, _) => updateInspectorText();
|
||||||
|
EditorBeatmap.PlacementObject.BindValueChanged(_ => updateInspectorText());
|
||||||
EditorBeatmap.TransactionBegan += updateInspectorText;
|
EditorBeatmap.TransactionBegan += updateInspectorText;
|
||||||
EditorBeatmap.TransactionEnded += updateInspectorText;
|
EditorBeatmap.TransactionEnded += updateInspectorText;
|
||||||
updateInspectorText();
|
updateInspectorText();
|
||||||
@ -29,24 +31,33 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
rollingTextUpdate?.Cancel();
|
rollingTextUpdate?.Cancel();
|
||||||
rollingTextUpdate = null;
|
rollingTextUpdate = null;
|
||||||
|
|
||||||
AddInspectorValues();
|
HitObject[] objects;
|
||||||
|
|
||||||
|
if (EditorBeatmap.SelectedHitObjects.Count > 0)
|
||||||
|
objects = EditorBeatmap.SelectedHitObjects.ToArray();
|
||||||
|
else if (EditorBeatmap.PlacementObject.Value != null)
|
||||||
|
objects = new[] { EditorBeatmap.PlacementObject.Value };
|
||||||
|
else
|
||||||
|
objects = Array.Empty<HitObject>();
|
||||||
|
|
||||||
|
AddInspectorValues(objects);
|
||||||
|
|
||||||
// I'd hope there's a better way to do this, but I don't want to bind to each and every property above to watch for changes.
|
// I'd hope there's a better way to do this, but I don't want to bind to each and every property above to watch for changes.
|
||||||
// This is a good middle-ground for the time being.
|
// This is a good middle-ground for the time being.
|
||||||
if (EditorBeatmap.SelectedHitObjects.Count > 0)
|
if (objects.Length > 0)
|
||||||
rollingTextUpdate ??= Scheduler.AddDelayed(updateInspectorText, 250);
|
rollingTextUpdate ??= Scheduler.AddDelayed(updateInspectorText, 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void AddInspectorValues()
|
protected virtual void AddInspectorValues(HitObject[] objects)
|
||||||
{
|
{
|
||||||
switch (EditorBeatmap.SelectedHitObjects.Count)
|
switch (objects.Length)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
AddValue("No selection");
|
AddValue("No selection");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
var selected = EditorBeatmap.SelectedHitObjects.Single();
|
var selected = objects.Single();
|
||||||
|
|
||||||
AddHeader("Type");
|
AddHeader("Type");
|
||||||
AddValue($"{selected.GetType().ReadableName()}");
|
AddValue($"{selected.GetType().ReadableName()}");
|
||||||
@ -105,13 +116,13 @@ namespace osu.Game.Screens.Edit.Compose.Components
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
AddHeader("Selected Objects");
|
AddHeader("Selected Objects");
|
||||||
AddValue($"{EditorBeatmap.SelectedHitObjects.Count:#,0.##}");
|
AddValue($"{objects.Length:#,0.##}");
|
||||||
|
|
||||||
AddHeader("Start Time");
|
AddHeader("Start Time");
|
||||||
AddValue($"{EditorBeatmap.SelectedHitObjects.Min(o => o.StartTime):#,0.##}ms");
|
AddValue($"{objects.Min(o => o.StartTime):#,0.##}ms");
|
||||||
|
|
||||||
AddHeader("End Time");
|
AddHeader("End Time");
|
||||||
AddValue($"{EditorBeatmap.SelectedHitObjects.Max(o => o.GetEndTime()):#,0.##}ms");
|
AddValue($"{objects.Max(o => o.GetEndTime()):#,0.##}ms");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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="11.5.0" />
|
<PackageReference Include="Realm" Version="11.5.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2024.802.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2024.809.2" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.802.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.802.0" />
|
||||||
<PackageReference Include="Sentry" Version="4.3.0" />
|
<PackageReference Include="Sentry" Version="4.3.0" />
|
||||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||||
|
@ -23,6 +23,6 @@
|
|||||||
<RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.802.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.809.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
Loading…
Reference in New Issue
Block a user