forked from gilzoide/unity-runtime-preset
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRuntimePreset.cs
119 lines (106 loc) · 4.05 KB
/
RuntimePreset.cs
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
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Gilzoide.RuntimePreset
{
public class RuntimePreset : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField] internal string _targetType = "";
[SerializeField] internal string _valuesJson = "{}";
[SerializeField] internal List<Object> _objectReferences = new();
private JsonSerializerSettings _jsonSettings;
/// <summary>
/// Target type for preset.
/// Presets can only be applied to objects of this type.
/// </summary>
public Type TargetType
{
get => Type.GetType(_targetType);
set => _targetType = value?.AssemblyQualifiedName ?? "";
}
/// <returns>Whether this preset can be applied to <paramref name="obj"/></returns>
public bool CanBeAppliedTo(Object obj)
{
return obj != null
&& TargetType is Type targetType
&& targetType.IsAssignableFrom(obj.GetType());
}
/// <summary>
/// Alias for <see cref="TryApplyTo"/> that ignores the returned value.
/// </summary>
/// <seealso cref="TryApplyTo"/>
public void ApplyTo(Object targetObject)
{
TryApplyTo(targetObject);
}
/// <summary>
/// Try applying preset values to the target object.
/// </summary>
/// <remarks>
/// If the target object is <see langword="null"/> or does not inherit from <see cref="TargetType"/>, the call is a no-op.
/// If the target object is a <see cref="GameObject"/> and this preset's target type is a component, <see cref="GetComponent"/> is used to find the correct target component.
/// If the target object implements <see cref="IRuntimePresetListener"/> it will be notified after the values were applied.
/// </remarks>
/// <returns>
/// Whether the preset's values were successfully applied to the target object.
/// </returns>
/// <seealso cref="ApplyTo"/>
public bool TryApplyTo(Object targetObject)
{
if (targetObject is GameObject gameObject
&& TargetType is Type targetType
&& targetType.IsSubclassOf(typeof(Component)))
{
targetObject = gameObject.GetComponent(targetType);
}
if (CanBeAppliedTo(targetObject))
{
JsonConvert.PopulateObject(_valuesJson, targetObject, _jsonSettings);
if (targetObject is IRuntimePresetListener presetListener)
{
presetListener.OnPresetApplied();
}
return true;
}
else
{
return false;
}
}
#region ISerializationCallbackReceiver
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
_jsonSettings = new JsonSerializerSettings
{
Converters = new JsonConverter[] { new JsonObjectConverter(_objectReferences), new JsonLayerMaskConverter() },
ContractResolver = JsonSerializeFieldContractResolver.Instance,
NullValueHandling = NullValueHandling.Include,
};
}
#endregion
#if UNITY_EDITOR
internal string AssetDependencyKey => $"{typeof(RuntimePreset).FullName}.{AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(this))}";
internal void MarkAssetUpdated()
{
AssetDatabase.RegisterCustomDependency(AssetDependencyKey, Hash128.Compute(EditorJsonUtility.ToJson(this)));
}
protected void OnValidate()
{
try
{
var _ = JsonConvert.DeserializeObject<Dictionary<string, object>>(_valuesJson);
}
catch (Exception)
{
_valuesJson = "{}";
}
}
#endif
}
}