-
Notifications
You must be signed in to change notification settings - Fork 474
/
GLTFProperty.cs
256 lines (228 loc) · 7.09 KB
/
GLTFProperty.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
using System;
using System.Collections.Generic;
using System.Linq;
using GLTF.Schema.KHR_lights_punctual;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace GLTF.Schema
{
public class GLTFProperty
{
public static IReadOnlyList<string> RegisteredExtensions
{
get
{
lock (_extensionRegistry)
{
return _extensionRegistry.Keys.ToList();
}
}
}
private static Dictionary<string, ExtensionFactory> _extensionRegistry = new Dictionary<string, ExtensionFactory>()
{
{ ExtTextureTransformExtensionFactory.EXTENSION_NAME, new ExtTextureTransformExtensionFactory() },
{ KHR_materials_pbrSpecularGlossinessExtensionFactory.EXTENSION_NAME, new KHR_materials_pbrSpecularGlossinessExtensionFactory() },
{ KHR_MaterialsUnlitExtensionFactory.EXTENSION_NAME, new KHR_MaterialsUnlitExtensionFactory() },
{ KHR_lights_punctualExtensionFactory.EXTENSION_NAME, new KHR_lights_punctualExtensionFactory() },
{ KHR_materials_emissive_strength_Factory.EXTENSION_NAME, new KHR_materials_emissive_strength_Factory() },
{ KHR_materials_transmission_Factory.EXTENSION_NAME, new KHR_materials_transmission_Factory() },
{ KHR_materials_volume_Factory.EXTENSION_NAME, new KHR_materials_volume_Factory() },
{ KHR_materials_ior_Factory.EXTENSION_NAME, new KHR_materials_ior_Factory() },
{ KHR_materials_iridescence_Factory.EXTENSION_NAME, new KHR_materials_iridescence_Factory() },
{ KHR_materials_specular_Factory.EXTENSION_NAME, new KHR_materials_specular_Factory() },
{ KHR_materials_clearcoat_Factory.EXTENSION_NAME, new KHR_materials_clearcoat_Factory() },
{ MSFT_LODExtensionFactory.EXTENSION_NAME, new MSFT_LODExtensionFactory() },
{ KHR_draco_mesh_compression_Factory.EXTENSION_NAME, new KHR_draco_mesh_compression_Factory() },
{ KHR_texture_basisu_Factory.EXTENSION_NAME, new KHR_texture_basisu_Factory() },
{ EXT_meshopt_compression_Factory.EXTENSION_NAME, new EXT_meshopt_compression_Factory() }
};
private static DefaultExtensionFactory _defaultExtensionFactory = new DefaultExtensionFactory();
public static bool IsExtensionRegistered(string extensionName)
{
lock (_extensionRegistry)
{
return _extensionRegistry.ContainsKey(extensionName);
}
}
public static void RegisterExtension(ExtensionFactory extensionFactory)
{
lock (_extensionRegistry)
{
_extensionRegistry[extensionFactory.ExtensionName] = extensionFactory;
}
}
public static ExtensionFactory TryGetExtension(string extensionName)
{
lock (_extensionRegistry)
{
ExtensionFactory result;
if (_extensionRegistry.TryGetValue(extensionName, out result))
{
return result;
}
return null;
}
}
public static IExtension CreateEmptyExtension(string extensionName)
{
return TryGetExtension(extensionName)?.Deserialize(null, new JProperty(extensionName, new JObject()));
}
public static bool TryRegisterExtension(ExtensionFactory extensionFactory)
{
lock (_extensionRegistry)
{
if (_extensionRegistry.ContainsKey(extensionFactory.ExtensionName))
{
return false;
}
_extensionRegistry.Add(extensionFactory.ExtensionName, extensionFactory);
return true;
}
}
public Dictionary<string, IExtension> Extensions;
public JToken Extras;
public GLTFProperty()
{
}
public GLTFProperty(GLTFProperty property, GLTFRoot gltfRoot = null)
{
if (property == null) return;
if (property.Extensions != null)
{
Extensions = new Dictionary<string, IExtension>(property.Extensions.Count);
foreach (KeyValuePair<string, IExtension> extensionKeyValuePair in property.Extensions)
{
Extensions.Add(extensionKeyValuePair.Key, extensionKeyValuePair.Value.Clone(gltfRoot));
}
}
if (property.Extras != null)
{
Extras = property.Extras.DeepClone();
}
}
public void DefaultPropertyDeserializer(GLTFRoot root, JsonReader reader)
{
switch (reader.Value.ToString())
{
case "extensions":
Extensions = DeserializeExtensions(root, reader);
break;
case "extras":
// advance to property value
reader.Read();
if (reader.TokenType != JsonToken.StartObject)
throw new Exception(string.Format("extras must be an object at: {0}", reader.Path));
Extras = JToken.ReadFrom(reader);
break;
default:
SkipValue(reader);
break;
}
}
public void AddExtension(string extname, IExtension extension)
{
if (Extensions == null)
{
Extensions = new Dictionary<string, IExtension>();
}
if (Extensions.ContainsKey(extname))
{
throw new Exception($"Extension {extname} already exist on GLTFProperty");
}
Extensions.Add(extname, extension);
}
private void SkipValue(JsonReader reader)
{
if (!reader.Read())
{
throw new Exception("No value found.");
}
if (reader.TokenType == JsonToken.StartObject)
{
SkipObject(reader);
}
else if (reader.TokenType == JsonToken.StartArray)
{
SkipArray(reader);
}
}
private void SkipObject(JsonReader reader)
{
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
if (reader.TokenType == JsonToken.StartArray)
{
SkipArray(reader);
}
else if (reader.TokenType == JsonToken.StartObject)
{
SkipObject(reader);
}
}
}
private void SkipArray(JsonReader reader)
{
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
if (reader.TokenType == JsonToken.StartArray)
{
SkipArray(reader);
}
else if (reader.TokenType == JsonToken.StartObject)
{
SkipObject(reader);
}
}
}
internal static Dictionary<string, IExtension> DeserializeExtensions(GLTFRoot root, JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartObject)
{
throw new GLTFParseException("GLTF extensions must be an object");
}
JObject extensions = (JObject)JToken.ReadFrom(reader);
var extensionsCollection = new Dictionary<string, IExtension>();
foreach(JToken child in extensions.Children())
{
if (child.Type != JTokenType.Property)
{
throw new GLTFParseException("Children token of extensions should be properties");
}
JProperty childAsJProperty = (JProperty) child;
string extensionName = childAsJProperty.Name;
ExtensionFactory extensionFactory;
lock (_extensionRegistry)
{
if (_extensionRegistry.TryGetValue(extensionName, out extensionFactory))
{
extensionsCollection.Add(extensionName, extensionFactory.Deserialize(root, childAsJProperty));
}
else
{
extensionsCollection.Add(extensionName, _defaultExtensionFactory.Deserialize(root, childAsJProperty));
}
}
}
return extensionsCollection;
}
public virtual void Serialize(JsonWriter writer)
{
if (Extensions != null && Extensions.Count > 0)
{
writer.WritePropertyName("extensions");
writer.WriteStartObject();
foreach (var extension in Extensions)
{
JToken extensionToken = extension.Value.Serialize();
extensionToken.WriteTo(writer);
}
writer.WriteEndObject();
}
if(Extras != null)
{
writer.WritePropertyName("extras");
Extras.WriteTo(writer);
}
}
}
}