mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-05-11 13:04:17 -05:00
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:
commit
521d3bfcfa
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
36
Assets/VRM/UniGLTF/Editor/JsonDeserializeTests.cs
Normal file
36
Assets/VRM/UniGLTF/Editor/JsonDeserializeTests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/VRM/UniGLTF/Editor/JsonDeserializeTests.cs.meta
Normal file
3
Assets/VRM/UniGLTF/Editor/JsonDeserializeTests.cs.meta
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6dab77b78a3d45bf8c20e7dcc8046881
|
||||
timeCreated: 1547715653
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
312
Assets/VRM/UniVRM/Editor/Tests/UniVRMSerializeTests.cs
Normal file
312
Assets/VRM/UniVRM/Editor/Tests/UniVRMSerializeTests.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 06e8ebf6af2b4e19a0c72ad986e88444
|
||||
timeCreated: 1547719804
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user