Merge pull request #123 from dwango/feature/fix_schemas_and_use_json_schema_instead_of_to_json

Feature/fix schemas and use json schema instead of to json
This commit is contained in:
ousttrue 2019-01-18 16:15:56 +09:00 committed by GitHub
commit 521d3bfcfa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1094 additions and 187 deletions

View File

@ -1,5 +1,6 @@
using NUnit.Framework;
using System.IO;
using UniGLTF;
using UniJSON;
using UnityEngine;
@ -41,15 +42,15 @@ namespace VRM.Samples
using (new ActionDisposer(() => { GameObject.DestroyImmediate(context.Root); }))
{
var importJson = JsonParser.Parse(context.Json);
importJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION);
importJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION);
importJson.SetValue("/scene", 0);
importJson.SetValue("/materials/*/doubleSided", false);
var importedJson = JsonParser.Parse(context.Json);
importedJson.SetValue("/extensions/VRM/exporterVersion", VRMVersion.VRM_VERSION);
importedJson.SetValue("/asset/generator", UniGLTF.UniGLTFVersion.UNIGLTF_VERSION);
importedJson.SetValue("/scene", 0);
importedJson.SetValue("/materials/*/doubleSided", false);
//importJson.SetValue("/materials/*/pbrMetallicRoughness/roughnessFactor", 0);
//importJson.SetValue("/materials/*/pbrMetallicRoughness/baseColorFactor", new float[] { 1, 1, 1, 1 });
importJson.SetValue("/accessors/*/normalized", false);
importJson.RemoveValue(Utf8String.From("/nodes/*/extras"));
importedJson.SetValue("/accessors/*/normalized", false);
importedJson.RemoveValue(Utf8String.From("/nodes/*/extras"));
/*
importJson.SetValue("/bufferViews/12/byteStride", 4);
importJson.SetValue("/bufferViews/13/byteStride", 4);
@ -78,11 +79,14 @@ namespace VRM.Samples
importJson.SetValue("/bufferViews/252/byteStride", 64);
importJson.SetValue("/bufferViews/253/byteStride", 64);
*/
importJson.RemoveValue(Utf8String.From("/bufferViews/*/byteStride"));
importedJson.RemoveValue(Utf8String.From("/bufferViews/*/byteStride"));
var vrm = VRMExporter.Export(context.Root);
var exportJson = JsonParser.Parse(vrm.ToJson());
var newExportedJson = JsonParser.Parse(JsonSchema.FromType<glTF>().Serialize(vrm));
/*
foreach (var kv in importJson.Diff(exportJson))
{

View File

@ -0,0 +1,36 @@
using NUnit.Framework;
using UnityEngine;
namespace UniGLTF
{
public class JsonDeserializeTests
{
static T deserialize<T>(string json)
{
return JsonUtility.FromJson<T>(json);
}
[Test]
public void PrimitivesExtensionsTest()
{
{
var r = deserialize<glTFPrimitives_extensions>("");
Assert.AreEqual(null, r);
}
{
var r = deserialize<glTFPrimitives_extensions>("{}");
Assert.NotNull(r);
// This is a curious behaviour of JsonUtility.
// TODO: We should replace a library which treats JSON from JsonUtility
//Assert.Null(r.KHR_draco_mesh_compression);
}
{
var r = deserialize<glTFPrimitives_extensions>("{\"KHR_draco_mesh_compression\":{}}");
Assert.NotNull(r);
//Assert.NotNull(r.KHR_draco_mesh_compression);
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6dab77b78a3d45bf8c20e7dcc8046881
timeCreated: 1547715653

View File

@ -150,45 +150,154 @@ namespace UniGLTF
[Test]
public void MeshTest()
{
var mesh = new glTFMesh("mesh")
var model = new glTFMesh("mesh")
{
primitives = new List<glTFPrimitives>
{
new glTFPrimitives
{
attributes=new glTFAttributes
attributes = new glTFAttributes
{
POSITION=0,
POSITION = 0,
}
}
}
},
};
var f = new JsonFormatter();
f.Serialize(mesh);
var json = new Utf8String(f.GetStoreBytes()).ToString();
var json = model.ToJson();
Assert.AreEqual(@"{""name"":""mesh"",""primitives"":[{""mode"":0,""indices"":-1,""attributes"":{""POSITION"":0},""material"":0}]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFMesh>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""mesh"",""primitives"":[{""mode"":0,""attributes"":{""POSITION"":0},""material"":0}]}", json2);
}
[Test]
public void PrimitiveTest()
{
var prims = new List<glTFPrimitives> {
new glTFPrimitives
var model = new glTFPrimitives
{
attributes = new glTFAttributes
{
attributes = new glTFAttributes
POSITION = 0,
},
extras = new glTFPrimitives_extras
{
targetNames = new List<String>
{
POSITION = 0,
"aaa",
}
}
};
var f = new JsonFormatter();
f.Serialize(prims);
var json = new Utf8String(f.GetStoreBytes()).ToString();
var json = model.ToJson();
Assert.AreEqual(@"{""mode"":0,""indices"":-1,""attributes"":{""POSITION"":0},""material"":0,""extras"":{""targetNames"":[""aaa""]}}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFPrimitives>().Serialize(model, c);
Assert.AreEqual(@"{""mode"":0,""attributes"":{""POSITION"":0},""material"":0,""extras"":{""targetNames"":[""aaa""]}}", json2);
}
[Test]
public void AttributesTest()
{
var model = new glTFAttributes
{
POSITION = 0,
};
var json = model.ToJson();
Assert.AreEqual(@"{""POSITION"":0}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFAttributes>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void TextureInfoTest()
{
var model = new glTFMaterialBaseColorTextureInfo()
{
index = 1,
};
var json = model.ToJson();
Assert.AreEqual(@"{""index"":1,""texCoord"":0}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFMaterialBaseColorTextureInfo>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void TextureInfoTestError()
{
var model = new glTFMaterialBaseColorTextureInfo();
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFMaterialBaseColorTextureInfo>().Serialize(model, c)
);
Assert.AreEqual("[index.String] minimum: ! -1>=0", ex.Message);
}
[Test]
public void MaterialTest()
{
var model = new glTFMaterial()
{
name = "a",
emissiveFactor = new float[] { 0.5f, 0.5f, 0.5f },
};
var json = model.ToJson();
Assert.AreEqual(@"{""name"":""a"",""emissiveFactor"":[0.5,0.5,0.5],""doubleSided"":false}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFMaterial>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""emissiveFactor"":[0.5,0.5,0.5],""doubleSided"":false}", json2);
}
[Test]
public void MaterialAlphaTest()
{
var model = new glTFMaterial()
{
name = "a",
emissiveFactor = new float[] { 0.5f, 0.5f, 0.5f },
alphaMode = "MASK",
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json = JsonSchema.FromType<glTFMaterial>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""emissiveFactor"":[0.5,0.5,0.5],""alphaMode"":""MASK"",""alphaCutoff"":0.5,""doubleSided"":false}", json);
}
[Test]
@ -267,5 +376,203 @@ namespace UniGLTF
Assert.AreEqual(expected, actual);
}
public void MaterialTestError()
{
var model = new glTFMaterial()
{
name = "b",
emissiveFactor = new float[] { 1.5f, 0.5f, 0.5f },
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFMaterial>().Serialize(model, c)
);
Assert.AreEqual("[emissiveFactor.String] maximum: ! 1.5<=1", ex.Message);
}
[Test]
public void NodeTest()
{
var model = new glTFNode()
{
name = "a",
skin = 0,
camera = -1,
};
var json = model.ToJson();
Assert.AreEqual(@"{""name"":""a"",""skin"":0}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFNode>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""extras"":{}}", json2);
}
[Test]
public void NodeMeshTest()
{
var model = new glTFNode()
{
name = "a",
mesh = 2,
skin = 0,
camera = -1,
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json = JsonSchema.FromType<glTFNode>().Serialize(model, c);
Assert.AreEqual(@"{""name"":""a"",""mesh"":2,""skin"":0,""extras"":{}}", json);
}
[Test]
public void NodeTestError()
{
var model = new glTFNode()
{
name = "a",
camera = -2,
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFNode>().Serialize(model, c)
);
Assert.AreEqual("[camera.String] minimum: ! -2>=0", ex.Message);
}
[Test]
public void SkinTest()
{
var model = new glTFSkin()
{
name = "b",
joints = new int[] {1},
};
var json = model.ToJson();
Assert.AreEqual(@"{""inverseBindMatrices"":-1,""joints"":[1]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFSkin>().Serialize(model, c);
Assert.AreEqual(@"{""joints"":[1],""name"":""b""}", json2);
}
[Test]
public void SkinTestEmptyName()
{
var model = new glTFSkin()
{
name = "",
joints = new int[] {1},
};
var json = model.ToJson();
// "name" = "", not excluded
Assert.AreEqual(@"{""inverseBindMatrices"":-1,""joints"":[1]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFSkin>().Serialize(model, c);
Assert.AreEqual(@"{""joints"":[1],""name"":""""}", json2);
}
[Test]
public void SkinTestErrorNull()
{
var model = new glTFSkin()
{
name = "b",
joints = null,
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFSkin>().Serialize(model, c)
);
Assert.AreEqual("[joints.String] null", ex.Message);
}
[Test]
public void SkinTestError()
{
var model = new glTFSkin()
{
name = "b",
joints = new int[] {},
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFSkin>().Serialize(model, c)
);
Assert.AreEqual("[joints.String] minItems", ex.Message);
}
[Test]
public void AssetsTest()
{
var model = new glTFAssets()
{
version = "0.49",
};
//var json = model.ToJson();
//Assert.AreEqual(@"{""inverseBindMatrices"":-1,""joints"":[1]}", json);
//Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTFAssets>().Serialize(model, c);
Assert.AreEqual(@"{""version"":""0.49""}", json2);
}
[Test]
public void AssetsTestError()
{
var model = new glTFAssets();
//var json = model.ToJson();
//Assert.AreEqual(@"{""inverseBindMatrices"":-1,""joints"":[1]}", json);
//Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTFAssets>().Serialize(model, c)
);
Assert.AreEqual("[version.String] null", ex.Message);
}
}
}

View File

@ -4,25 +4,9 @@ using UniJSON;
namespace UniGLTF
{
[Serializable]
public class glTF_KHR_draco_mesh_compression : JsonSerializableBase
{
[JsonSchema(Required = true, Minimum = 0)]
public int bufferView = -1;
public glTFAttributes attributes;
protected override void SerializeMembers(GLTFJsonFormatter f)
{
//throw new NotImplementedException();
}
}
[Serializable]
public partial class glTFPrimitives_extensions : ExtensionsBase<glTFPrimitives_extensions>
{
[JsonSchema(Required = true)]
public glTF_KHR_draco_mesh_compression KHR_draco_mesh_compression;
[JsonSerializeMembers]
void SerializeMembers_draco(GLTFJsonFormatter f)
{

View File

@ -35,12 +35,12 @@ namespace UniGLTF
}
[ItemJsonSchema(ValueType = ValueNodeType.Object)]
[JsonSchema(MinProperties = 1)]
//[JsonSchema(MinProperties = 1)]
public partial class ExtensionsBase<T> : PartialExtensionBase<T>
{
}
[JsonSchema(MinProperties = 1)]
//[JsonSchema(MinProperties = 1)]
public partial class ExtraBase<T> : PartialExtensionBase<T>
{
}

View File

@ -30,7 +30,7 @@ namespace UniGLTF
[JsonSchema(Required = true)]
public glTFAssets asset = new glTFAssets();
#region Buffer
#region Buffer
[JsonSchema(MinItems = 1)]
public List<glTFBuffer> buffers = new List<glTFBuffer>();
public int AddBuffer(IBytesBuffer bytesBuffer)
@ -197,10 +197,10 @@ namespace UniGLTF
}
#endregion
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFTexture> textures = new List<glTFTexture>();
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFTextureSampler> samplers = new List<glTFTextureSampler>();
public glTFTextureSampler GetSampler(int index)
{
@ -257,7 +257,7 @@ namespace UniGLTF
}
}
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFMaterial> materials = new List<glTFMaterial>();
public string GetUniqueMaterialName(int index)
{
@ -288,7 +288,7 @@ namespace UniGLTF
return MaterialHasVertexColor(materialIndex);
}
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFMesh> meshes = new List<glTFMesh>();
public bool MaterialHasVertexColor(int materialIndex)
@ -302,16 +302,16 @@ namespace UniGLTF
return hasVertexColor;
}
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFNode> nodes = new List<glTFNode>();
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFSkin> skins = new List<glTFSkin>();
[JsonSchema(Dependencies = new string[] { "scenes" }, Minimum = 0)]
public int scene;
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<gltfScene> scenes = new List<gltfScene>();
public int[] rootnodes
{
@ -321,16 +321,16 @@ namespace UniGLTF
}
}
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFAnimation> animations = new List<glTFAnimation>();
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<glTFCamera> cameras = new List<glTFCamera>();
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<string> extensionsUsed = new List<string>();
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
public List<string> extensionsRequired = new List<string>();
public glTF_extensions extensions = new glTF_extensions();
@ -503,7 +503,11 @@ namespace UniGLTF
string json;
if (UseUniJSONSerializer)
{
json = JsonSchema.FromType(GetType()).Serialize(this);
var c = new JsonSchemaValidationContext(this)
{
EnableDiagnosisForNotRequiredFields = true,
};
json = JsonSchema.FromType(GetType()).Serialize(this, c);
}
else
{

View File

@ -7,25 +7,25 @@ namespace UniGLTF
[Serializable]
public class glTFAttributes : JsonSerializableBase
{
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int POSITION = -1;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int NORMAL = -1;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int TANGENT = -1;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int TEXCOORD_0 = -1;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int COLOR_0 = -1;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int JOINTS_0 = -1;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int WEIGHTS_0 = -1;
public override int GetHashCode()
@ -66,8 +66,13 @@ namespace UniGLTF
[Serializable]
public class gltfMorphTarget : JsonSerializableBase
{
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int POSITION = -1;
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int NORMAL = -1;
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int TANGENT = -1;
protected override void SerializeMembers(GLTFJsonFormatter f)
@ -87,7 +92,7 @@ namespace UniGLTF
[JsonSchema(EnumValues = new object[] { 0, 1, 2, 3, 4, 5, 6 })]
public int mode;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int indices = -1;
[JsonSchema(Required = true, SkipSchemaComparison = true)]
@ -104,14 +109,14 @@ namespace UniGLTF
[JsonSchema(Minimum = 0)]
public int material;
[JsonSchema(MinItems = 1)]
[JsonSchema(MinItems = 1, ExplicitIgnorableItemLength = 0)]
[ItemJsonSchema(SkipSchemaComparison = true)]
public List<gltfMorphTarget> targets = new List<gltfMorphTarget>();
public glTFPrimitives_extras extras = new glTFPrimitives_extras();
[JsonSchema(SkipSchemaComparison = true)]
public glTFPrimitives_extensions extensions = new glTFPrimitives_extensions();
public glTFPrimitives_extensions extensions = null;
protected override void SerializeMembers(GLTFJsonFormatter f)
{
@ -123,10 +128,6 @@ namespace UniGLTF
{
f.Key("targets"); f.GLTFValue(targets);
}
if (extensions.KHR_draco_mesh_compression != null)
{
f.Key("extensions"); f.GLTFValue(extensions);
}
if (extras.targetNames.Count > 0)
{
f.Key("extras"); f.GLTFValue(extras);

View File

@ -7,7 +7,8 @@ namespace UniGLTF
[Serializable]
public class glTFNode : JsonSerializableBase
{
public string name = "";
// TODO: need an empty string?
public string name;
[JsonSchema(MinItems = 1)]
[ItemJsonSchema(Minimum = 0)]
@ -26,20 +27,21 @@ namespace UniGLTF
[JsonSchema(MinItems = 3, MaxItems = 3)]
public float[] scale;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int mesh = -1;
[JsonSchema(Dependencies = new string[] { "mesh" }, Minimum = 0)]
[JsonSchema(Dependencies = new string[] { "mesh" }, Minimum = 0, ExplicitIgnorableValue = -1)]
public int skin = -1;
[JsonSchema(Dependencies = new string[] { "mesh" }, MinItems = 1)]
public float[] weights;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int camera = -1;
// empty schemas
public glTFNode_extensions extensions;
public glTFNode_extra extras = new glTFNode_extra();
protected override void SerializeMembers(GLTFJsonFormatter f)

View File

@ -6,14 +6,14 @@ namespace UniGLTF
[Serializable]
public class glTFSkin : JsonSerializableBase
{
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int inverseBindMatrices = -1;
[JsonSchema(Required = true, MinItems = 1)]
[ItemJsonSchema(Minimum = 0)]
public int[] joints;
[JsonSchema(Minimum = 0)]
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int skeleton = -1;
// empty schemas

View File

@ -232,7 +232,7 @@ namespace UniGLTF
}
/// <summary>
///
///
/// </summary>
/// <param name="bytes"></param>
public void ParseGlb(Byte[] bytes)
@ -503,9 +503,9 @@ namespace UniGLTF
.ContinueWithCoroutine(Scheduler.MainThread, LoadMaterials)
.OnExecute(Scheduler.ThreadPool, parent =>
{
if (GLTF.meshes
.SelectMany(x => x.primitives)
.Any(x => x.extensions.KHR_draco_mesh_compression != null))
// UniGLTF does not support draco
// https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md#conformance
if (GLTF.extensionsRequired.Contains("KHR_draco_mesh_compression"))
{
throw new UniGLTFNotSupportedException("draco is not supported");
}
@ -958,7 +958,7 @@ namespace UniGLTF
/// Destroy resources that created ImporterContext for runtime load.
/// </summary>
public void DestroyRootAndResources()
{
{
if (!Application.isPlaying)
{
Debug.LogWarningFormat("Dispose called in editor mode. This function is for runtime");

View File

@ -10,7 +10,7 @@ namespace UniJSON
[JsonSchema(Minimum = 0)]
public int X;
[JsonSchema(Minimum = 10)] // Not required, thus ignored when the value violates the constraints
[JsonSchema(Minimum = 10, ExplicitIgnorableValue = 0)] // Not required, thus ignored when the value violates the constraints
public int Y;
}
@ -77,5 +77,124 @@ namespace UniJSON
Assert.AreEqual(expected, actual);
}
public class HasDepsTest
{
[JsonSchema(Minimum = 0, ExplicitIgnorableValue = -1)]
public int X;
[JsonSchema(Dependencies = new string[] {"X"})]
public int Y;
}
[Test]
public void TestHasDeps()
{
var obj = new HasDepsTest();
var s = JsonSchema.FromType<HasDepsTest>();
{
var c = new JsonSchemaValidationContext(obj);
Assert.Null(s.Validator.Validate(c, s));
}
var actual = s.Serialize(obj);
var expected = @"{""X"":0,""Y"":0}";
Assert.AreEqual(expected, actual);
}
[Test]
public void TestHasDepsHasViolation()
{
var obj = new HasDepsTest()
{
X = -1,
};
var s = JsonSchema.FromType<HasDepsTest>();
{
var c = new JsonSchemaValidationContext(obj);
Assert.Null(s.Validator.Validate(c, s));
}
var actual = s.Serialize(obj);
var expected = @"{}";
Assert.AreEqual(expected, actual);
}
public class HasStringTest
{
public string X;
}
[Test]
public void TestHasString()
{
var obj = new HasStringTest()
{
X = "a",
};
var s = JsonSchema.FromType<HasStringTest>();
{
var c = new JsonSchemaValidationContext(obj);
Assert.Null(s.Validator.Validate(c, s));
}
var actual = s.Serialize(obj);
var expected = @"{""X"":""a""}";
Assert.AreEqual(expected, actual);
}
[Test]
public void TestHasStringWithNull()
{
var obj = new HasStringTest();
var s = JsonSchema.FromType<HasStringTest>();
{
var c = new JsonSchemaValidationContext(obj);
Assert.Null(s.Validator.Validate(c, s));
}
var actual = s.Serialize(obj);
var expected = @"{}";
Assert.AreEqual(expected, actual);
}
public class NestedRequiredTestParent
{
[JsonSchema(Required = true)]
public NestedRequiredTestChild C;
}
public class NestedRequiredTestChild
{
public string X;
}
[Test]
public void TestNestedRequired()
{
var obj = new NestedRequiredTestParent()
{
C = new NestedRequiredTestChild(),
};
var s = JsonSchema.FromType<NestedRequiredTestParent>();
{
var c = new JsonSchemaValidationContext(obj);
Assert.Null(s.Validator.Validate(c, s));
}
var actual = s.Serialize(obj);
var expected = @"{""C"":{}}";
Assert.AreEqual(expected, actual);
}
}
}

View File

@ -354,7 +354,7 @@ namespace UniJSON
var s = JsonSchema.FromType<HasArrayOBject>();
Assert.Null(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] {} }));
Assert.Null(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] { } }));
Assert.Null(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] { 0.5f } }));
Assert.NotNull(s.Validator.Validate(c, new HasArrayOBject { xs = new float[] { 1.5f } }));
@ -379,12 +379,63 @@ namespace UniJSON
var s = JsonSchema.FromType<HasListObject>();
Assert.Null(s.Validator.Validate(c, new HasListObject { xs = new List<float> {} }));
Assert.Null(s.Validator.Validate(c, new HasListObject { xs = new List<float> { } }));
Assert.Null(s.Validator.Validate(c, new HasListObject { xs = new List<float> { 0.5f } }));
Assert.NotNull(s.Validator.Validate(c, new HasListObject { xs = new List<float> { 1.5f } }));
Assert.True(c.IsEmpty());
}
}
class HasRequiredListObject
{
[JsonSchema(Required = true, MinItems = 1)]
[ItemJsonSchema(Minimum = 0)]
public int[] xs;
}
[Test]
public void HasRequiredListObjecttValidator()
{
{
var c = new JsonSchemaValidationContext("test")
{
EnableDiagnosisForNotRequiredFields = true,
};
var s = JsonSchema.FromType<HasRequiredListObject>();
Assert.NotNull(s.Validator.Validate(c, new HasRequiredListObject()));
Assert.NotNull(s.Validator.Validate(c, new HasRequiredListObject { xs = new int[] {} }));
Assert.NotNull(s.Validator.Validate(c, new HasRequiredListObject { xs = new int[] { -1 } }));
Assert.Null(s.Validator.Validate(c, new HasRequiredListObject { xs = new int[] { 0 } }));
Assert.True(c.IsEmpty());
}
}
class HasRequiredStringObject
{
[JsonSchema(Required = true)]
public string s;
}
[Test]
public void HasRequiredStringObjectValidator()
{
{
var c = new JsonSchemaValidationContext("test")
{
EnableDiagnosisForNotRequiredFields = true,
};
var s = JsonSchema.FromType<HasRequiredStringObject>();
Assert.NotNull(s.Validator.Validate(c, new HasRequiredStringObject()));
Assert.Null(s.Validator.Validate(c, new HasRequiredStringObject { s = "" }));
Assert.True(c.IsEmpty());
}
}
}
}

View File

@ -162,7 +162,14 @@ namespace UniJSON
{
// reflection
var schema = JsonSchema.FromType<T>();
return (IFormatter f, T value) => schema.Serialize(f, value);
return (IFormatter f, T value) =>
{
var c = new JsonSchemaValidationContext(value)
{
EnableDiagnosisForNotRequiredFields = true
};
schema.Serialize(f, value, c);
};
}

View File

@ -392,7 +392,10 @@ namespace UniJSON
{
if (c == null)
{
c = new JsonSchemaValidationContext(o);
c = new JsonSchemaValidationContext(o)
{
EnableDiagnosisForNotRequiredFields = true,
};
}
var ex = Validator.Validate(c, o);

View File

@ -297,28 +297,66 @@ namespace UniJSON
}
}
static class GenericFieldView<T>
{
public static FieldInfo[] GetFields()
{
var t = typeof(T);
return t.GetFields(BindingFlags.Instance | BindingFlags.Public);
}
public static void CreateFieldProcessors<G, D>(
string methodName,
Dictionary<string, D> processors
)
{
var mi = typeof(G).GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic);
var t = typeof(T);
foreach (var fi in GetFields())
{
var value = Expression.Parameter(t, "value");
var fieldValue = Expression.Field(value, fi);
var compileld = Expression.Lambda(fieldValue, value).Compile();
var getter = Expression.Constant(compileld);
var name = Expression.Constant(fi.Name);
var g = mi.MakeGenericMethod(fi.FieldType);
var call = Expression.Call(g, getter, name);
var lambda = (Func<D>)Expression.Lambda(call).Compile();
processors.Add(fi.Name, lambda());
}
}
}
internal class ValidationResult
{
public bool IsIgnorable;
public JsonSchemaValidationException Ex;
}
public static class GenericValidator<T>
{
class ObjectValidator
{
delegate JsonSchemaValidationException FieldValidator(
JsonSchema s, JsonSchemaValidationContext c, T o, bool isRequired);
JsonSchema s, JsonSchemaValidationContext c, T o, out bool isIgnorable);
Dictionary<string, FieldValidator> m_validators = new Dictionary<string, FieldValidator>();
Dictionary<string, FieldValidator> m_validators;
static FieldValidator CreteFieldValidator<U>(Func<T, U> getter, string name)
static FieldValidator CreateFieldValidator<U>(Func<T, U> getter, string name)
{
return (s, c, o, isRequired) =>
return (JsonSchema s, JsonSchemaValidationContext c, T o, out bool isIgnorable) =>
{
var v = s.Validator;
using (c.Push(name))
{
var field = getter(o);
var ex = v.Validate(c, field);
if (ex != null && !isRequired && s.IsExplicitlyIgnorableValue(field))
{
return null;
}
isIgnorable = ex != null && s.IsExplicitlyIgnorableValue(field);
return ex;
}
@ -327,25 +365,46 @@ namespace UniJSON
public ObjectValidator()
{
var mi = typeof(ObjectValidator).GetMethod("CreteFieldValidator",
BindingFlags.Static|BindingFlags.NonPublic);
var validators = new Dictionary<string, FieldValidator>();
GenericFieldView<T>.CreateFieldProcessors<ObjectValidator, FieldValidator>(
"CreateFieldValidator", validators);
var t = typeof(T);
foreach(var fi in t.GetFields(
BindingFlags.Instance|BindingFlags.Public))
m_validators = validators;
}
public JsonSchemaValidationException ValidateProperty(
HashSet<string> required,
KeyValuePair<string, JsonSchema> property,
JsonSchemaValidationContext c,
T o,
out bool isIgnorable
)
{
var fieldName = property.Key;
var schema = property.Value;
isIgnorable = false;
FieldValidator fv;
if (m_validators.TryGetValue(fieldName, out fv))
{
var value = Expression.Parameter(typeof(T), "value");
var fieldValue = Expression.Field(value, fi);
var compileld = Expression.Lambda(fieldValue, value).Compile();
var isRequired = required != null && required.Contains(fieldName);
var getter = Expression.Constant(compileld);
var name = Expression.Constant(fi.Name);
var g = mi.MakeGenericMethod(fi.FieldType);
var call = Expression.Call(g, getter, name);
var lambda = (Func<FieldValidator>)Expression.Lambda(call).Compile();
bool isMemberIgnorable;
var ex = fv(schema, c, o, out isMemberIgnorable);
if (ex != null)
{
isIgnorable = !isRequired && isMemberIgnorable;
m_validators.Add(fi.Name, lambda());
if (isRequired // required fields must be checked
|| c.EnableDiagnosisForNotRequiredFields)
{
return ex;
}
}
}
return null;
}
public JsonSchemaValidationException Validate(
@ -355,41 +414,62 @@ namespace UniJSON
{
foreach (var kv in properties)
{
var fieldName = kv.Key;
var schema = kv.Value;
FieldValidator fv;
if (m_validators.TryGetValue(fieldName, out fv))
bool isIgnorable;
var ex = ValidateProperty(required, kv, c, o, out isIgnorable);
if (ex != null && !isIgnorable)
{
var isRequired = required != null && required.Contains(fieldName);
var ex = fv(schema, c, o, isRequired);
if (ex != null)
{
if (isRequired // required fields must be checked
|| c.EnableDiagnosisForNotRequiredFields)
{
return ex;
}
}
return ex;
}
}
return null;
}
public void ValidationResults
(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o,
Dictionary<string, ValidationResult> results)
{
foreach (var kv in properties)
{
bool isIgnorable;
var ex = ValidateProperty(required, kv, c, o, out isIgnorable);
results.Add(kv.Key, new ValidationResult {
IsIgnorable = isIgnorable,
Ex = ex,
});
}
}
}
static ObjectValidator s_validator;
public static JsonSchemaValidationException Validate(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o)
static void prepareValidator()
{
if (s_validator == null)
{
s_validator = new ObjectValidator();
}
}
public static JsonSchemaValidationException Validate(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o)
{
prepareValidator();
return s_validator.Validate(required, properties, c, o);
}
internal static void ValidationResults(HashSet<string> required,
Dictionary<string, JsonSchema> properties,
JsonSchemaValidationContext c, T o,
Dictionary<string, ValidationResult> results)
{
prepareValidator();
s_validator.ValidationResults(required, properties, c, o, results);
}
}
public JsonSchemaValidationException Validate<T>(JsonSchemaValidationContext c, T o)
@ -411,103 +491,89 @@ namespace UniJSON
{
class Serializer
{
delegate void FieldSerializer(JsonObjectValidator v, IFormatter f, JsonSchemaValidationContext c, T src);
delegate void FieldSerializer(JsonSchema s, JsonSchemaValidationContext c, IFormatter f, T o,
Dictionary<string, ValidationResult> vRes, string[] deps);
List<FieldSerializer> m_fieldSerializers = new List<FieldSerializer>();
Dictionary<string, FieldSerializer> m_serializers;
static FieldSerializer CreateSerializer<U>(FieldInfo fi)
static FieldSerializer CreateFieldSerializer<U>(Func<T, U> getter, string name)
{
var src = Expression.Parameter(typeof(T), "src");
var getter = Expression.Field(src, fi);
var compiled = (Func<T, U>)Expression.Lambda(getter, src).Compile();
var name = fi.Name;
return (v, f, c, s) =>
return (s, c, f, o, vRes, deps) =>
{
//c.Push(name);
var v = s.Validator;
var field = getter(o);
var validator = v.Properties[name].Validator;
var value = compiled(s);
// validate
if (validator.Validate(c, value) != null)
if (vRes[name].Ex != null)
{
return;
}
/*
// depencencies
string[] dependencies;
if (validator.Dependencies.TryGetValue(name, out dependencies))
if (deps != null)
{
// check dependencies
bool hasDependencies = true;
foreach (var x in dependencies)
foreach(var dep in deps)
{
if (!map.ContainsKey(x))
if (vRes[dep].Ex != null)
{
hasDependencies = false;
break;
return;
}
}
if (!hasDependencies)
{
continue;
}
}
*/
f.Key(name);
validator.Serialize(f, c, value);
//f.Serialize(value);
//c.Pop();
v.Serialize(f, c, field);
};
}
public void AddField(FieldInfo fi)
public Serializer()
{
var mi = typeof(Serializer).GetMethod("CreateSerializer",
BindingFlags.Static | BindingFlags.NonPublic);
var g = mi.MakeGenericMethod(fi.FieldType);
var f = Expression.Constant(fi);
var call = Expression.Call(g, f);
var compiled = (Func<FieldSerializer>)Expression.Lambda(call).Compile();
m_fieldSerializers.Add(compiled());
var serializers = new Dictionary<string, FieldSerializer>();
GenericFieldView<T>.CreateFieldProcessors<Serializer, FieldSerializer>(
"CreateFieldSerializer", serializers);
m_serializers = serializers;
}
public void Serialize(JsonObjectValidator v, IFormatter f, JsonSchemaValidationContext c, T value)
public void Serialize(JsonObjectValidator objectValidator,
IFormatter f, JsonSchemaValidationContext c, T o)
{
f.BeginMap(m_fieldSerializers.Count);
foreach (var s in m_fieldSerializers)
// Validates fields
var validationResults = new Dictionary<string, ValidationResult>();
GenericValidator<T>.ValidationResults(
objectValidator.Required, objectValidator.Properties,
c, o, validationResults);
// Serialize fields
f.BeginMap(objectValidator.Properties.Count());
foreach (var property in objectValidator.Properties)
{
s(v, f, c, value);
var fieldName = property.Key;
var schema = property.Value;
string[] deps = null;
objectValidator.Dependencies.TryGetValue(fieldName, out deps);
FieldSerializer fs;
if (m_serializers.TryGetValue(fieldName, out fs))
{
fs(schema, c, f, o, validationResults, deps);
}
}
f.EndMap();
}
}
static FieldInfo[] s_fields;
static Serializer s_serializer;
public static void Serialize(JsonObjectValidator validator,
public static void Serialize(JsonObjectValidator objectValidator,
IFormatter f, JsonSchemaValidationContext c, T value)
{
if (s_serializer == null)
{
var t = typeof(T);
if (t == typeof(object))
{
throw new ArgumentException("object cannot serialize");
}
var serializer = new Serializer();
var fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public);
foreach (var fi in fields)
{
serializer.AddField(fi);
}
s_serializer = serializer;
s_serializer = new Serializer();
}
s_serializer.Serialize(validator, f, c, value);
s_serializer.Serialize(objectValidator, f, c, value);
}
}

View File

@ -0,0 +1,312 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using UniJSON;
using UnityEngine;
namespace VRM
{
public class UniVRMSerializeTests
{
[Test]
public void MaterialValueBindTest()
{
var model = new glTF_VRM_MaterialValueBind();
var json = model.ToJson();
Assert.AreEqual(@"{}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_MaterialValueBind>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void BlendShapeBindTest()
{
var model = new glTF_VRM_BlendShapeBind()
{
mesh = 1,
weight = 2,
index = 3,
};
var json = model.ToJson();
Assert.AreEqual(@"{""mesh"":1,""index"":3,""weight"":2}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_BlendShapeBind>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void BlendShapeBindTestError()
{
var model = new glTF_VRM_BlendShapeBind();
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTF_VRM_BlendShapeBind>().Serialize(model, c)
);
Assert.AreEqual("[mesh.String] minimum: ! -1>=0", ex.Message);
}
[Test]
public void BlendShapeGroupTest()
{
var model = new glTF_VRM_BlendShapeGroup()
{
presetName = "neutral",
};
var json = model.ToJson();
Assert.AreEqual(@"{""presetName"":""neutral"",""isBinary"":false,""binds"":[],""materialValues"":[]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_BlendShapeGroup>().Serialize(model, c);
Assert.AreEqual(@"{""presetName"":""neutral"",""binds"":[],""materialValues"":[],""isBinary"":false}", json2);
}
[Test]
public void BlendShapeGroupTestError()
{
var model = new glTF_VRM_BlendShapeGroup()
{
presetName = "aaaaaaaaaaaa_not_exists_",
};
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var ex = Assert.Throws<JsonSchemaValidationException>(
() => JsonSchema.FromType<glTF_VRM_BlendShapeGroup>().Serialize(model, c)
);
Assert.AreEqual("[presetName.String] aaaaaaaaaaaa_not_exists_ is not valid enum", ex.Message);
}
[Test]
public void DegreeMapTest()
{
var model = new glTF_VRM_DegreeMap();
var json = model.ToJson();
Assert.AreEqual(@"{""xRange"":90,""yRange"":10}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_DegreeMap>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void MeshAnnotationTest()
{
var model = new glTF_VRM_MeshAnnotation();
var json = model.ToJson();
Assert.AreEqual(@"{""mesh"":0}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_MeshAnnotation>().Serialize(model, c);
Assert.AreEqual(json, json2);
}
[Test]
public void FirstPersonTest()
{
var model = new glTF_VRM_Firstperson();
var json = model.ToJson();
Assert.AreEqual(
@"{""firstPersonBone"":-1,""firstPersonBoneOffset"":{""x"":0,""y"":0,""z"":0},""meshAnnotations"":[],""lookAtTypeName"":""Bone"",""lookAtHorizontalInner"":{""xRange"":90,""yRange"":10},""lookAtHorizontalOuter"":{""xRange"":90,""yRange"":10},""lookAtVerticalDown"":{""xRange"":90,""yRange"":10},""lookAtVerticalUp"":{""xRange"":90,""yRange"":10}}",
json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_Firstperson>().Serialize(model, c);
Assert.AreEqual(
@"{""firstPersonBone"":-1,""firstPersonBoneOffset"":{""x"":0,""y"":0,""z"":0},""meshAnnotations"":[],""lookAtTypeName"":""Bone"",""lookAtHorizontalInner"":{""xRange"":90,""yRange"":10},""lookAtHorizontalOuter"":{""xRange"":90,""yRange"":10},""lookAtVerticalDown"":{""xRange"":90,""yRange"":10},""lookAtVerticalUp"":{""xRange"":90,""yRange"":10}}",
json2);
}
[Test]
public void HumanoidBoneTest()
{
var model = new glTF_VRM_HumanoidBone()
{
bone = "hips", // NOTE: This field must not be null?
};
var json = model.ToJson();
Assert.AreEqual(@"{""bone"":""hips"",""node"":-1,""useDefaultValues"":true}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_HumanoidBone>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(
@"{""bone"":""hips"",""node"":-1,""useDefaultValues"":true,""min"":{""x"":0,""y"":0,""z"":0},""max"":{""x"":0,""y"":0,""z"":0},""center"":{""x"":0,""y"":0,""z"":0},""axisLength"":0}",
json2);
}
[Test]
public void HumanoidTest()
{
var model = new glTF_VRM_Humanoid();
var json = model.ToJson();
Assert.AreEqual(@"{""humanBones"":[],""armStretch"":0.05,""legStretch"":0.05,""upperArmTwist"":0.5,""lowerArmTwist"":0.5,""upperLegTwist"":0.5,""lowerLegTwist"":0.5,""feetSpacing"":0,""hasTranslationDoF"":false}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_Humanoid>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
}
[Test]
public void MaterialTest()
{
var model = new glTF_VRM_Material();
var json = model.ToJson();
Assert.AreEqual(@"{""renderQueue"":-1,""floatProperties"":{},""vectorProperties"":{},""textureProperties"":{},""keywordMap"":{},""tagMap"":{}}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_Material>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
}
[Test]
public void MetaTest()
{
var model = new glTF_VRM_Meta();
var json = model.ToJson();
Assert.AreEqual(@"{""texture"":-1}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_Meta>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
}
[Test]
public void SecondaryAnimationColliderTest()
{
var model = new glTF_VRM_SecondaryAnimationCollider()
{
offset = new Vector3(1, 2, 3),
radius = 42,
};
var json = model.ToJson();
Assert.AreEqual(@"{""offset"":{""x"":1,""y"":2,""z"":3},""radius"":42}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimationCollider>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
}
[Test]
public void SecondaryAnimationColliderGroupTest()
{
var model = new glTF_VRM_SecondaryAnimationColliderGroup();
var json = model.ToJson();
Assert.AreEqual(@"{""node"":0,""colliders"":[]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimationColliderGroup>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
}
[Test]
public void SecondaryAnimationGroupTest()
{
var model = new glTF_VRM_SecondaryAnimationGroup();
var json = model.ToJson();
Assert.AreEqual(@"{""stiffiness"":0,""gravityPower"":0,""gravityDir"":{""x"":0,""y"":0,""z"":0},""dragForce"":0,""center"":0,""hitRadius"":0,""bones"":[],""colliderGroups"":[]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimationGroup>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
}
[Test]
public void SecondaryAnimationTest()
{
var model = new glTF_VRM_SecondaryAnimation();
var json = model.ToJson();
Assert.AreEqual(@"{""boneGroups"":[],""colliderGroups"":[]}", json);
Debug.Log(json);
var c = new JsonSchemaValidationContext("")
{
EnableDiagnosisForNotRequiredFields = true,
};
var json2 = JsonSchema.FromType<glTF_VRM_SecondaryAnimation>().Serialize(model, c);
// NOTE: New serializer outputs values which will not be used...
Assert.AreEqual(json,json2);
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 06e8ebf6af2b4e19a0c72ad986e88444
timeCreated: 1547719804

View File

@ -24,6 +24,8 @@ namespace VRM
public bool PoseFreeze = true;
public bool UseExperimentalExporter = true;
public IEnumerable<string> CanExport()
{
if (Source == null)
@ -250,7 +252,7 @@ namespace VRM
}
void Export(string path, List<GameObject> destroy)
{
{
var target = Source;
if (IsPrefab(target))
{
@ -277,7 +279,7 @@ namespace VRM
vrm.extensions.VRM.meta.title = Title;
vrm.extensions.VRM.meta.author = Author;
var bytes = vrm.ToGlbBytes();
var bytes = vrm.ToGlbBytes(UseExperimentalExporter);
File.WriteAllBytes(path, bytes);
Debug.LogFormat("Export elapsed {0}", sw.Elapsed);
}

View File

@ -90,7 +90,10 @@ namespace VRM
[JsonSchema(Title = "vrm.secondaryanimation", Description = "The setting of automatic animation of string-like objects such as tails and hairs.")]
public class glTF_VRM_SecondaryAnimation : JsonSerializableBase
{
[JsonSchema(ExplicitIgnorableItemLength = 0)]
public List<glTF_VRM_SecondaryAnimationGroup> boneGroups = new List<glTF_VRM_SecondaryAnimationGroup>();
[JsonSchema(ExplicitIgnorableItemLength = 0)]
public List<glTF_VRM_SecondaryAnimationColliderGroup> colliderGroups = new List<glTF_VRM_SecondaryAnimationColliderGroup>();
protected override void SerializeMembers(GLTFJsonFormatter f)