forked from ppy/osu
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSerialisedDrawableInfo.cs
More file actions
131 lines (107 loc) · 4.66 KB
/
Copy pathSerialisedDrawableInfo.cs
File metadata and controls
131 lines (107 loc) · 4.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// 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;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Newtonsoft.Json;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using osu.Game.Configuration;
using osu.Game.Extensions;
using osu.Game.Rulesets;
using System.Numerics;
namespace osu.Game.Skinning
{
/// <summary>
/// Serialised backing data for <see cref="ISerialisableDrawable"/>s.
/// Used for json serialisation in user skins.
/// </summary>
/// <remarks>
/// Can be created using <see cref="SerialisableDrawableExtensions.CreateSerialisedInfo"/>.
/// Can also be applied to an existing drawable using <see cref="SerialisableDrawableExtensions.ApplySerialisedInfo"/>.
/// </remarks>
[Serializable]
public sealed class SerialisedDrawableInfo
{
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
public Type Type { get; set; } = null!;
public Vector2 Position { get; set; }
public float Rotation { get; set; }
public Vector2 Scale { get; set; } = Vector2.One;
public float? Width { get; set; }
public float? Height { get; set; }
public Anchor Anchor { get; set; } = Anchor.TopLeft;
public Anchor Origin { get; set; } = Anchor.TopLeft;
/// <inheritdoc cref="ISerialisableDrawable.UsesFixedAnchor"/>
public bool UsesFixedAnchor { get; set; }
public Dictionary<string, object> Settings { get; set; } = new Dictionary<string, object>();
public List<SerialisedDrawableInfo> Children { get; } = new List<SerialisedDrawableInfo>();
[JsonConstructor]
public SerialisedDrawableInfo()
{
}
/// <summary>
/// Construct a new instance populating all attributes from the provided drawable.
/// </summary>
/// <param name="component">The drawable which attributes should be sourced from.</param>
public SerialisedDrawableInfo(Drawable component)
{
Type = component.GetType();
Position = component.Position;
Rotation = component.Rotation;
Scale = component.Scale;
if ((component as CompositeDrawable)?.AutoSizeAxes.HasFlag(Axes.X) != true)
Width = component.Width;
if ((component as CompositeDrawable)?.AutoSizeAxes.HasFlag(Axes.Y) != true)
Height = component.Height;
Anchor = component.Anchor;
Origin = component.Origin;
if (component is ISerialisableDrawable serialisableDrawable)
UsesFixedAnchor = serialisableDrawable.UsesFixedAnchor;
foreach (var (_, property) in component.GetSettingsSourceProperties())
{
var bindable = (IBindable)property.GetValue(component)!;
Settings.Add(property.Name.ToSnakeCase(), bindable.GetUnderlyingSettingValue());
}
if (component is Container<Drawable> container)
{
foreach (var child in container.OfType<ISerialisableDrawable>().OfType<Drawable>())
Children.Add(child.CreateSerialisedInfo());
}
}
/// <summary>
/// Construct an instance of the drawable with all attributes applied.
/// </summary>
/// <returns>The new instance.</returns>
public Drawable CreateInstance()
{
try
{
Drawable d = (Drawable)Activator.CreateInstance(Type)!;
d.ApplySerialisedInfo(this);
return d;
}
catch (Exception e)
{
Logger.Error(e, $"Unable to create skin component {Type.Name}");
return Drawable.Empty();
}
}
/// <summary>
/// Retrieve all types available which support serialisation.
/// </summary>
/// <param name="ruleset">The ruleset to filter results to. If <c>null</c>, global components will be returned instead.</param>
public static Type[] GetAllAvailableDrawables(RulesetInfo? ruleset = null)
{
return (ruleset?.CreateInstance().GetType() ?? typeof(OsuGame))
.Assembly.GetTypes()
.Where(t => !t.IsInterface && !t.IsAbstract && t.IsPublic)
.Where(t => typeof(ISerialisableDrawable).IsAssignableFrom(t))
.OrderBy(t => t.Name)
.ToArray();
}
}
}