mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:37:28 +08:00
Merge branch 'master' into update-hit-error-icons
This commit is contained in:
commit
d6b1e68ee7
@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.306.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2024.329.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
@ -6,6 +6,7 @@ using System.Text;
|
||||
using DiscordRPC;
|
||||
using DiscordRPC.Message;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
@ -78,9 +79,13 @@ namespace osu.Desktop
|
||||
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Message} ({e.Code})", LoggingTarget.Network, LogLevel.Error);
|
||||
|
||||
// A URI scheme is required to support game invitations, as well as informing Discord of the game executable path to support launching the game when a user clicks on join/spectate.
|
||||
client.RegisterUriScheme();
|
||||
client.Subscribe(EventType.Join);
|
||||
client.OnJoin += onJoin;
|
||||
// The library doesn't properly support URI registration when ran from an app bundle on macOS.
|
||||
if (!RuntimeInfo.IsApple)
|
||||
{
|
||||
client.RegisterUriScheme();
|
||||
client.Subscribe(EventType.Join);
|
||||
client.OnJoin += onJoin;
|
||||
}
|
||||
|
||||
config.BindWith(OsuSetting.DiscordRichPresence, privacyMode);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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 osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
@ -45,10 +46,32 @@ namespace osu.Game.Storyboards
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public double CommandsStartTime => timelines.Min(static t => t.StartTime);
|
||||
public double CommandsStartTime
|
||||
{
|
||||
get
|
||||
{
|
||||
double min = double.MaxValue;
|
||||
|
||||
for (int i = 0; i < timelines.Length; i++)
|
||||
min = Math.Min(min, timelines[i].StartTime);
|
||||
|
||||
return min;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public double CommandsEndTime => timelines.Max(static t => t.EndTime);
|
||||
public double CommandsEndTime
|
||||
{
|
||||
get
|
||||
{
|
||||
double max = double.MinValue;
|
||||
|
||||
for (int i = 0; i < timelines.Length; i++)
|
||||
max = Math.Max(max, timelines[i].EndTime);
|
||||
|
||||
return max;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonIgnore]
|
||||
public double CommandsDuration => CommandsEndTime - CommandsStartTime;
|
||||
@ -60,7 +83,19 @@ namespace osu.Game.Storyboards
|
||||
public virtual double EndTime => CommandsEndTime;
|
||||
|
||||
[JsonIgnore]
|
||||
public bool HasCommands => timelines.Any(static t => t.HasCommands);
|
||||
public bool HasCommands
|
||||
{
|
||||
get
|
||||
{
|
||||
for (int i = 0; i < timelines.Length; i++)
|
||||
{
|
||||
if (timelines[i].HasCommands)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual IEnumerable<CommandTimeline<T>.TypedCommand> GetCommands<T>(CommandTimelineSelector<T> timelineSelector, double offset = 0)
|
||||
{
|
||||
|
@ -85,23 +85,12 @@ namespace osu.Game.Storyboards
|
||||
{
|
||||
get
|
||||
{
|
||||
double latestEndTime = double.MaxValue;
|
||||
|
||||
// Ignore the whole setup if there are loops. In theory they can be handled here too, however the logic will be overly complex.
|
||||
if (loops.Count == 0)
|
||||
{
|
||||
// Take the minimum time of all the potential "death" reasons.
|
||||
latestEndTime = calculateOptimisedEndTime(TimelineGroup);
|
||||
}
|
||||
|
||||
// If the logic above fails to find anything or discarded by the fact that there are loops present, latestEndTime will be double.MaxValue
|
||||
// and thus conservativeEndTime will be used.
|
||||
double conservativeEndTime = TimelineGroup.EndTime;
|
||||
double latestEndTime = TimelineGroup.EndTime;
|
||||
|
||||
foreach (var l in loops)
|
||||
conservativeEndTime = Math.Max(conservativeEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations);
|
||||
latestEndTime = Math.Max(latestEndTime, l.StartTime + l.CommandsDuration * l.TotalIterations);
|
||||
|
||||
return Math.Min(latestEndTime, conservativeEndTime);
|
||||
return latestEndTime;
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,47 +194,6 @@ namespace osu.Game.Storyboards
|
||||
return commands;
|
||||
}
|
||||
|
||||
private static double calculateOptimisedEndTime(CommandTimelineGroup timelineGroup)
|
||||
{
|
||||
// Here we are starting from maximum value and trying to minimise the end time on each step.
|
||||
// There are few solid guesses we can make using which sprite's end time can be minimised: alpha = 0, scale = 0, colour.a = 0.
|
||||
double[] deathTimes =
|
||||
{
|
||||
double.MaxValue, // alpha
|
||||
double.MaxValue, // colour alpha
|
||||
double.MaxValue, // scale
|
||||
double.MaxValue, // scale x
|
||||
double.MaxValue, // scale y
|
||||
};
|
||||
|
||||
// The loops below are following the same pattern.
|
||||
// We could be using TimelineGroup.EndValue here, however it's possible to have multiple commands with 0 value in a row
|
||||
// so we are saving the earliest of them.
|
||||
foreach (var alphaCommand in timelineGroup.Alpha.Commands)
|
||||
{
|
||||
if (alphaCommand.EndValue == 0)
|
||||
// commands are ordered by the start time, however end time may vary. Save the earliest.
|
||||
deathTimes[0] = Math.Min(alphaCommand.EndTime, deathTimes[0]);
|
||||
else
|
||||
// If value isn't 0 (sprite becomes visible again), revert the saved state.
|
||||
deathTimes[0] = double.MaxValue;
|
||||
}
|
||||
|
||||
foreach (var colourCommand in timelineGroup.Colour.Commands)
|
||||
deathTimes[1] = colourCommand.EndValue.A == 0 ? Math.Min(colourCommand.EndTime, deathTimes[1]) : double.MaxValue;
|
||||
|
||||
foreach (var scaleCommand in timelineGroup.Scale.Commands)
|
||||
deathTimes[2] = scaleCommand.EndValue == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[2]) : double.MaxValue;
|
||||
|
||||
foreach (var scaleCommand in timelineGroup.VectorScale.Commands)
|
||||
{
|
||||
deathTimes[3] = scaleCommand.EndValue.X == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[3]) : double.MaxValue;
|
||||
deathTimes[4] = scaleCommand.EndValue.Y == 0 ? Math.Min(scaleCommand.EndTime, deathTimes[4]) : double.MaxValue;
|
||||
}
|
||||
|
||||
return deathTimes.Min();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> $"{Path}, {Origin}, {InitialPosition}";
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Realm" Version="11.5.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2024.306.0" />
|
||||
<PackageReference Include="ppy.osu.Framework" Version="2024.329.0" />
|
||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2024.404.0" />
|
||||
<PackageReference Include="Sentry" Version="3.41.3" />
|
||||
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
|
||||
|
@ -23,6 +23,6 @@
|
||||
<RuntimeIdentifier>iossimulator-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.306.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2024.329.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
Loading…
Reference in New Issue
Block a user