From 8096c89e5122a12fe01fe6854a351e761447f04b Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 15:25:32 +0900 Subject: [PATCH 1/8] =?UTF-8?q?extensionUsed=20=E3=81=AE=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E3=82=92=E8=87=AA=E5=8B=95=E5=8C=96=E3=81=99=E3=82=8B=E6=BA=96?= =?UTF-8?q?=E5=82=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/IO/ExportingGltfData.cs | 69 ++----------------- .../Runtime/UniGLTF/IO/GltfJsonUtil.cs | 15 ++++ .../Runtime/UniGLTF/IO/GltfJsonUtil.cs.meta | 11 +++ .../Tests/UniGLTF/GltfJsonUtilTests.cs | 48 +++++++++++++ .../Tests/UniGLTF/GltfJsonUtilTests.cs.meta | 11 +++ 5 files changed, 91 insertions(+), 63 deletions(-) create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs create mode 100644 Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs.meta create mode 100644 Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs create mode 100644 Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs.meta diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs index c08ee784b..7eb73bd4a 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs @@ -138,66 +138,6 @@ namespace UniGLTF #endregion #region ToGltf & ToGlb - static Utf8String s_extensions = Utf8String.From("extensions"); - - static bool UsedExtension(glTF self, string key) - { - if (self.extensionsUsed.Contains(key)) - { - return true; - } - - return false; - } - - static void Traverse(glTF self, JsonNode node, JsonFormatter f, Utf8String parentKey) - { - if (node.IsMap()) - { - f.BeginMap(); - foreach (var kv in node.ObjectItems()) - { - if (parentKey == s_extensions) - { - if (!UsedExtension(self, kv.Key.GetString())) - { - // skip extension not in used - continue; - } - } - f.Key(kv.Key.GetUtf8String()); - Traverse(self, kv.Value, f, kv.Key.GetUtf8String()); - } - f.EndMap(); - } - else if (node.IsArray()) - { - f.BeginList(); - foreach (var x in node.ArrayItems()) - { - Traverse(self, x, f, default(Utf8String)); - } - f.EndList(); - } - else - { - f.Value(node); - } - } - - /// - /// 出力前に不要な extension を削除する - /// - /// - /// - /// - static string RemoveUnusedExtensions(glTF self, string json) - { - var f = new JsonFormatter(); - Traverse(self, JsonParser.Parse(json), f, default(Utf8String)); - return f.ToString(); - } - /// /// GLBバイト列 /// @@ -207,9 +147,10 @@ namespace UniGLTF var f = new JsonFormatter(); GltfSerializer.Serialize(f, GLTF); - // remove unused extenions var json = f.ToString().ParseAsJson().ToString(" "); - RemoveUnusedExtensions(GLTF, json); + + json = GltfJsonUtil.Update_extensionsUsed(json); + return Glb.Create(json, BinBytes).ToBytes(); } @@ -234,7 +175,9 @@ namespace UniGLTF var f = new JsonFormatter(); GltfSerializer.Serialize(f, GLTF); var json = f.ToString().ParseAsJson().ToString(" "); - RemoveUnusedExtensions(GLTF, json); + + json = GltfJsonUtil.Update_extensionsUsed(json); + return (json, GLTF.buffers[0]); } #endregion diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs new file mode 100644 index 000000000..e45e11f8c --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -0,0 +1,15 @@ +namespace UniGLTF +{ + public static class GltfJsonUtil + { + /// + /// https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/schema/glTF.schema.json + /// + /// + /// + public static string Update_extensionsUsed(string src) + { + return src; + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs.meta b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs.meta new file mode 100644 index 000000000..bc9cd03f0 --- /dev/null +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5a820504e80b57241b7716b5606235f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs new file mode 100644 index 000000000..1866d808a --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs @@ -0,0 +1,48 @@ +using NUnit.Framework; +using UniJSON; + +namespace UniGLTF +{ + public class GltfJsonUtilTests + { + [Test] + public void Update_extensionUsed() + { + var dst = GltfJsonUtil.Update_extensionsUsed(@"{ + ""asset"": { + ""generator"": ""COLLADA2GLTF"", + ""version"": ""2.0"" + }, + ""scene"": 0, + ""scenes"": [ + { + ""nodes"": [ + 0 + ] + } + ], + ""materials"": [ + { + ""pbrMetallicRoughness"": { + ""baseColorFactor"": [ + 0.800000011920929, + 0.0, + 0.0, + 1.0 + ], + ""metallicFactor"": 0.0 + }, + ""name"": ""Red"", + ""extensions"": { + ""KHR_materials_unlit"", {} + } + } + ], +}"); + + var parsed = dst.ParseAsJson(); + + Assert.AreEqual("[\"KHR_materials_unlit\"]", parsed["extensionUsed"].ToString()); + } + } +} \ No newline at end of file diff --git a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs.meta b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs.meta new file mode 100644 index 000000000..d45dd48e9 --- /dev/null +++ b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bf03004ca38f9994c8feedbf3afc9352 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: From 659bbd43f4aa263bdfe895aa3dee7467445af945 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 16:20:59 +0900 Subject: [PATCH 2/8] impl Update_extensionsUsed --- .../Runtime/UniGLTF/IO/GltfJsonUtil.cs | 86 ++++++++++++++++++- .../Tests/UniGLTF/GltfJsonUtilTests.cs | 50 ++++++++++- 2 files changed, 132 insertions(+), 4 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs index e45e11f8c..3b7403eff 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -1,15 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using UniJSON; +using UnityEngine; + namespace UniGLTF { public static class GltfJsonUtil { + public static IEnumerable TraverseJsonPath(JsonNode node, List path) + { + if (path == null) + { + path = new List(); + } + yield return path.ToArray(); + + if (node.IsArray()) + { + int i = 0; + foreach (var child in node.ArrayItems()) + { + path.Add(i); + foreach (var x in TraverseJsonPath(child, path)) + { + yield return x; + } + path.RemoveAt(path.Count - 1); + ++i; + } + } + else if (node.IsMap()) + { + foreach (var kv in node.ObjectItems()) + { + path.Add(kv.Key.GetString()); + foreach (var x in TraverseJsonPath(kv.Value, path)) + { + yield return x; + } + path.RemoveAt(path.Count - 1); + } + } + } + + static string DoubleQuote(string src) + { + return $"\"{src}\""; + } + /// /// https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/schema/glTF.schema.json + /// + /// extensionUsed の更新を各拡張自身にやらせるのは無駄だし、手動でコントロールするのも間違いの元である。 + /// 完成品の JSON から後付けで作ることにした。 + /// + /// * Exporter しか使わない処理なので、GC, 処理速度は気にしてない + /// /// /// /// public static string Update_extensionsUsed(string src) { + var used = new HashSet(); + var parsed = src.ParseAsJson(); + foreach (var path in TraverseJsonPath(parsed, null)) + { + if (path.Length >= 2) + { + if (path[path.Length - 2] is string x) + { + if (x == "extensions") + { + used.Add(path[path.Length - 1] as string); + } + } + } + } + + var values = "\"extensionUsed\":[" + string.Join(",", used.Select(x => DoubleQuote(x))) + "]"; + Debug.Log(values); + if (parsed.ContainsKey("extensionUsed")) + { + // replace + src = Regex.Replace(src, @"""extensionUsed""\s*:\s*\[[^\]]+\]", values); + } + else + { + // add + var close = src.LastIndexOf("}"); + src = src.Substring(0, close) + "," + values + "}"; + } + return src; } } -} \ No newline at end of file +} diff --git a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs index 1866d808a..d044a0744 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using UniJSON; +using System.Linq; namespace UniGLTF { @@ -34,15 +35,58 @@ namespace UniGLTF }, ""name"": ""Red"", ""extensions"": { - ""KHR_materials_unlit"", {} + ""KHR_materials_unlit"": {} } } - ], + ] }"); var parsed = dst.ParseAsJson(); - Assert.AreEqual("[\"KHR_materials_unlit\"]", parsed["extensionUsed"].ToString()); + Assert.AreEqual(new string[] { "KHR_materials_unlit" }, + parsed["extensionUsed"].ArrayItems().Select(x => x.GetString()).ToArray()); + } + + [Test] + public void Replace_extensionUsed() + { + var dst = GltfJsonUtil.Update_extensionsUsed(@"{ + ""asset"": { + ""generator"": ""COLLADA2GLTF"", + ""version"": ""2.0"" + }, + ""scene"": 0, + ""scenes"": [ + { + ""nodes"": [ + 0 + ] + } + ], + ""extensionUsed"": [""dummy""], + ""materials"": [ + { + ""pbrMetallicRoughness"": { + ""baseColorFactor"": [ + 0.800000011920929, + 0.0, + 0.0, + 1.0 + ], + ""metallicFactor"": 0.0 + }, + ""name"": ""Red"", + ""extensions"": { + ""KHR_materials_unlit"": {} + } + } + ] +}"); + + var parsed = dst.ParseAsJson(); + + Assert.AreEqual(new string[] { "KHR_materials_unlit" }, + parsed["extensionUsed"].ArrayItems().Select(x => x.GetString()).ToArray()); } } } \ No newline at end of file From e4dae3621b1b9af86d2a1826b26cf7290acebea3 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 18:19:33 +0900 Subject: [PATCH 3/8] rename Update_extensionsUsed to FindUsedExtensionsAndUpdateJson --- Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs | 4 ++-- Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs | 2 +- Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs index 7eb73bd4a..a5b29d16c 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/ExportingGltfData.cs @@ -149,7 +149,7 @@ namespace UniGLTF var json = f.ToString().ParseAsJson().ToString(" "); - json = GltfJsonUtil.Update_extensionsUsed(json); + json = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(json); return Glb.Create(json, BinBytes).ToBytes(); } @@ -176,7 +176,7 @@ namespace UniGLTF GltfSerializer.Serialize(f, GLTF); var json = f.ToString().ParseAsJson().ToString(" "); - json = GltfJsonUtil.Update_extensionsUsed(json); + json = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(json); return (json, GLTF.buffers[0]); } diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs index 3b7403eff..5492e5490 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -61,7 +61,7 @@ namespace UniGLTF /// /// /// - public static string Update_extensionsUsed(string src) + public static string FindUsedExtensionsAndUpdateJson(string src) { var used = new HashSet(); var parsed = src.ParseAsJson(); diff --git a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs index d044a0744..9c58fd5d0 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs @@ -9,7 +9,7 @@ namespace UniGLTF [Test] public void Update_extensionUsed() { - var dst = GltfJsonUtil.Update_extensionsUsed(@"{ + var dst = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(@"{ ""asset"": { ""generator"": ""COLLADA2GLTF"", ""version"": ""2.0"" @@ -50,7 +50,7 @@ namespace UniGLTF [Test] public void Replace_extensionUsed() { - var dst = GltfJsonUtil.Update_extensionsUsed(@"{ + var dst = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(@"{ ""asset"": { ""generator"": ""COLLADA2GLTF"", ""version"": ""2.0"" From 8f5a6bed4ec82047ed42a0a457e825d2bd4a42a1 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 18:27:20 +0900 Subject: [PATCH 4/8] =?UTF-8?q?=E3=82=B3=E3=83=BC=E3=83=89=E6=95=B4?= =?UTF-8?q?=E7=90=86=E3=80=82=E3=82=B3=E3=83=A1=E3=83=B3=E3=83=88=E5=A2=97?= =?UTF-8?q?=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/IO/GltfJsonUtil.cs | 58 ++++++++++++++++--- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs index 5492e5490..341a5bab9 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -9,6 +9,13 @@ namespace UniGLTF { public static class GltfJsonUtil { + /// + /// JsonPath を 再帰的に列挙する + /// object[] の中身は int(array index) or string(object key) + /// + /// + /// + /// public static IEnumerable TraverseJsonPath(JsonNode node, List path) { if (path == null) @@ -50,6 +57,43 @@ namespace UniGLTF return $"\"{src}\""; } + /// + /// jsonPath が + /// + /// [..., "extensions", "EXTENSION_NAME"] + /// + /// で有る場合に EXTENSION_NAME を返す。 + /// + /// + /// + /// + static bool TryGetExtensionName(object[] path, out string extensionName) + { + if (path.Length >= 2) + { + if (path[path.Length - 2] is string x) + { + if (x == "extensions") + { + if (path[path.Length - 1] is string y) + { + extensionName = y; + return true; + } + else + { + // ありえない。はず + var join = string.Join(", ", path); + Debug.LogWarning($"invalid json path: {join}"); + } + } + } + } + + extensionName = default; + return false; + } + /// /// https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/schema/glTF.schema.json /// @@ -63,19 +107,15 @@ namespace UniGLTF /// public static string FindUsedExtensionsAndUpdateJson(string src) { - var used = new HashSet(); var parsed = src.ParseAsJson(); + + // unique な extension 名を収集 + var used = new HashSet(); foreach (var path in TraverseJsonPath(parsed, null)) { - if (path.Length >= 2) + if (TryGetExtensionName(path, out string extensionName)) { - if (path[path.Length - 2] is string x) - { - if (x == "extensions") - { - used.Add(path[path.Length - 1] as string); - } - } + used.Add(extensionName); } } From 266218633650e501b69d5ae9d49a7cb9a38f168e Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 18:42:34 +0900 Subject: [PATCH 5/8] =?UTF-8?q?replace=20=E3=81=AE=E3=83=AD=E3=82=B8?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=82=92=20JsonNode=20=E3=81=AE=E3=83=90?= =?UTF-8?q?=E3=82=A4=E3=83=88=E7=AF=84=E5=9B=B2=E3=81=AE=E7=BD=AE=E3=81=8D?= =?UTF-8?q?=E6=8F=9B=E3=81=88=E3=81=AB=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/IO/GltfJsonUtil.cs | 59 ++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs index 341a5bab9..eecdc8a86 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Text; using System.Text.RegularExpressions; using UniJSON; using UnityEngine; @@ -9,6 +11,8 @@ namespace UniGLTF { public static class GltfJsonUtil { + const string EXTENSION_USED_KEY = "extensionUsed"; + /// /// JsonPath を 再帰的に列挙する /// object[] の中身は int(array index) or string(object key) @@ -119,18 +123,57 @@ namespace UniGLTF } } - var values = "\"extensionUsed\":[" + string.Join(",", used.Select(x => DoubleQuote(x))) + "]"; - Debug.Log(values); - if (parsed.ContainsKey("extensionUsed")) + if (used.Count == 0) { - // replace - src = Regex.Replace(src, @"""extensionUsed""\s*:\s*\[[^\]]+\]", values); + // 無いとき + if (parsed.ContainsKey(EXTENSION_USED_KEY)) + { + // 消す + throw new NotImplementedException(); + } + else + { + // OK + } } else { - // add - var close = src.LastIndexOf("}"); - src = src.Substring(0, close) + "," + values + "}"; + if (parsed.ContainsKey(EXTENSION_USED_KEY)) + { + var values = "[" + string.Join(",", used.Select(x => DoubleQuote(x))) + "]"; + // Debug.Log($"replace: {values}"); + // replace + var node = parsed[EXTENSION_USED_KEY]; + + var segment = node.Value.Segment.Bytes; + // arraySegment.Array に JSON 全体 + // arraySegment.Offset~Count に extensionUsed 値が入っている + + // BOM 無し encoder + var utf8 = new UTF8Encoding(false); + var bytes = utf8.GetBytes(values); + + using (var w = new MemoryStream()) + { + // before + w.Write(segment.Array, 0, segment.Offset); + // replace + w.Write(bytes, 0, bytes.Length); + // after + var after = segment.Offset + segment.Count; + w.Write(segment.Array, after, segment.Array.Length - after); + + src = utf8.GetString(w.ToArray()); + } + } + else + { + var values = "\"" + EXTENSION_USED_KEY + "\":[" + string.Join(",", used.Select(x => DoubleQuote(x))) + "]"; + // Debug.Log($"add: {values}"); + // add + var close = src.LastIndexOf("}"); + src = src.Substring(0, close) + "," + values + "}"; + } } return src; From 500b59d2aee5b36211bec9145ade3f2550367a32 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 18:45:16 +0900 Subject: [PATCH 6/8] =?UTF-8?q?Test=20=E8=BF=BD=E5=8A=A0=E3=80=82Empty=5Fe?= =?UTF-8?q?xtensionUsed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/IO/GltfJsonUtil.cs | 1 - .../Tests/UniGLTF/GltfJsonUtilTests.cs | 39 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs index eecdc8a86..d3bc1696c 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using System.Text.RegularExpressions; using UniJSON; using UnityEngine; diff --git a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs index 9c58fd5d0..547c32d56 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs @@ -88,5 +88,42 @@ namespace UniGLTF Assert.AreEqual(new string[] { "KHR_materials_unlit" }, parsed["extensionUsed"].ArrayItems().Select(x => x.GetString()).ToArray()); } + + [Test] + public void Empty_extensionUsed() + { + var dst = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(@"{ + ""asset"": { + ""generator"": ""COLLADA2GLTF"", + ""version"": ""2.0"" + }, + ""scene"": 0, + ""scenes"": [ + { + ""nodes"": [ + 0 + ] } -} \ No newline at end of file + ], + ""extensionUsed"": [""dummy""], + ""materials"": [ + { + ""pbrMetallicRoughness"": { + ""baseColorFactor"": [ + 0.800000011920929, + 0.0, + 0.0, + 1.0 + ], + ""metallicFactor"": 0.0 + }, + ""name"": ""Red"" + } + ] +}"); + + var parsed = dst.ParseAsJson(); + Assert.False(parsed.ContainsKey("extensionUsed")); + } + } +} From 805613b1fe1ff93d9509bb89edb00bb78ddb5722 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 18:57:02 +0900 Subject: [PATCH 7/8] =?UTF-8?q?extensions=20=E3=81=8C=E7=84=A1=E3=81=84?= =?UTF-8?q?=E5=A0=B4=E5=90=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/IO/GltfJsonUtil.cs | 51 +++++++++++++++++-- .../Tests/UniGLTF/GltfJsonUtilTests.cs | 40 ++++++++++++++- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs index d3bc1696c..76f5168fe 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -127,8 +126,52 @@ namespace UniGLTF // 無いとき if (parsed.ContainsKey(EXTENSION_USED_KEY)) { - // 消す - throw new NotImplementedException(); + foreach (var kv in parsed.ObjectItems()) + { + if (kv.Key.GetString() == EXTENSION_USED_KEY) + { + // 削除範囲は + // kv.Key の先頭から kv.Value の後ろ + // kv.Value の次の文字は , か } がありえる。 + var begin = kv.Key.Value.Segment.Bytes.Offset; + var end = kv.Value.Value.Segment.Bytes.Offset + kv.Value.Value.Segment.Bytes.Count; + var array = kv.Key.Value.Segment.Bytes.Array; + for (var i = end; i < array.Length; ++i) + { + if (array[i] == ',') + { + end = i + 1; + break; + } + else if (array[i] == '}') + { + // begin 側の , を探す + for (var j = begin - 1; j >= 0; --j) + { + if (array[j] == ',') + { + begin = j; + break; + } + } + end = i; + break; + } + } + + using (var w = new MemoryStream()) + { + // before + w.Write(array, 0, begin); + // after + w.Write(array, end, array.Length - end); + + // BOM 無し encoder + var utf8 = new UTF8Encoding(false); + src = utf8.GetString(w.ToArray()); + } + } + } } else { @@ -150,8 +193,8 @@ namespace UniGLTF // BOM 無し encoder var utf8 = new UTF8Encoding(false); - var bytes = utf8.GetBytes(values); + var bytes = utf8.GetBytes(values); using (var w = new MemoryStream()) { // before diff --git a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs index 547c32d56..cd806db21 100644 --- a/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs +++ b/Assets/UniGLTF/Tests/UniGLTF/GltfJsonUtilTests.cs @@ -105,7 +105,7 @@ namespace UniGLTF ] } ], - ""extensionUsed"": [""dummy""], + ""extensionUsed"": [""dummy""] , ""materials"": [ { ""pbrMetallicRoughness"": { @@ -125,5 +125,43 @@ namespace UniGLTF var parsed = dst.ParseAsJson(); Assert.False(parsed.ContainsKey("extensionUsed")); } + + [Test] + public void Empty2_extensionUsed() + { + var dst = GltfJsonUtil.FindUsedExtensionsAndUpdateJson(@"{ + ""asset"": { + ""generator"": ""COLLADA2GLTF"", + ""version"": ""2.0"" + }, + ""scene"": 0, + ""scenes"": [ + { + ""nodes"": [ + 0 + ] + } + ], + ""materials"": [ + { + ""pbrMetallicRoughness"": { + ""baseColorFactor"": [ + 0.800000011920929, + 0.0, + 0.0, + 1.0 + ], + ""metallicFactor"": 0.0 + }, + ""name"": ""Red"" + } + ], + ""extensionUsed"": [""dummy""] +}"); + + var parsed = dst.ParseAsJson(); + Assert.False(parsed.ContainsKey("extensionUsed")); + } + } } From fdb4899019f9d177444eba9396fb926cc427074f Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 19:38:43 +0900 Subject: [PATCH 8/8] =?UTF-8?q?JSON=E6=96=87=E5=AD=97=E5=88=97=E3=81=AE?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E6=9B=B8=E3=81=8D=E6=8F=9B=E3=81=88=E3=82=92?= =?UTF-8?q?=E5=9B=9E=E9=81=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Runtime/UniGLTF/IO/GltfJsonUtil.cs | 182 ++++++++---------- 1 file changed, 85 insertions(+), 97 deletions(-) diff --git a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs index 76f5168fe..c96e33e84 100644 --- a/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs +++ b/Assets/UniGLTF/Runtime/UniGLTF/IO/GltfJsonUtil.cs @@ -96,6 +96,84 @@ namespace UniGLTF return false; } + static void CopyJson(IReadOnlyList extensionUsed, JsonFormatter dst, JsonNode src, int level) + { + if (src.IsArray()) + { + dst.BeginList(); + foreach (var v in src.ArrayItems()) + { + CopyJson(extensionUsed, dst, v, level + 1); + } + dst.EndList(); + } + else if (src.IsMap()) + { + if (level == 0) + { + // 最上層だけ extensionsUsed の処理をする + var done = false; + dst.BeginMap(); + foreach (var kv in src.ObjectItems()) + { + var key = kv.Key.GetString(); + if (key == EXTENSION_USED_KEY) + { + if (extensionUsed.Count == 0) + { + // skip + } + else + { + dst.Key(key); + // replace + dst.BeginList(); + foreach (var ex in extensionUsed) + { + dst.Value(ex); + } + dst.EndList(); + // 処理済 + } + done = true; + } + else + { + dst.Key(key); + CopyJson(extensionUsed, dst, kv.Value, level + 1); + } + } + if (!done && level == 0 && extensionUsed.Count > 0) + { + // add + dst.Key(EXTENSION_USED_KEY); + dst.BeginList(); + foreach (var ex in extensionUsed) + { + dst.Value(ex); + } + dst.EndList(); + } + dst.EndMap(); + } + else + { + dst.BeginMap(); + foreach (var kv in src.ObjectItems()) + { + dst.Key(kv.Key.GetUtf8String()); + CopyJson(extensionUsed, dst, kv.Value, level + 1); + } + dst.EndMap(); + } + } + else + { + // leaf + dst.Value(src); + } + } + /// /// https://github.com/KhronosGroup/glTF/blob/main/specification/2.0/schema/glTF.schema.json /// @@ -121,104 +199,14 @@ namespace UniGLTF } } - if (used.Count == 0) - { - // 無いとき - if (parsed.ContainsKey(EXTENSION_USED_KEY)) - { - foreach (var kv in parsed.ObjectItems()) - { - if (kv.Key.GetString() == EXTENSION_USED_KEY) - { - // 削除範囲は - // kv.Key の先頭から kv.Value の後ろ - // kv.Value の次の文字は , か } がありえる。 - var begin = kv.Key.Value.Segment.Bytes.Offset; - var end = kv.Value.Value.Segment.Bytes.Offset + kv.Value.Value.Segment.Bytes.Count; - var array = kv.Key.Value.Segment.Bytes.Array; - for (var i = end; i < array.Length; ++i) - { - if (array[i] == ',') - { - end = i + 1; - break; - } - else if (array[i] == '}') - { - // begin 側の , を探す - for (var j = begin - 1; j >= 0; --j) - { - if (array[j] == ',') - { - begin = j; - break; - } - } - end = i; - break; - } - } + // json 加工 + var f = new JsonFormatter(); + CopyJson(used.ToArray(), f, parsed, 0); - using (var w = new MemoryStream()) - { - // before - w.Write(array, 0, begin); - // after - w.Write(array, end, array.Length - end); - - // BOM 無し encoder - var utf8 = new UTF8Encoding(false); - src = utf8.GetString(w.ToArray()); - } - } - } - } - else - { - // OK - } - } - else - { - if (parsed.ContainsKey(EXTENSION_USED_KEY)) - { - var values = "[" + string.Join(",", used.Select(x => DoubleQuote(x))) + "]"; - // Debug.Log($"replace: {values}"); - // replace - var node = parsed[EXTENSION_USED_KEY]; - - var segment = node.Value.Segment.Bytes; - // arraySegment.Array に JSON 全体 - // arraySegment.Offset~Count に extensionUsed 値が入っている - - // BOM 無し encoder - var utf8 = new UTF8Encoding(false); - - var bytes = utf8.GetBytes(values); - using (var w = new MemoryStream()) - { - // before - w.Write(segment.Array, 0, segment.Offset); - // replace - w.Write(bytes, 0, bytes.Length); - // after - var after = segment.Offset + segment.Count; - w.Write(segment.Array, after, segment.Array.Length - after); - - src = utf8.GetString(w.ToArray()); - } - } - else - { - var values = "\"" + EXTENSION_USED_KEY + "\":[" + string.Join(",", used.Select(x => DoubleQuote(x))) + "]"; - // Debug.Log($"add: {values}"); - // add - var close = src.LastIndexOf("}"); - src = src.Substring(0, close) + "," + values + "}"; - } - } - - return src; + // bom無しutf8 + var bytes = f.GetStoreBytes(); + var utf8 = new UTF8Encoding(false); + return utf8.GetString(bytes.Array, bytes.Offset, bytes.Count); } } }