1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-02 20:20:23 +08:00

Compare commits

...

7 Commits

15 changed files with 214 additions and 41 deletions
@@ -3,11 +3,16 @@
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Rulesets.Catch.Edit.Blueprints;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit.Components.TernaryButtons;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
@@ -22,6 +27,29 @@ namespace osu.Game.Rulesets.Catch.Edit
{
}
protected override Drawable CreateNewComboButton() => new NewComboTernaryButton
{
Current = NewCombo,
CreateIcon = () => new Container
{
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Icon = OsuIcon.EditorFruit,
Size = new Vector2(15),
},
new SpriteIcon
{
Icon = OsuIcon.EditorNewComboSparkles,
Size = new Vector2(20),
}
},
},
};
protected override SelectionHandler<HitObject> CreateSelectionHandler() => new CatchSelectionHandler();
public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject)
@@ -3,11 +3,16 @@
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Mania.Edit.Blueprints;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects;
using osu.Game.Screens.Edit.Components.TernaryButtons;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
@@ -22,6 +27,29 @@ namespace osu.Game.Rulesets.Mania.Edit
{
}
protected override Drawable CreateNewComboButton() => new NewComboTernaryButton
{
Current = NewCombo,
CreateIcon = () => new Container
{
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Icon = OsuIcon.EditorNote,
Size = new Vector2(15),
},
new SpriteIcon
{
Icon = OsuIcon.EditorNewComboSparkles,
Size = new Vector2(20),
}
},
},
};
public override HitObjectSelectionBlueprint? CreateHitObjectBlueprintFor(HitObject hitObject)
{
switch (hitObject)
@@ -3,10 +3,15 @@
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Game.Graphics;
using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Taiko.Edit.Blueprints;
using osu.Game.Screens.Edit.Components.TernaryButtons;
using osu.Game.Screens.Edit.Compose.Components;
using osuTK;
@@ -21,6 +26,29 @@ namespace osu.Game.Rulesets.Taiko.Edit
{
}
protected override Drawable CreateNewComboButton() => new NewComboTernaryButton
{
Current = NewCombo,
CreateIcon = () => new Container
{
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
Icon = OsuIcon.EditorHit,
Size = new Vector2(15),
},
new SpriteIcon
{
Icon = OsuIcon.EditorNewComboSparkles,
Size = new Vector2(20),
}
},
},
};
protected override SelectionHandler<HitObject> CreateSelectionHandler() => new TaikoSelectionHandler();
public override HitObjectSelectionBlueprint CreateHitObjectBlueprintFor(HitObject hitObject) =>
@@ -122,6 +122,29 @@ namespace osu.Game.Tests.Beatmaps.IO
() => Is.EqualTo(384).Within(0.00001));
}
[Test]
public void TestBackgroundSpecificationPreserved()
{
IWorkingBeatmap beatmap = null!;
MemoryStream outStream = null!;
// Ensure importer encoding is correct
AddStep("import beatmap", () => beatmap = importBeatmapFromArchives(@"241526 Soleily - Renatus.osz"));
AddAssert("beatmap background is correct", () => beatmap.BeatmapInfo.Metadata.BackgroundFile, () => Is.EqualTo("machinetop_background.jpg"));
// Ensure exporter legacy conversion is correct
AddStep("export", () =>
{
outStream = new MemoryStream();
new LegacyBeatmapExporter(LocalStorage)
.ExportToStream((BeatmapSetInfo)beatmap.BeatmapInfo.BeatmapSet!, outStream, null);
});
AddStep("import beatmap again", () => beatmap = importBeatmapFromStream(outStream));
AddAssert("beatmap background is still correct", () => beatmap.BeatmapInfo.Metadata.BackgroundFile, () => Is.EqualTo("machinetop_background.jpg"));
}
[Test]
public void TestExportStability()
{
@@ -74,6 +74,8 @@ namespace osu.Game.Database
using var storyboardStreamReader = new LineBufferedReader(storyboardStream);
var beatmapStoryboard = new LegacyStoryboardDecoder().Decode(storyboardStreamReader);
beatmapStoryboard.Beatmap = beatmapContent;
beatmapStoryboard.BeatmapInfo = beatmapInfo;
MutateBeatmap(model, playableBeatmap);
+3 -3
View File
@@ -107,7 +107,7 @@ namespace osu.Game.Graphics
public static IconUsage EditorDistanceSnap => get(OsuIconMapping.EditorDistanceSnap);
public static IconUsage EditorFinish => get(OsuIconMapping.EditorFinish);
public static IconUsage EditorGridSnap => get(OsuIconMapping.EditorGridSnap);
public static IconUsage EditorNewCombo => get(OsuIconMapping.EditorNewCombo);
public static IconUsage EditorNewComboSparkles => get(OsuIconMapping.EditorNewComboSparkles);
public static IconUsage EditorSelect => get(OsuIconMapping.EditorSelect);
public static IconUsage EditorSound => get(OsuIconMapping.EditorSound);
public static IconUsage EditorWhistle => get(OsuIconMapping.EditorWhistle);
@@ -459,8 +459,8 @@ namespace osu.Game.Graphics
[Description(@"Editor/grid-snap")]
EditorGridSnap,
[Description(@"Editor/new-combo")]
EditorNewCombo,
[Description(@"Editor/new-combo-sparkles")]
EditorNewComboSparkles,
[Description(@"Editor/select")]
EditorSelect,
@@ -1011,6 +1011,7 @@ namespace osu.Game.Online.Multiplayer
APIRoom.AutoStartDuration = Room.Settings.AutoStartDuration;
APIRoom.CurrentPlaylistItem = APIRoom.Playlist.Single(item => item.ID == settings.PlaylistItemId);
APIRoom.AutoSkip = Room.Settings.AutoSkip;
APIRoom.MaxParticipants = Room.Settings.MaxParticipants;
SettingsChanged?.Invoke(settings);
RoomUpdated?.Invoke();
+8 -1
View File
@@ -1301,10 +1301,17 @@ namespace osu.Game
applyConfigMigrations();
string lastVersion = LocalConfig.Get<string>(OsuSetting.Version);
string version = Version;
// only show a notification if we've previously saved a version to the config file (ie. not the first run).
if (IsDeployedBuild && !string.IsNullOrEmpty(lastVersion) && version != lastVersion)
Notifications.Post(new UpdateCompleteNotification(version));
// finally, update the version stored to the configuration.
// this MUST happen after `applyConfigMigrations()` call, as it relies on comparing the previous version.
// debug / local compilations will reset to a non-release string.
LocalConfig.SetValue(OsuSetting.Version, Version);
LocalConfig.SetValue(OsuSetting.Version, version);
}
/// <summary>
@@ -29,6 +29,8 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
{
public partial class NewComboTernaryButton : CompositeDrawable, IHasCurrentValue<TernaryState>
{
public Func<Drawable>? CreateIcon { get; init; }
public Bindable<TernaryState> Current
{
get => current.Current;
@@ -61,7 +63,7 @@ namespace osu.Game.Screens.Edit.Components.TernaryButtons
{
Current = Current,
Description = "New combo",
CreateIcon = () => new SpriteIcon { Icon = OsuIcon.EditorNewCombo },
CreateIcon = CreateIcon,
},
},
pickerButton = new ColourPickerButton
@@ -181,13 +181,50 @@ namespace osu.Game.Screens.Edit.Compose.Components
public SampleBankTernaryButton[] SampleBankTernaryStates { get; private set; }
/// <summary>
/// Create the new combo ternary button. Mainly used to customize the displayed icon
/// depending on the ruleset. Can be overriden to return null if a ruleset does not
/// provide combo-supporting HitObjects.
/// </summary>
/// <returns></returns>
[CanBeNull]
protected virtual Drawable CreateNewComboButton() => new NewComboTernaryButton
{
Current = NewCombo,
CreateIcon = () => new Container
{
Children = new Drawable[]
{
new SpriteIcon
{
Anchor = Anchor.BottomLeft,
Origin = Anchor.BottomLeft,
// This is currently using the osu! hitcircle icon as a default in order
// not to break any custom rulesets that depend on there being a defined
// new combo button.
// Could consider removing it and let rulesets specify their own buttons/icons.
Icon = OsuIcon.EditorHitCircle,
Size = new Vector2(15),
},
new SpriteIcon
{
Icon = OsuIcon.EditorNewComboSparkles,
Size = new Vector2(20),
}
},
},
};
/// <summary>
/// Create all ternary states required to be displayed to the user.
/// </summary>
protected virtual IEnumerable<Drawable> CreateTernaryButtons()
{
//TODO: this should only be enabled (visible?) for rulesets that provide combo-supporting HitObjects.
yield return new NewComboTernaryButton { Current = NewCombo };
var newComboButton = CreateNewComboButton();
if (newComboButton != null)
yield return newComboButton;
foreach (var kvp in SelectionHandler.SelectionSampleStates)
{
@@ -77,6 +77,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
private DrawableSample resultsAppearSample = null!;
private DrawableSample dmgFlySample = null!;
private DrawableSample dmgHitSample = null!;
private DrawableSample damageMultiplierSample = null!;
private DrawableSample damageMultiplierUpSample = null!;
private DrawableSample damageMultiplierDownSample = null!;
private DrawableSample hpDownSample = null!;
private DrawableSample playerAppearSample = null!;
private DrawableSample pseudoScoreCounterSample = null!;
@@ -337,6 +340,9 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
resultsAppearSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/results-appear")),
dmgFlySample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-fly")),
dmgHitSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-hit")),
damageMultiplierSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-multiplier")),
damageMultiplierUpSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-multiplier-up")),
damageMultiplierDownSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/dmg-multiplier-down")),
hpDownSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/hp-down")),
playerAppearSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/players-appear")),
pseudoScoreCounterSample = new DrawableSample(audio.Samples.Get(@"Multiplayer/Matchmaking/Ranked/Results/pseudo-score-counter")),
@@ -515,14 +521,22 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
));
}
int pitchChangeAmount = 0;
foreach (var breakdown in damageBreakdowns)
{
using (BeginDelayedSequence(delay))
{
int pitch = pitchChangeAmount;
Schedule(() =>
{
damageBreakdownValueText.Text = breakdown.displayValue;
damageBreakdownSourceText.Text = breakdown.source;
SampleChannel damageBreakdownChannel = damageMultiplierSample.GetChannel();
damageBreakdownChannel.Frequency.Value = 1f + (pitch * .1f);
damageBreakdownChannel.Play();
});
damageBreakdownContainer.MoveToX(120)
@@ -540,7 +554,16 @@ namespace osu.Game.Screens.OnlinePlay.Matchmaking.RankedPlay
.ScaleTo(new Vector2(1.25f), 200, Easing.OutQuint)
.Then()
.ScaleTo(Vector2.One, 200);
SampleChannel scoreChangeChannel = breakdown.rawDamage > 0 ? damageMultiplierUpSample.GetChannel() : damageMultiplierDownSample.GetChannel();
scoreChangeChannel.Frequency.Value = 1f + (pitch * .1f);
scoreChangeChannel.Play();
});
if (breakdown.rawDamage > 0)
pitchChangeAmount++;
else if (breakdown.rawDamage < 0)
pitchChangeAmount--;
}
}
@@ -63,7 +63,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
for (byte i = 0; i < slotUserIds.Length; ++i)
{
var participant = slotUserIds[i] == null ? Slot.Empty(i) : Slot.FromUser(client.Room.Users.Single(u => u.UserID == slotUserIds[i]));
var user = slotUserIds[i] != null ? client.Room.Users.SingleOrDefault(u => u.UserID == slotUserIds[i]) : null;
var participant = user == null ? Slot.Empty(i) : Slot.FromUser(client.Room.Users.Single(u => u.UserID == slotUserIds[i]));
if (i >= slots.Count)
slots.Add(participant);
+1 -1
View File
@@ -18,7 +18,7 @@ namespace osu.Game.Storyboards
private readonly Dictionary<string, StoryboardLayer> layers = new Dictionary<string, StoryboardLayer>();
public IEnumerable<StoryboardLayer> Layers => layers.Values;
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
public BeatmapInfo BeatmapInfo { get; set; } = new BeatmapInfo();
public IBeatmap Beatmap { get; set; } = new Beatmap();
/// <summary>
+25 -32
View File
@@ -56,15 +56,8 @@ namespace osu.Game.Updater
{
base.LoadComplete();
string version = game.Version;
string lastVersion = config.Get<string>(OsuSetting.Version);
if (game.IsDeployedBuild)
{
// only show a notification if we've previously saved a version to the config file (ie. not the first run).
if (!string.IsNullOrEmpty(lastVersion) && version != lastVersion)
Notifications.Post(new UpdateCompleteNotification(version));
// make sure the release stream setting matches the build which was just run.
if (FixedReleaseStream != null)
config.SetValue(OsuSetting.ReleaseStream, FixedReleaseStream.Value);
@@ -137,31 +130,6 @@ namespace osu.Game.Updater
updateCancellationSource.Dispose();
}
private partial class UpdateCompleteNotification : SimpleNotification
{
private readonly string version;
public UpdateCompleteNotification(string version)
{
this.version = version;
Text = NotificationsStrings.GameVersionAfterUpdate(version);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours, ChangelogOverlay changelog, INotificationOverlay notificationOverlay)
{
Icon = FontAwesome.Solid.CheckSquare;
IconContent.Colour = colours.BlueDark;
Activated = delegate
{
notificationOverlay.Hide();
changelog.ShowBuild(version);
return true;
};
}
}
public partial class UpdateDownloadProgressNotification : ProgressNotification
{
private readonly CancellationToken cancellationToken;
@@ -259,4 +227,29 @@ namespace osu.Game.Updater
}
}
}
public partial class UpdateCompleteNotification : SimpleNotification
{
private readonly string version;
public UpdateCompleteNotification(string version)
{
this.version = version;
Text = NotificationsStrings.GameVersionAfterUpdate(version);
}
[BackgroundDependencyLoader]
private void load(OsuColour colours, ChangelogOverlay changelog, INotificationOverlay notificationOverlay)
{
Icon = FontAwesome.Solid.CheckSquare;
IconContent.Colour = colours.BlueDark;
Activated = delegate
{
notificationOverlay.Hide();
changelog.ShowBuild(version);
return true;
};
}
}
}
+1 -1
View File
@@ -40,7 +40,7 @@
</PackageReference>
<PackageReference Include="Realm" Version="20.1.0" />
<PackageReference Include="ppy.osu.Framework" Version="2026.521.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2026.521.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2026.523.0" />
<PackageReference Include="Sentry" Version="6.2.0" />
<!-- Held back due to 0.34.0 failing AOT compilation on ZstdSharp.dll dependency. -->
<PackageReference Include="SharpCompress" Version="0.48.0" />