Merge pull request #298 from vrm-c/generate_json_serializer

Generate json serializer
This commit is contained in:
hiroj 2019-12-12 21:03:20 +09:00 committed by GitHub
commit bb36ee1c7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 6133 additions and 16 deletions

View File

@ -84,10 +84,12 @@ namespace VRM.Samples
var vrm = VRMExporter.Export(context.Root);
// TODO: Check contents in JSON
/*var exportJson = */JsonParser.Parse(vrm.ToJson());
/*var exportJson = */
JsonParser.Parse(vrm.ToJson());
// TODO: Check contents in JSON
/*var newExportedJson = */JsonParser.Parse(JsonSchema.FromType<glTF>().Serialize(vrm));
/*var newExportedJson = */
JsonParser.Parse(JsonSchema.FromType<glTF>().Serialize(vrm));
/*
foreach (var kv in importJson.Diff(exportJson))
@ -117,5 +119,35 @@ namespace VRM.Samples
MeshTests.MeshEquals(src, dst);
}
}
[Test]
public void SerializerCompare()
{
// Aliciaを古いデシリアライザでロードする
var path = AliciaPath;
var context = new VRMImporterContext();
context.ParseGlb(File.ReadAllBytes(path));
var oldJson = context.GLTF.ToJson().ParseAsJson().ToString(" ");
// 生成シリアライザでJSON化する
var f = new JsonFormatter();
f.GenSerialize(context.GLTF);
var parsed = f.ToString().ParseAsJson();
var newJson = parsed.ToString(" ");
File.WriteAllText("old.json", oldJson);
File.WriteAllText("new.json", newJson);
// 比較
Assert.AreEqual(oldJson, newJson);
// 生成デシリアライザでロードする
var ff = new JsonFormatter();
var des = GltfDeserializer.Deserialize(parsed);
ff.Clear();
ff.GenSerialize(des);
var desJson = ff.ToString().ParseAsJson().ToString(" ");
Assert.AreEqual(oldJson, desJson);
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 43be0cf78be61614cb840cb906de4275
folderAsset: yes
timeCreated: 1565252168
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,115 @@
using System;
using System.IO;
namespace UniGLTF
{
public class ArraySerialization : FunctionSerializationBase
{
IValueSerialization m_inner;
public ArraySerialization(Type t, IValueSerialization inner)
{
ValueType = t;
m_inner = inner;
}
public override void GenerateDeserializer(StreamWriter writer, string callName)
{
var itemCallName = callName + "_ARRAY";
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new $1[parsed.GetArrayCount()];
int i=0;
foreach(var x in parsed.ArrayItems())
{
value[i++] = $3;
}
return value;
}
"
.Replace("$0", UniJSON.JsonSchemaAttribute.GetTypeName(ValueType))
.Replace("$1", m_inner.ValueType.Name)
.Replace("$2", callName)
.Replace("$3", m_inner.GenerateDeserializerCall(itemCallName, "x"))
);
if (!m_inner.IsInline)
{
m_inner.GenerateDeserializer(writer, itemCallName);
}
}
}
public class ListSerialization : FunctionSerializationBase
{
IValueSerialization m_inner;
public ListSerialization(Type t, IValueSerialization inner)
{
ValueType = t;
m_inner = inner;
}
public override void GenerateDeserializer(StreamWriter writer, string callName)
{
var itemCallName = callName + "_LIST";
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new List<$1>();
foreach(var x in parsed.ArrayItems())
{
value.Add($3);
}
return value;
}"
.Replace("$0", UniJSON.JsonSchemaAttribute.GetTypeName(ValueType))
.Replace("$1", m_inner.ValueType.Name)
.Replace("$2", callName)
.Replace("$3", m_inner.GenerateDeserializerCall(itemCallName, "x"))
);
if (!m_inner.IsInline)
{
m_inner.GenerateDeserializer(writer, itemCallName);
}
}
}
public class StringKeyDictionarySerialization : FunctionSerializationBase
{
IValueSerialization m_inner;
public StringKeyDictionarySerialization(Type t, IValueSerialization inner)
{
ValueType = t;
m_inner = inner;
}
public override void GenerateDeserializer(StreamWriter writer, string callName)
{
var itemCallName = callName + "_DICT";
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new Dictionary<string, $1>();
foreach(var kv in parsed.ObjectItems())
{
value.Add(kv.Key.GetString(), $3);
}
return value;
}
"
.Replace("$0", UniJSON.JsonSchemaAttribute.GetTypeName(ValueType))
.Replace("$1", m_inner.ValueType.Name)
.Replace("$2", callName)
.Replace("$3", m_inner.GenerateDeserializerCall(itemCallName, "kv.Value"))
);
if (!m_inner.IsInline)
{
m_inner.GenerateDeserializer(writer, itemCallName);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e85f0c5204f5ac3429503462ef29cdae
timeCreated: 1565259169
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
using System.IO;
using System.Reflection;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
public static class DeserializerGenerator
{
public const BindingFlags FIELD_FLAGS = BindingFlags.Instance | BindingFlags.Public;
static string OutPath
{
get
{
return Path.Combine(UnityEngine.Application.dataPath,
"VRM/UniGLTF/Scripts/IO/GltfDeserializer.g.cs");
}
}
/// <summary>
/// AOT向けにデシリアライザを生成する
/// </summary>
[MenuItem(VRM.VRMVersion.MENU + "/Generate Deserializer")]
static void GenerateSerializer()
{
var info = new ObjectSerialization(typeof(glTF), "gltf");
Debug.Log(info);
using (var s = File.Open(OutPath, FileMode.Create))
using (var w = new StreamWriter(s, Encoding.UTF8))
{
// header
w.Write(@"
using UniJSON;
using System;
using System.Collections.Generic;
using VRM;
using UnityEngine;
namespace UniGLTF {
public static class GltfDeserializer
{
");
info.GenerateDeserializer(w, "Deserialize");
// footer
w.Write(@"
} // GltfDeserializer
} // UniGLTF
");
Debug.LogFormat("write: {0}", OutPath);
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c2f242dff8534b1409257c4e7fe8a21d
timeCreated: 1564983410
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,152 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using UniJSON;
namespace UniGLTF
{
public class FieldSerializationInfo
{
FieldInfo m_fi;
public FieldInfo FieldInfo
{
get { return m_fi; }
}
public string Name
{
get { return FieldInfo.Name; }
}
public string Path
{
get;
private set;
}
public string FunctionName
{
get
{
return "Deserialize_" + Path
.Replace("/", "_")
.Replace("[]", "_")
;
}
}
JsonSchemaAttribute m_attr;
public IValueSerialization Serialization
{
get;
private set;
}
public FieldSerializationInfo(FieldInfo fi, string path)
{
m_fi = fi;
Path = path + "/" + fi.Name;
m_attr = fi.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(JsonSchemaAttribute)) as JsonSchemaAttribute;
Serialization = GetSerialization(m_fi.FieldType, Path);
}
static IValueSerialization GetSerialization(Type t, string path)
{
if (t.IsArray)
{
return new ArraySerialization(t,
GetSerialization(t.GetElementType(), path + "[]"));
}
else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>))
{
return new ListSerialization(t,
GetSerialization(t.GetGenericArguments()[0], path + "[]"));
}
else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>)
&& t.GetGenericArguments()[0] == typeof(string))
{
return new StringKeyDictionarySerialization(t,
GetSerialization(t.GetGenericArguments()[1], path));
}
// GetCollectionType(fi.FieldType, out suffix, out t);
if (t == typeof(sbyte))
{
return new Int8Serialization();
}
else if (t == typeof(short))
{
return new Int16Serialization();
}
else if (t == typeof(int))
{
return new Int32Serialization();
}
else if (t == typeof(long))
{
return new Int64Serialization();
}
else if (t == typeof(byte))
{
return new UInt8Serialization();
}
else if (t == typeof(ushort))
{
return new UInt16Serialization();
}
else if (t == typeof(uint))
{
return new UInt32Serialization();
}
else if (t == typeof(ulong))
{
return new UInt64Serialization();
}
else if (t == typeof(float))
{
return new SingleSerialization();
}
else if (t == typeof(double))
{
return new DoubleSerialization();
}
else if (t == typeof(string))
{
return new StringSerialization();
}
else if (t == typeof(bool))
{
return new BooleanSerialization();
}
else if (t.IsEnum)
{
return new EnumIntSerialization(t);
}
return new ObjectSerialization(t, path);
}
public override string ToString()
{
var sb = new StringBuilder();
var typeName = BaseJsonSchemaAttribute.GetTypeName(m_fi.FieldType);
if (m_attr != null)
{
sb.AppendLine(string.Format("{0}: {1}", Path, m_attr.GetInfo(m_fi)));
}
else
{
sb.AppendLine(string.Format("{0}: {1}", Path, typeName));
}
sb.Append(Serialization.ToString());
return sb.ToString();
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3c26deb26a3941642a30691d374199da
timeCreated: 1565256318
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
using System;
using System.IO;
namespace UniGLTF
{
// Use this for initialization
public interface IValueSerialization
{
Type ValueType { get; }
bool IsInline { get; }
string GenerateDeserializerCall(string callName, string argName);
void GenerateDeserializer(StreamWriter writer, string callName);
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 199c91bbade4ea043928e29946a28502
timeCreated: 1565256001
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,112 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
namespace UniGLTF
{
public abstract class FunctionSerializationBase : IValueSerialization
{
public Type ValueType
{
get;
protected set;
}
public bool IsInline
{
get { return false; }
}
public abstract void GenerateDeserializer(StreamWriter writer, string callName);
public string GenerateDeserializerCall(string callName, string argName)
{
return string.Format("{0}({1})", callName, argName);
}
}
public class ObjectSerialization : FunctionSerializationBase
{
string m_path;
FieldSerializationInfo[] m_fsi;
public ObjectSerialization(Type t, string path)
{
ValueType = t;
m_path = path;
m_fsi = t.GetFields(DeserializerGenerator.FIELD_FLAGS)
.Where(x =>
{
if (x.FieldType == typeof(object))
{
// object. coannot serialize
return false;
}
if (x.IsLiteral && !x.IsInitOnly)
{
// const
return false;
}
return true;
})
.Select(x =>
{
return new FieldSerializationInfo(x, path);
}).ToArray();
}
public override string ToString()
{
var sb = new StringBuilder();
foreach (var x in m_fsi)
{
sb.Append(x.ToString());
}
return sb.ToString();
}
public override void GenerateDeserializer(StreamWriter writer, string parentName)
{
writer.Write(@"
public static $0 $2(ListTreeNode<JsonValue> parsed)
{
var value = new $0();
foreach(var kv in parsed.ObjectItems())
{
var key = kv.Key.GetString();
"
.Replace("$0", ValueType.Name)
.Replace("$2", parentName)
);
foreach (var f in m_fsi)
{
writer.Write(@"
if(key==""$0""){
value.$0 = $1;
continue;
}
"
.Replace("$0", f.Name)
.Replace("$1", f.Serialization.GenerateDeserializerCall(f.FunctionName, "kv.Value"))
);
}
writer.Write(@"
}
return value;
}
");
foreach (var f in m_fsi)
{
if (!f.Serialization.IsInline)
{
f.Serialization.GenerateDeserializer(writer, f.FunctionName);
}
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 87a20b1fb7336e34bbc61c9d7476c6db
timeCreated: 1565256016
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,198 @@
using System;
using System.IO;
namespace UniGLTF
{
public abstract class PrimitiveSerializationBase : IValueSerialization
{
public bool IsInline
{
get { return true; }
}
public abstract Type ValueType { get; }
public void GenerateDeserializer(StreamWriter writer, string callName)
{
throw new System.NotImplementedException();
}
public abstract string GenerateDeserializerCall(string callName, string argName);
}
public class Int8Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(SByte); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt8()";
}
}
public class Int16Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Int16); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt16()";
}
}
public class Int32Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Int32); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt32()";
}
}
public class Int64Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Int64); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetInt64()";
}
}
public class UInt8Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Byte); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt8()";
}
}
public class UInt16Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(UInt16); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt16()";
}
}
public class UInt32Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(UInt32); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt32()";
}
}
public class UInt64Serialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(UInt64); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetUInt64()";
}
}
public class SingleSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Single); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetSingle()";
}
}
public class DoubleSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Double); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetDouble()";
}
}
public class BooleanSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(Boolean); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetBoolean()";
}
}
public class StringSerialization : PrimitiveSerializationBase
{
public override Type ValueType
{
get { return typeof(String); }
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return argName + ".GetString()";
}
}
public class EnumIntSerialization : PrimitiveSerializationBase
{
Type m_type;
public override Type ValueType
{
get { return m_type; }
}
public EnumIntSerialization(Type t)
{
m_type = t;
}
public override string GenerateDeserializerCall(string callName, string argName)
{
return string.Format("({0}){1}.GetInt32()", m_type.Name, argName);
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8ddae9fc19efaec43a6d3aacad1c8d56
timeCreated: 1565256889
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,293 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UniJSON;
using UnityEditor;
using UnityEngine;
namespace UniGLTF
{
public static class SerializerGenerator
{
const BindingFlags FIELD_FLAGS = BindingFlags.Instance | BindingFlags.Public;
static string OutPath
{
get
{
return Path.Combine(UnityEngine.Application.dataPath,
"VRM/UniGLTF/Scripts/IO/FormatterExtensionsGltf.g.cs");
}
}
/// <summary>
/// AOT向けにシリアライザを生成する
/// </summary>
[MenuItem(VRM.VRMVersion.MENU + "/Generate Serializer")]
static void GenerateSerializer()
{
var path = OutPath;
using (var g = new Generator(path))
{
var rootType = typeof(glTF);
g.Generate(rootType, "gltf");
}
}
class Generator : IDisposable
{
String m_path;
Stream m_s;
StreamWriter m_w;
static Dictionary<string, string> s_snipets = new Dictionary<string, string>
{
{"gltf/animations", "if(value.animations!=null && value.animations.Count>0)" },
{"gltf/cameras", "if(value.cameras!=null && value.cameras.Count>0)" },
{"gltf/bufferViews[]/byteStride", "if(false)" },
{"gltf/bufferViews[]/target", "if(value.target!=0)" },
{"gltf/animations[]/channels[]/target", "if(value!=null)" },
{"gltf/accessors[]/sparse", "if(value.sparse!=null && value.sparse.count>0)"},
{"gltf/meshes[]/primitives[]/targets", "if(value.targets.Count>0)" },
{"gltf/meshes[]/primitives[]/targets[]/POSITION", "if(value.POSITION!=-1)" },
{"gltf/meshes[]/primitives[]/targets[]/NORMAL", "if(value.NORMAL!=-1)" },
{"gltf/meshes[]/primitives[]/targets[]/TANGENT", "if(value.TANGENT!=-1)" },
{"gltf/meshes[]/primitives[]/attributes/POSITION", "if(value.POSITION!=-1)"},
{"gltf/meshes[]/primitives[]/attributes/NORMAL", "if(value.NORMAL!=-1)"},
{"gltf/meshes[]/primitives[]/attributes/TANGENT", "if(value.TANGENT!=-1)"},
{"gltf/meshes[]/primitives[]/attributes/TEXCOORD_0", "if(value.TEXCOORD_0!=-1)"},
{"gltf/meshes[]/primitives[]/attributes/COLOR_0", "if(value.COLOR_0!=-1)"},
{"gltf/meshes[]/primitives[]/attributes/JOINTS_0", "if(value.JOINTS_0!=-1)"},
{"gltf/meshes[]/primitives[]/attributes/WEIGHTS_0", "if(value.WEIGHTS_0!=-1)"},
{"gltf/meshes[]/primitives[]/extras", "if(value.extras!=null && value.extras.targetNames!=null && value.extras.targetNames.Count>0)"},
{"gltf/materials[]/alphaCutoff", "if(!string.IsNullOrEmpty(value.alphaMode))" },
{"gltf/nodes[]/camera", "if(value.camera!=-1)"},
{"gltf/nodes[]/mesh", "if(value.mesh!=-1)"},
{"gltf/nodes[]/skin", "if(value.skin!=-1)"},
{"gltf/skins[]/skeleton", "if(value.skeleton!=-1)"},
{"gltf/extensionsRequired", "if(false)"},
{"gltf/extensions/VRM/humanoid/humanBones[]/axisLength", "if(value.axisLength>0)"},
{"gltf/extensions/VRM/humanoid/humanBones[]/center", "if(value.center!=Vector3.zero)"},
{"gltf/extensions/VRM/humanoid/humanBones[]/max", "if(value.max!=Vector3.zero)"},
{"gltf/extensions/VRM/humanoid/humanBones[]/min", "if(value.min!=Vector3.zero)"},
};
public Generator(string path)
{
m_path = path;
m_s = File.Open(path, FileMode.Create);
m_w = new StreamWriter(m_s, Encoding.UTF8);
// begin
m_w.Write(@"
using System;
using System.Collections.Generic;
using UniJSON;
using UnityEngine;
using VRM;
namespace UniGLTF {
static public class IFormatterExtensionsGltf
{
");
}
public void Dispose()
{
// end
m_w.Write(@"
} // class
} // namespace
");
m_w.Dispose();
m_s.Dispose();
UnityPath.FromFullpath(m_path).ImportAsset();
}
HashSet<Type> m_used = new HashSet<Type>
{
typeof(object),
};
public void Generate(Type t, string path, int level = 0)
{
if (m_used.Contains(t))
{
// 処理済み
return;
}
m_used.Add(t);
// primitive
try
{
var mi = typeof(IFormatter).GetMethod("Value", new Type[] { t });
if (mi != null)
{
m_w.Write(@"
public static void GenSerialize(this IFormatter f, $0 value)
{
f.Value(value);
}
".Replace("$0", t.Name));
return;
}
}
catch (AmbiguousMatchException)
{
// skip
}
if (t.IsEnum)
{
m_w.Write(@"
public static void GenSerialize(this IFormatter f, $0 value)
{
f.Value((int)value);
}
".Replace("$0", t.Name));
}
else if (t.IsArray)
{
var et = t.GetElementType();
m_w.Write(@"
/// $1
public static void GenSerialize(this IFormatter f, $0[] value)
{
f.BeginList(value.Length);
foreach (var x in value)
{
f.GenSerialize(x);
}
f.EndList();
}
"
.Replace("$0", et.Name)
.Replace("$1", path)
);
Generate(et, path + "[]", level + 1);
}
else if (t.IsGenericType)
{
if (t.GetGenericTypeDefinition() == typeof(List<>))
{
var et = t.GetGenericArguments()[0];
m_w.Write(@"
/// $1
public static void GenSerialize(this IFormatter f, List<$0> value)
{
f.BeginList(value.Count);
foreach (var x in value)
{
f.GenSerialize(x);
}
f.EndList();
}
"
.Replace("$0", et.Name)
.Replace("$1", path));
Generate(et, path + "[]", level + 1);
}
else if (t.GetGenericTypeDefinition() == typeof(Dictionary<,>)
&& t.GetGenericArguments()[0] == typeof(string))
{
var et = t.GetGenericArguments()[1];
m_w.Write(@"
/// $1
public static void GenSerialize(this IFormatter f, Dictionary<string, $0> value)
{
f.BeginMap(value.Count);
foreach (var kv in value)
{
f.Key(kv.Key);
f.GenSerialize(kv.Value);
}
f.EndMap();
}
"
.Replace("$0", et.Name)
.Replace("$1", path));
Generate(et, path + "{}", level + 1);
}
else
{
Debug.LogWarningFormat("unknown type: {0}", t);
}
}
else
{
Debug.LogFormat("{0}({1})", path, t.Name);
m_w.Write(@"
/// $1
public static void GenSerialize(this IFormatter f, $0 value)
{
f.BeginMap(0); // dummy
"
.Replace("$0", t.Name)
.Replace("$1", path)
);
foreach (var fi in t.GetFields(FIELD_FLAGS))
{
if (fi.FieldType == typeof(object))
{
continue;
}
if (fi.IsLiteral && !fi.IsInitOnly)
{
continue;
}
if (fi.FieldType == typeof(string) || fi.FieldType.IsEnum || fi.FieldType.IsArray || fi.FieldType.IsGenericType)
{
}
else if (fi.FieldType.IsClass && fi.FieldType.GetFields(FIELD_FLAGS).Length == 0)
{
continue;
}
var snipet = fi.FieldType.IsClass ? "if(value." + fi.Name + "!=null)" : "";
var value = default(string);
if (s_snipets.TryGetValue(path + "/" + fi.Name, out value))
{
snipet = value;
}
m_w.Write(@"
$1
{
f.Key(""$0""); f.GenSerialize(value.$0);
}
"
.Replace("$0", fi.Name)
.Replace("$1", snipet)
);
}
m_w.Write(@"
f.EndMap();
}
");
foreach (var fi in t.GetFields(FIELD_FLAGS))
{
Generate(fi.FieldType, path + "/" + fi.Name, level + 1);
}
}
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a9c53a1e9bb8c9244927b7a7041e8e3a
timeCreated: 1564983410
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -2,12 +2,17 @@
"name": "UniGLTF.Editor",
"references": [
"VRM",
"ShaderProperty.Runtime"
"ShaderProperty.Runtime",
"UniJSON"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 972f1c538db788042863a4ac753dbc04
timeCreated: 1564987956
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fd51f973e67cbb448bab93da7ea596a8
timeCreated: 1565245501
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace UniJSON
{
@ -76,9 +79,109 @@ namespace UniJSON
Title = rhs.Title;
}
}
public virtual string GetInfo(FieldInfo fi)
{
return "";
}
public static bool IsNumber(Type t)
{
if (t == typeof(sbyte)
|| t == typeof(short)
|| t == typeof(int)
|| t == typeof(long)
|| t == typeof(byte)
|| t == typeof(ushort)
|| t == typeof(uint)
|| t == typeof(ulong)
|| t == typeof(float)
|| t == typeof(double)
)
{
return true;
}
return false;
}
public static string GetTypeName(Type t)
{
if (t.IsArray)
{
return t.GetElementType().Name + "[]";
}
else if (t.IsGenericType)
{
if (t.GetGenericTypeDefinition() == typeof(List<>))
{
return "List<" + t.GetGenericArguments()[0] + ">";
}
else if (t.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
return "Dictionary<" + string.Join(", ", t.GetGenericArguments().Select(x => x.Name).ToArray()) + ">";
}
}
return t.Name;
}
}
public class JsonSchemaAttribute : BaseJsonSchemaAttribute { }
public class JsonSchemaAttribute : BaseJsonSchemaAttribute
{
public override string GetInfo(FieldInfo fi)
{
if (IsNumber(fi.FieldType))
{
var sb = new StringBuilder();
if (!double.IsNaN(Minimum) && !double.IsNaN(Maximum))
{
sb.Append(string.Format("{0} <= N <= {1}", Minimum, Maximum));
}
else if (!double.IsNaN(Minimum))
{
sb.Append(string.Format("{0} <= N", Minimum));
}
else if (!double.IsNaN(Maximum))
{
sb.Append(string.Format("N <= {0}", Maximum));
}
return sb.ToString();
}
else
{
if (EnumValues != null)
{
return string.Join(", ", EnumValues.Select(x => x.ToString()).ToArray());
}
else
{
return GetTypeName(fi.FieldType);
}
}
}
}
public class ItemJsonSchemaAttribute : BaseJsonSchemaAttribute { }
public class ItemJsonSchemaAttribute : BaseJsonSchemaAttribute
{
public override string GetInfo(FieldInfo fi)
{
var sb = new StringBuilder();
sb.Append(GetTypeName(fi.FieldType));
if (!double.IsNaN(MinItems) && !double.IsNaN(MaxItems))
{
sb.Append(string.Format("{0} < N < {1}", MinItems, MaxItems));
}
else if (!double.IsNaN(MinItems))
{
sb.Append(string.Format("{0}< N", MinItems));
}
else if (!double.IsNaN(MaxItems))
{
}
return sb.ToString();
}
}
}

View File

@ -157,7 +157,7 @@ namespace UniJSON
var isFirst = true;
var childLevel = level + 1;
foreach (var kv in this.ObjectItems())
foreach (var kv in this.ObjectItems().OrderBy(x => x.Key.ToString()))
{
if (isFirst)
{

View File

@ -213,7 +213,7 @@ namespace VRM
};
var json2 = JsonSchema.FromType<glTF_VRM_Humanoid>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
Assert.AreEqual(json, json2);
}
[Test]
@ -283,7 +283,7 @@ namespace VRM
};
var json2 = JsonSchema.FromType<glTF_VRM_Meta>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(@"{""allowedUserName"":""OnlyAuthor"",""violentUssageName"":""Disallow"",""sexualUssageName"":""Disallow"",""commercialUssageName"":""Disallow"",""licenseName"":""CC0""}",json2);
Assert.AreEqual(@"{""allowedUserName"":""OnlyAuthor"",""violentUssageName"":""Disallow"",""sexualUssageName"":""Disallow"",""commercialUssageName"":""Disallow"",""licenseName"":""CC0""}", json2);
}
[Test]
@ -544,7 +544,7 @@ namespace VRM
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimationCollider>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
Assert.AreEqual(json, json2);
}
[Test]
@ -562,7 +562,7 @@ namespace VRM
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimationColliderGroup>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
Assert.AreEqual(json, json2);
}
[Test]
@ -598,7 +598,7 @@ namespace VRM
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimationGroup>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
Assert.AreEqual(json, json2);
}
[Test]
@ -652,7 +652,7 @@ namespace VRM
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimation>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
Assert.AreEqual(json, json2);
}
[Test]
@ -675,7 +675,7 @@ namespace VRM
var json2 = JsonSchema.FromType<glTF_VRM_extensions>().Serialize(model, c);
var expected =
String.Format(@"{{""exporterVersion"":""{0}"",""specVersion"":""0.0""}}", VRMVersion.VRM_VERSION);
Assert.AreEqual(expected,json2);
Assert.AreEqual(expected, json2);
}
// TODO: Move to another suitable location

View File

@ -35,6 +35,7 @@ GraphicsSettings:
- {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
- {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0}
m_PreloadedShaders: []
m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
type: 0}

View File

@ -70,6 +70,8 @@ PlayerSettings:
captureSingleScreen: 0
muteOtherAudioSources: 0
Prepare IOS For Recording: 0
deferSystemGesturesMode: 0
hideHomeButton: 0
submitAnalytics: 1
usePlayerLog: 1
bakeCollisionMeshes: 0
@ -99,6 +101,8 @@ PlayerSettings:
n3dsEnableVSync: 0
ignoreAlphaClear: 0
xboxOneResolution: 0
xboxOneSResolution: 0
xboxOneXResolution: 3
xboxOneMonoLoggingLevel: 0
xboxOneLoggingLevel: 1
videoMemoryForVertexBuffers: 0
@ -172,15 +176,21 @@ PlayerSettings:
iPhone47inSplashScreen: {fileID: 0}
iPhone55inPortraitSplashScreen: {fileID: 0}
iPhone55inLandscapeSplashScreen: {fileID: 0}
iPhone58inPortraitSplashScreen: {fileID: 0}
iPhone58inLandscapeSplashScreen: {fileID: 0}
iPadPortraitSplashScreen: {fileID: 0}
iPadHighResPortraitSplashScreen: {fileID: 0}
iPadLandscapeSplashScreen: {fileID: 0}
iPadHighResLandscapeSplashScreen: {fileID: 0}
appleTVSplashScreen: {fileID: 0}
appleTVSplashScreen2x: {fileID: 0}
tvOSSmallIconLayers: []
tvOSSmallIconLayers2x: []
tvOSLargeIconLayers: []
tvOSTopShelfImageLayers: []
tvOSTopShelfImageLayers2x: []
tvOSTopShelfImageWideLayers: []
tvOSTopShelfImageWideLayers2x: []
iOSLaunchScreenType: 0
iOSLaunchScreenPortrait: {fileID: 0}
iOSLaunchScreenLandscape: {fileID: 0}
@ -277,6 +287,9 @@ PlayerSettings:
switchTitleNames_9:
switchTitleNames_10:
switchTitleNames_11:
switchTitleNames_12:
switchTitleNames_13:
switchTitleNames_14:
switchPublisherNames_0:
switchPublisherNames_1:
switchPublisherNames_2:
@ -289,6 +302,9 @@ PlayerSettings:
switchPublisherNames_9:
switchPublisherNames_10:
switchPublisherNames_11:
switchPublisherNames_12:
switchPublisherNames_13:
switchPublisherNames_14:
switchIcons_0: {fileID: 0}
switchIcons_1: {fileID: 0}
switchIcons_2: {fileID: 0}
@ -301,6 +317,9 @@ PlayerSettings:
switchIcons_9: {fileID: 0}
switchIcons_10: {fileID: 0}
switchIcons_11: {fileID: 0}
switchIcons_12: {fileID: 0}
switchIcons_13: {fileID: 0}
switchIcons_14: {fileID: 0}
switchSmallIcons_0: {fileID: 0}
switchSmallIcons_1: {fileID: 0}
switchSmallIcons_2: {fileID: 0}
@ -313,6 +332,9 @@ PlayerSettings:
switchSmallIcons_9: {fileID: 0}
switchSmallIcons_10: {fileID: 0}
switchSmallIcons_11: {fileID: 0}
switchSmallIcons_12: {fileID: 0}
switchSmallIcons_13: {fileID: 0}
switchSmallIcons_14: {fileID: 0}
switchManualHTML:
switchAccessibleURLs:
switchLegalInformation:
@ -354,6 +376,7 @@ PlayerSettings:
switchLocalCommunicationIds_7:
switchParentalControl: 0
switchAllowsScreenshot: 1
switchAllowsVideoCapturing: 1
switchDataLossConfirmation: 0
switchSupportedNpadStyles: 3
switchSocketConfigEnabled: 0
@ -496,7 +519,8 @@ PlayerSettings:
webGLUseEmbeddedResources: 0
webGLUseWasm: 0
webGLCompressionFormat: 1
scriptingDefineSymbols: {}
scriptingDefineSymbols:
1: VRM_DEVELOP
platformArchitecture: {}
scriptingBackend: {}
incrementalIl2cppBuild: {}