diff --git a/osu.Game/Skinning/SkinModelManager.cs b/osu.Game/Skinning/SkinModelManager.cs index 40c280c5c2..822cb8efa0 100644 --- a/osu.Game/Skinning/SkinModelManager.cs +++ b/osu.Game/Skinning/SkinModelManager.cs @@ -24,6 +24,8 @@ namespace osu.Game.Skinning { public class SkinModelManager : RealmArchiveModelManager { + private const string skin_info_file = "skininfo.json"; + private readonly IStorageResourceProvider skinResources; public SkinModelManager(Storage storage, RealmContextFactory contextFactory, GameHost host, IStorageResourceProvider skinResources) @@ -49,8 +51,36 @@ namespace osu.Game.Skinning protected override Task Populate(SkinInfo model, ArchiveReader? archive, Realm realm, CancellationToken cancellationToken = default) { - if (string.IsNullOrEmpty(model.InstantiationInfo)) - model.InstantiationInfo = createInstance(model).GetType().GetInvariantInstantiationInfo(); + var skinInfoFile = model.Files.SingleOrDefault(f => f.Filename == skin_info_file); + + if (skinInfoFile != null) + { + try + { + using (var existingStream = Files.Storage.GetStream(skinInfoFile.File.GetStoragePath())) + using (var reader = new StreamReader(existingStream)) + { + var deserialisedSkinInfo = JsonConvert.DeserializeObject(reader.ReadToEnd()); + + if (deserialisedSkinInfo != null) + { + // for now we only care about the instantiation info. + // eventually we probably want to transfer everything across. + model.InstantiationInfo = deserialisedSkinInfo.InstantiationInfo; + } + } + } + catch (Exception e) + { + LogForModel(model, $"Error during {skin_info_file} parsing, falling back to default", e); + + // Not sure if we should still run the import in the case of failure here, but let's do so for now. + model.InstantiationInfo = string.Empty; + } + } + + // Always rewrite instantiation info (even after parsing in from the skin json) for sanity. + model.InstantiationInfo = createInstance(model).GetType().GetInvariantInstantiationInfo(); checkSkinIniMetadata(model, realm); @@ -203,6 +233,15 @@ namespace osu.Game.Skinning { skin.SkinInfo.PerformWrite(s => { + // Serialise out the SkinInfo itself. + string skinInfoJson = JsonConvert.SerializeObject(s, new JsonSerializerSettings { Formatting = Formatting.Indented }); + + using (var streamContent = new MemoryStream(Encoding.UTF8.GetBytes(skinInfoJson))) + { + AddFile(s, streamContent, skin_info_file, s.Realm); + } + + // Then serialise each of the drawable component groups into respective files. foreach (var drawableInfo in skin.DrawableComponentInfo) { string json = JsonConvert.SerializeObject(drawableInfo.Value, new JsonSerializerSettings { Formatting = Formatting.Indented });