mirror of
https://github.com/ppy/osu.git
synced 2026-06-02 20:20:23 +08:00
Compare commits
7 Commits
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
Reference in New Issue
Block a user