mirror of
https://github.com/ppy/osu.git
synced 2025-01-26 20:23:00 +08:00
Hook up full save/load flow
This commit is contained in:
parent
004798d61d
commit
b248b2e5e3
@ -1,15 +0,0 @@
|
||||
// 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 osu.Game.Skinning;
|
||||
|
||||
namespace osu.Game.Screens.Play.HUD
|
||||
{
|
||||
/// <summary>
|
||||
/// A container which supports skinnable components being added to it.
|
||||
/// </summary>
|
||||
public interface ISkinnableTarget
|
||||
{
|
||||
public SkinnableTarget Target { get; }
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ using osuTK;
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
[Cached]
|
||||
public class HUDOverlay : Container, IKeyBindingHandler<GlobalAction>, IDefaultSkinnableTarget
|
||||
public class HUDOverlay : Container, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
public const float FADE_DURATION = 300;
|
||||
|
||||
|
@ -2,17 +2,11 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
@ -20,35 +14,11 @@ namespace osu.Game.Skinning
|
||||
public class DefaultSkin : Skin
|
||||
{
|
||||
public DefaultSkin()
|
||||
: base(SkinInfo.Default)
|
||||
: base(SkinInfo.Default, null)
|
||||
{
|
||||
Configuration = new DefaultSkinConfiguration();
|
||||
}
|
||||
|
||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||
{
|
||||
switch (component)
|
||||
{
|
||||
case SkinnableTargetComponent target:
|
||||
switch (target.Target)
|
||||
{
|
||||
case SkinnableTarget.MainHUDComponents:
|
||||
var infos = JsonConvert.DeserializeObject<IEnumerable<SkinnableInfo>>(File.ReadAllText("/Users/Dean/json-out.json")).Where(i => i.Target == SkinnableTarget.MainHUDComponents);
|
||||
|
||||
var container = new SkinnableTargetWrapper(target.Target)
|
||||
{
|
||||
ChildrenEnumerable = infos.Select(i => i.CreateInstance())
|
||||
};
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT) => null;
|
||||
|
||||
public override ISample GetSample(ISampleInfo sampleInfo) => null;
|
||||
@ -72,14 +42,4 @@ namespace osu.Game.Skinning
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class SkinnableTargetWrapper : Container, ISkinnableTarget
|
||||
{
|
||||
public SkinnableTarget Target { get; }
|
||||
|
||||
public SkinnableTargetWrapper(SkinnableTarget target)
|
||||
{
|
||||
Target = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Screens.Edit.Compose.Components;
|
||||
|
||||
@ -32,11 +29,6 @@ namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
ISkinnableComponent[] skinnableComponents = target.ChildrenOfType<ISkinnableComponent>().ToArray();
|
||||
|
||||
// todo: the OfType() call can be removed with better IDrawable support.
|
||||
string json = JsonConvert.SerializeObject(skinnableComponents.OfType<Drawable>().Select(d => d.CreateSerialisedInformation()), new JsonSerializerSettings { Formatting = Formatting.Indented });
|
||||
|
||||
File.WriteAllText("/Users/Dean/json-out.json", json);
|
||||
|
||||
foreach (var c in skinnableComponents)
|
||||
AddBlueprintFor(c);
|
||||
|
||||
|
@ -11,6 +11,8 @@ using osu.Framework.Testing;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
|
||||
namespace osu.Game.Skinning.Editor
|
||||
{
|
||||
@ -24,6 +26,9 @@ namespace osu.Game.Skinning.Editor
|
||||
|
||||
protected override bool StartHidden => true;
|
||||
|
||||
[Resolved]
|
||||
private SkinManager skins { get; set; }
|
||||
|
||||
public SkinEditor(Drawable target)
|
||||
{
|
||||
this.target = target;
|
||||
@ -53,7 +58,24 @@ namespace osu.Game.Skinning.Editor
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
RequestPlacement = placeComponent
|
||||
}
|
||||
},
|
||||
new TriangleButton
|
||||
{
|
||||
Text = "Save Changes",
|
||||
Width = 140,
|
||||
Height = 50,
|
||||
Padding = new MarginPadding
|
||||
{
|
||||
Top = 10,
|
||||
Left = 10,
|
||||
},
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Right = 10,
|
||||
Bottom = 10,
|
||||
},
|
||||
Action = save,
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -71,7 +93,7 @@ namespace osu.Game.Skinning.Editor
|
||||
|
||||
var targetContainer = target.ChildrenOfType<IDefaultSkinnableTarget>().FirstOrDefault();
|
||||
|
||||
targetContainer?.Add(instance);
|
||||
(targetContainer as Container)?.Add(instance);
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@ -80,6 +102,23 @@ namespace osu.Game.Skinning.Editor
|
||||
Show();
|
||||
}
|
||||
|
||||
private void save()
|
||||
{
|
||||
var currentSkin = skins.CurrentSkin.Value;
|
||||
|
||||
var legacySkin = currentSkin as LegacySkin;
|
||||
|
||||
if (legacySkin == null)
|
||||
return;
|
||||
|
||||
SkinnableElementTargetContainer[] targetContainers = target.ChildrenOfType<SkinnableElementTargetContainer>().ToArray();
|
||||
|
||||
foreach (var t in targetContainers)
|
||||
legacySkin.UpdateDrawableTarget(t);
|
||||
|
||||
skins.Save(skins.CurrentSkin.Value);
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e) => true;
|
||||
|
||||
protected override bool OnMouseDown(MouseDownEvent e) => true;
|
||||
|
@ -2,14 +2,14 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
/// <summary>
|
||||
/// Denotes a container which can house <see cref="ISkinnableComponent"/>s.
|
||||
/// </summary>
|
||||
public interface ISkinnableTarget : IContainerCollection<Drawable>
|
||||
public interface ISkinnableTarget : IDrawable
|
||||
{
|
||||
public SkinnableTarget Target { get; }
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Skinning
|
||||
}
|
||||
|
||||
protected LegacySkin(SkinInfo skin, [CanBeNull] IResourceStore<byte[]> storage, [CanBeNull] IStorageResourceProvider resources, string filename)
|
||||
: base(skin)
|
||||
: base(skin, resources)
|
||||
{
|
||||
using (var stream = storage?.GetStream(filename))
|
||||
{
|
||||
@ -321,8 +321,32 @@ namespace osu.Game.Skinning
|
||||
|
||||
public override Drawable GetDrawableComponent(ISkinComponent component)
|
||||
{
|
||||
if (base.GetDrawableComponent(component) is Drawable c)
|
||||
return c;
|
||||
|
||||
switch (component)
|
||||
{
|
||||
case SkinnableTargetComponent target:
|
||||
|
||||
switch (target.Target)
|
||||
{
|
||||
case SkinnableTarget.MainHUDComponents:
|
||||
return new SkinnableTargetWrapper(target.Target)
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new[]
|
||||
{
|
||||
// TODO: these should fallback to the osu!classic skin.
|
||||
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ComboCounter)) ?? new DefaultComboCounter(),
|
||||
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.ScoreCounter)) ?? new DefaultScoreCounter(),
|
||||
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.AccuracyCounter)) ?? new DefaultAccuracyCounter(),
|
||||
GetDrawableComponent(new HUDSkinComponent(HUDSkinComponents.HealthDisplay)) ?? new DefaultHealthDisplay(),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
case HUDSkinComponent hudComponent:
|
||||
{
|
||||
if (!this.HasFont(LegacyFont.Score))
|
||||
|
@ -2,12 +2,19 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.IO;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
|
||||
namespace osu.Game.Skinning
|
||||
{
|
||||
@ -15,9 +22,13 @@ namespace osu.Game.Skinning
|
||||
{
|
||||
public readonly SkinInfo SkinInfo;
|
||||
|
||||
private readonly IStorageResourceProvider resources;
|
||||
|
||||
public SkinConfiguration Configuration { get; protected set; }
|
||||
|
||||
public abstract Drawable GetDrawableComponent(ISkinComponent componentName);
|
||||
public IDictionary<SkinnableTarget, SkinnableInfo[]> DrawableComponentInfo => drawableComponentInfo;
|
||||
|
||||
private readonly Dictionary<SkinnableTarget, SkinnableInfo[]> drawableComponentInfo = new Dictionary<SkinnableTarget, SkinnableInfo[]>();
|
||||
|
||||
public abstract ISample GetSample(ISampleInfo sampleInfo);
|
||||
|
||||
@ -27,9 +38,62 @@ namespace osu.Game.Skinning
|
||||
|
||||
public abstract IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup);
|
||||
|
||||
protected Skin(SkinInfo skin)
|
||||
protected Skin(SkinInfo skin, IStorageResourceProvider resources)
|
||||
{
|
||||
SkinInfo = skin;
|
||||
|
||||
// may be null for default skin.
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
public void UpdateDrawableTarget(SkinnableElementTargetContainer targetContainer)
|
||||
{
|
||||
DrawableComponentInfo[targetContainer.Target] = targetContainer.CreateSerialisedChildren().ToArray();
|
||||
}
|
||||
|
||||
public virtual Drawable GetDrawableComponent(ISkinComponent component)
|
||||
{
|
||||
switch (component)
|
||||
{
|
||||
case SkinnableTargetComponent target:
|
||||
|
||||
var skinnableTarget = target.Target;
|
||||
|
||||
if (!DrawableComponentInfo.TryGetValue(skinnableTarget, out var skinnableInfo))
|
||||
{
|
||||
switch (skinnableTarget)
|
||||
{
|
||||
case SkinnableTarget.MainHUDComponents:
|
||||
|
||||
// skininfo files may be null for default skin.
|
||||
var fileInfo = SkinInfo.Files?.FirstOrDefault(f => f.Filename == $"{skinnableTarget}.json");
|
||||
|
||||
if (fileInfo == null)
|
||||
return null;
|
||||
|
||||
var bytes = resources?.Files.Get(fileInfo.FileInfo.StoragePath);
|
||||
|
||||
if (bytes == null)
|
||||
return null;
|
||||
|
||||
string jsonContent = Encoding.UTF8.GetString(bytes);
|
||||
|
||||
DrawableComponentInfo[skinnableTarget] = skinnableInfo =
|
||||
JsonConvert.DeserializeObject<IEnumerable<SkinnableInfo>>(jsonContent).Where(i => i.Target == SkinnableTarget.MainHUDComponents).ToArray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (skinnableInfo == null)
|
||||
return null;
|
||||
|
||||
return new SkinnableTargetWrapper(skinnableTarget)
|
||||
{
|
||||
ChildrenEnumerable = skinnableInfo.Select(i => i.CreateInstance())
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#region Disposal
|
||||
@ -58,4 +122,17 @@ namespace osu.Game.Skinning
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class SkinnableTargetWrapper : Container, IDefaultSkinnableTarget
|
||||
{
|
||||
// this is just here to implement the interface and allow a silly parent lookup to work (where the target is not the direct parent for reasons).
|
||||
// TODO: need to fix this.
|
||||
public SkinnableTarget Target { get; }
|
||||
|
||||
public SkinnableTargetWrapper(SkinnableTarget target)
|
||||
{
|
||||
Target = target;
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,11 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using osu.Framework.Audio;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
@ -17,6 +19,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Utils;
|
||||
@ -158,6 +161,35 @@ namespace osu.Game.Skinning
|
||||
return new LegacySkin(skinInfo, this);
|
||||
}
|
||||
|
||||
public void Save(Skin skin)
|
||||
{
|
||||
// some skins don't support saving just yet.
|
||||
// eventually we will want to create a copy of the skin to allow for customisation.
|
||||
if (skin.SkinInfo.Files == null)
|
||||
return;
|
||||
|
||||
foreach (var drawableInfo in skin.DrawableComponentInfo)
|
||||
{
|
||||
// todo: the OfType() call can be removed with better IDrawable support.
|
||||
string json = JsonConvert.SerializeObject(drawableInfo.Value, new JsonSerializerSettings { Formatting = Formatting.Indented });
|
||||
|
||||
using (var streamContent = new MemoryStream(Encoding.UTF8.GetBytes(json)))
|
||||
{
|
||||
string filename = $"{drawableInfo.Key}.json";
|
||||
|
||||
var oldFile = skin.SkinInfo.Files.FirstOrDefault(f => f.Filename == filename);
|
||||
|
||||
if (oldFile != null)
|
||||
ReplaceFile(skin.SkinInfo, oldFile, streamContent, oldFile.Filename);
|
||||
else
|
||||
AddFile(skin.SkinInfo, streamContent, filename);
|
||||
|
||||
Logger.Log($"Saving out {filename} with {json.Length} bytes");
|
||||
Logger.Log(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a lookup query on available <see cref="SkinInfo"/>s.
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user