Files
AR-Menu/Library/PackageCache/org.khronos.unitygltf@6b55d14e19c1/Runtime/Plugins/GLTFSerialization/GLTFJsonExtensions.cs
2025-11-30 08:35:03 +02:00

440 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using GLTF.Math;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using GLTF.Schema;
namespace GLTF.Extensions
{
public static class JsonWriterExtensions
{
public static void WriteTexture(this JObject token, string name, TextureInfo texture)
{
var jsonWriter = token.CreateWriter();
jsonWriter.WritePropertyName(name);
texture.Serialize(jsonWriter);
}
}
public static class JsonReaderExtensions
{
public static List<string> ReadStringList(this JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid array at: {0}", reader.Path));
}
var list = new List<string>();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
var value = reader.Value;
if (value != null)
list.Add(value.ToString());
}
return list;
}
public static List<double> ReadDoubleList(this JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid array at: {0}", reader.Path));
}
var list = new List<double>();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
var value = reader.Value;
if (value != null)
list.Add(double.Parse(value.ToString()));
}
return list;
}
public static List<int> ReadInt32List(this JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid array at: {0}", reader.Path));
}
var list = new List<int>();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
var value = reader.Value;
if (value != null)
list.Add(int.Parse(value.ToString()));
}
return list;
}
public static List<T> ReadList<T>(this JsonReader reader, Func<T> deserializerFunc)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid array at: {0}", reader.Path));
}
var list = new List<T>();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
list.Add(deserializerFunc());
// deserializerFunc can advance to EndArray. We need to check for this case as well.
if (reader.TokenType == JsonToken.EndArray)
{
break;
}
}
return list;
}
public static TextureInfo DeserializeAsTexture(this JToken token, GLTFRoot root)
{
TextureInfo textureInfo = null;
if (token != null)
{
JObject textureObject = token as JObject;
if (textureObject == null)
{
throw new Exception("JToken used for Texture deserialization was not a JObject. It was a " + token.Type.ToString());
}
#if DEBUG
// Broken on il2cpp. Don't ship debug DLLs there.
System.Diagnostics.Debug.WriteLine("textureObject is " + textureObject.Type + " with a value of: " + textureObject[TextureInfo.INDEX].Type + " " + textureObject.ToString());
#endif
int indexVal = textureObject[TextureInfo.INDEX].DeserializeAsInt();
textureInfo = new TextureInfo()
{
Index = new TextureId()
{
Id = indexVal,
Root = root
}
};
if (textureObject.ContainsKey(TextureInfo.TEXCOORD))
{
textureInfo.TexCoord = textureObject[TextureInfo.TEXCOORD].DeserializeAsInt();
}
if (textureObject.ContainsKey("extensions"))
{
textureInfo.Extensions = GLTFProperty.DeserializeExtensions(root, textureObject["extensions"].CreateReader());
}
}
return textureInfo;
}
public static NormalTextureInfo DeserializeAsNormalTexture(this JToken token, GLTFRoot root)
{
var tex = DeserializeAsTexture(token, root);
if (tex != null)
{
var normalTex = new NormalTextureInfo() { Index = tex.Index, TexCoord = tex.TexCoord };
JObject textureObject = token as JObject;
if (textureObject != null && textureObject.ContainsKey(NormalTextureInfo.SCALE))
{
normalTex.Scale = textureObject[NormalTextureInfo.SCALE].DeserializeAsDouble();
}
return normalTex;
}
return null;
}
public static int DeserializeAsInt(this JToken token)
{
if (token != null)
{
JValue intValue = token as JValue;
if (intValue == null)
{
throw new Exception("JToken used for int deserialization was not a JValue. It was a " + token.Type.ToString());
}
return (int)intValue;
}
return 0;
}
public static double DeserializeAsDouble(this JToken token)
{
if (token != null)
{
JValue doubleValue = token as JValue;
if (doubleValue == null)
{
throw new Exception("JToken used for double deserialization was not a JValue. It was a " + token.Type.ToString());
}
return (double)doubleValue;
}
return 0d;
}
public static Color ReadAsRGBAColor(this JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid color value at: {0}", reader.Path));
}
var color = new Color
{
R = (float) reader.ReadAsDouble().Value,
G = (float) reader.ReadAsDouble().Value,
B = (float) reader.ReadAsDouble().Value,
A = (float) reader.ReadAsDouble().Value
};
if (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
throw new Exception(string.Format("Invalid color value at: {0}", reader.Path));
}
return color;
}
public static Color DeserializeAsColor(this JToken token)
{
Color color = Color.White;
if (token != null)
{
JArray colorArray = token as JArray;
if (colorArray == null)
{
throw new Exception("JToken used for Color deserialization was not a JArray. It was a " + token.Type.ToString());
}
if (colorArray.Count < 3)
{
throw new Exception("JArray used for Color deserialization did have less than 3 entries (needs to be RGB or RGBA). It had " + colorArray.Count);
}
color = new Color
{
R = (float)colorArray[0].DeserializeAsDouble(),
G = (float)colorArray[1].DeserializeAsDouble(),
B = (float)colorArray[2].DeserializeAsDouble(),
A = (float)(colorArray.Count == 4 ? colorArray[3].DeserializeAsDouble() : 1.0),
};
}
return color;
}
public static Color ReadAsRGBColor(this JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid vector value at: {0}", reader.Path));
}
var color = new Color
{
R = (float) reader.ReadAsDouble().Value,
G = (float) reader.ReadAsDouble().Value,
B = (float) reader.ReadAsDouble().Value,
A = 1.0f
};
if (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
throw new Exception(string.Format("Invalid color value at: {0}", reader.Path));
}
return color;
}
public static Vector3 ReadAsVector3(this JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid vector value at: {0}", reader.Path));
}
var vector = new Vector3
{
X = (float) reader.ReadAsDouble().Value,
Y = (float) reader.ReadAsDouble().Value,
Z = (float) reader.ReadAsDouble().Value
};
if (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
throw new Exception(string.Format("Invalid vector value at: {0}", reader.Path));
}
return vector;
}
public static Vector2 DeserializeAsVector2(this JToken token)
{
Vector2 vector = new Vector2();
if (token != null)
{
JArray vectorArray = token as JArray;
if (vectorArray == null)
{
throw new Exception("JToken used for Vector2 deserialization was not a JArray. It was a " + token.Type.ToString());
}
if (vectorArray.Count != 2)
{
throw new Exception("JArray used for Vector2 deserialization did not have 2 entries for XY. It had " + vectorArray.Count);
}
vector = new Vector2
{
X = (float)vectorArray[0].DeserializeAsDouble(),
Y = (float)vectorArray[1].DeserializeAsDouble()
};
}
return vector;
}
public static Vector3 DeserializeAsVector3(this JToken token)
{
Vector3 vector = new Vector3();
if (token != null)
{
JArray vectorArray = token as JArray;
if (vectorArray == null)
{
throw new Exception("JToken used for Vector3 deserialization was not a JArray. It was a " + token.Type.ToString());
}
if (vectorArray.Count != 3)
{
throw new Exception("JArray used for Vector3 deserialization did not have 3 entries for XYZ. It had " + vectorArray.Count);
}
vector = new Vector3
{
X = (float)vectorArray[0].DeserializeAsDouble(),
Y = (float)vectorArray[1].DeserializeAsDouble(),
Z = (float)vectorArray[2].DeserializeAsDouble()
};
}
return vector;
}
public static Quaternion ReadAsQuaternion(this JsonReader reader)
{
if (reader.Read() && reader.TokenType != JsonToken.StartArray)
{
throw new Exception(string.Format("Invalid vector value at: {0}", reader.Path));
}
var quat = new Quaternion
{
X = (float) reader.ReadAsDouble().Value,
Y = (float) reader.ReadAsDouble().Value,
Z = (float) reader.ReadAsDouble().Value,
W = (float) reader.ReadAsDouble().Value
};
if (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
throw new Exception(string.Format("Invalid vector value at: {0}", reader.Path));
}
return quat;
}
public static Dictionary<string, T> ReadAsDictionary<T>(this JsonReader reader, Func<T> deserializerFunc, bool skipStartObjectRead = false)
{
if (!skipStartObjectRead && reader.Read() && reader.TokenType != JsonToken.StartObject)
{
throw new Exception(string.Format("Dictionary must be an object at: {0}.", reader.Path));
}
var dict = new Dictionary<string, T>();
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
var value = reader.Value;
if (value != null)
dict.Add(value.ToString(), deserializerFunc());
}
return dict;
}
public static Dictionary<string, object> ReadAsObjectDictionary(this JsonReader reader, bool skipStartObjectRead = false)
{
if (!skipStartObjectRead && reader.Read() && reader.TokenType != JsonToken.StartObject)
{
throw new Exception(string.Format("Dictionary must be an object at: {0}", reader.Path));
}
var dict = new Dictionary<string, object>();
while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
var value = reader.Value;
if (value != null)
dict.Add(value.ToString(), ReadDictionaryValue(reader));
}
return dict;
}
private static object ReadDictionaryValue(JsonReader reader)
{
if (!reader.Read())
{
return null;
}
switch (reader.TokenType)
{
case JsonToken.StartArray:
return reader.ReadObjectList();
case JsonToken.StartObject:
return reader.ReadAsObjectDictionary(true);
default:
return reader.Value;
}
}
private static List<object> ReadObjectList(this JsonReader reader)
{
var list = new List<object>();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
list.Add(reader.Value);
}
return list;
}
public static T ReadStringEnum<T>(this JsonReader reader)
{
return (T) Enum.Parse(typeof(T), reader.ReadAsString());
}
}
}