diff --git a/osu.Game/Overlays/SkinEditor/SkinEditor.cs b/osu.Game/Overlays/SkinEditor/SkinEditor.cs index ad89057d12..4ef45b8df5 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditor.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditor.cs @@ -125,7 +125,7 @@ namespace osu.Game.Overlays.SkinEditor { Items = new[] { - new EditorMenuItem(Resources.Localisation.Web.CommonStrings.ButtonsSave, MenuItemType.Standard, Save), + new EditorMenuItem(Resources.Localisation.Web.CommonStrings.ButtonsSave, MenuItemType.Standard, () => Save()), new EditorMenuItem(CommonStrings.RevertToDefault, MenuItemType.Destructive, revert), new EditorMenuItemSpacer(), new EditorMenuItem(CommonStrings.Exit, MenuItemType.Standard, () => skinEditorOverlay?.Hide()), @@ -333,7 +333,7 @@ namespace osu.Game.Overlays.SkinEditor } } - public void Save() + public void Save(bool userTriggered = true) { if (!hasBegunMutating) return; @@ -343,8 +343,9 @@ namespace osu.Game.Overlays.SkinEditor foreach (var t in targetContainers) currentSkin.Value.UpdateDrawableTarget(t); - skins.Save(skins.CurrentSkin.Value); - onScreenDisplay?.Display(new SkinEditorToast(ToastStrings.SkinSaved, currentSkin.Value.SkinInfo.ToString() ?? "Unknown")); + // In the case the save was user triggered, always show the save message to make them feel confident. + if (skins.Save(skins.CurrentSkin.Value) || userTriggered) + onScreenDisplay?.Display(new SkinEditorToast(ToastStrings.SkinSaved, currentSkin.Value.SkinInfo.ToString() ?? "Unknown")); } protected override bool OnHover(HoverEvent e) => true; diff --git a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs index 4eff87c5f4..b8da3e3f67 100644 --- a/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs +++ b/osu.Game/Overlays/SkinEditor/SkinEditorOverlay.cs @@ -147,7 +147,7 @@ namespace osu.Game.Overlays.SkinEditor if (skinEditor == null) return; - skinEditor.Save(); + skinEditor.Save(false); // ensure the toolbar is re-hidden even if a new screen decides to try and show it. updateComponentVisibility(); diff --git a/osu.Game/Skinning/SkinImporter.cs b/osu.Game/Skinning/SkinImporter.cs index 1685562cc7..7485a89404 100644 --- a/osu.Game/Skinning/SkinImporter.cs +++ b/osu.Game/Skinning/SkinImporter.cs @@ -179,8 +179,14 @@ namespace osu.Game.Skinning private Skin createInstance(SkinInfo item) => item.CreateInstance(skinResources); - public void Save(Skin skin) + /// + /// Save a skin. Updates any drawable layouts that are out of date. + /// + /// Whether any change actually occurred. + public bool Save(Skin skin) { + bool hadChanges = false; + skin.SkinInfo.PerformWrite(s => { // Update for safety @@ -212,8 +218,14 @@ namespace osu.Game.Skinning } } - s.Hash = ComputeHash(s); + string newHash = ComputeHash(s); + + hadChanges = newHash != s.Hash; + + s.Hash = newHash; }); + + return hadChanges; } } } diff --git a/osu.Game/Skinning/SkinManager.cs b/osu.Game/Skinning/SkinManager.cs index a4cf83b32e..70173d9c2a 100644 --- a/osu.Game/Skinning/SkinManager.cs +++ b/osu.Game/Skinning/SkinManager.cs @@ -192,12 +192,16 @@ namespace osu.Game.Skinning }); } - public void Save(Skin skin) + /// + /// Save a skin. Updates any drawable layouts that are out of date. + /// + /// Whether any change actually occurred. + public bool Save(Skin skin) { if (!skin.SkinInfo.IsManaged) throw new InvalidOperationException($"Attempting to save a skin which is not yet tracked. Call {nameof(EnsureMutableSkin)} first."); - skinImporter.Save(skin); + return skinImporter.Save(skin); } ///