From 659bbd43f4aa263bdfe895aa3dee7467445af945 Mon Sep 17 00:00:00 2001 From: ousttrue Date: Thu, 16 Dec 2021 16:20:59 +0900 Subject: [PATCH] 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