소스 검색

Code Generation project was becoming too bloated. I've splitted it in logical units, and separated extension builders into its own libraries. Hopefully, this would make adding more extensions easier.

Vicente Penades Armengot 8 달 전
부모
커밋
f185be798d
79개의 변경된 파일3149개의 추가작업 그리고 2860개의 파일을 삭제
  1. 28 0
      SharpGLTF.sln
  2. 92 92
      build/SharpGLTF.CodeGen.Core/CodeGen/CodeEmitUtils.cs
  3. 842 842
      build/SharpGLTF.CodeGen.Core/CodeGen/EmitCSharp.cs
  4. 88 0
      build/SharpGLTF.CodeGen.Core/Constants.cs
  5. 137 137
      build/SharpGLTF.CodeGen.Core/MainSchemaProcessor.cs
  6. 38 38
      build/SharpGLTF.CodeGen.Core/SchemaDownload.cs
  7. 119 119
      build/SharpGLTF.CodeGen.Core/SchemaProcessing.cs
  8. 15 15
      build/SharpGLTF.CodeGen.Core/SchemaProcessor.cs
  9. 460 460
      build/SharpGLTF.CodeGen.Core/SchemaReflection/SchemaTypes.cs
  10. 112 112
      build/SharpGLTF.CodeGen.Core/SchemaReflection/SchemaTypesContext.cs
  11. 299 299
      build/SharpGLTF.CodeGen.Core/SchemaReflection/SchemaTypesReader.cs
  12. 14 0
      build/SharpGLTF.CodeGen.Core/SharpGLTF.CodeGen.Core.csproj
  13. 52 0
      build/SharpGLTF.CodeGen.Extensions.AGI/AgiExtensions.cs
  14. 54 54
      build/SharpGLTF.CodeGen.Extensions.AGI/Ext.AGI_Articulations.cs
  15. 40 40
      build/SharpGLTF.CodeGen.Extensions.AGI/Ext.AGI_RootStkMetadata.cs
  16. 12 0
      build/SharpGLTF.CodeGen.Extensions.AGI/SharpGLTF.CodeGen.Extensions.AGI.csproj
  17. 81 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/CesiumExtensions.cs
  18. 3 3
      build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.CESIUM_primitive_outline.cs
  19. 4 4
      build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.EXT_InstanceFeatures.cs
  20. 5 5
      build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.EXT_MeshFeatures.cs
  21. 21 21
      build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.EXT_Structural_Metadata.cs
  22. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/README.md
  23. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/schema/featureId.schema.json
  24. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/schema/featureIdAttribute.schema.json
  25. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/schema/node.EXT_instance_features.schema.json
  26. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/README.md
  27. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/featureId.schema.json
  28. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/featureIdAttribute.schema.json
  29. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/featureIdTexture.schema.json
  30. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/mesh.primitive.EXT_mesh_features.schema.json
  31. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/README.md
  32. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-attribute.png
  33. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-attribute.svg
  34. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-table.png
  35. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-table.svg
  36. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-texture.png
  37. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-texture.svg
  38. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/EXT_structural_metadata.schema.json
  39. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/class.property.schema.json
  40. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/class.schema.json
  41. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/definitions.schema.json
  42. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/enum.schema.json
  43. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/enum.value.schema.json
  44. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/glTF.EXT_structural_metadata.schema.json
  45. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/mesh.primitive.EXT_structural_metadata.schema.json
  46. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyAttribute.property.schema.json
  47. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyAttribute.schema.json
  48. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTable.property.schema.json
  49. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTable.schema.json
  50. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTexture.property.schema.json
  51. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTexture.schema.json
  52. 0 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/schema.schema.json
  53. 17 0
      build/SharpGLTF.CodeGen.Extensions.Cesium/SharpGLTF.CodeGen.Extensions.Cesium.csproj
  54. 1 64
      build/SharpGLTF.CodeGen/Constants.cs
  55. 5 43
      build/SharpGLTF.CodeGen/Program.cs
  56. 10 8
      build/SharpGLTF.CodeGen/SharpGLTF.CodeGen.csproj
  57. 24 24
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.EXT_MeshGpuInstancing.cs
  58. 24 24
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.EXT_TextureWebp.cs
  59. 1 1
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_AnimPointer.cs
  60. 1 1
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Anisotropy.cs
  61. 27 27
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_ClearCoat.cs
  62. 1 1
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_DiffuseTransmission.cs
  63. 1 1
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Dispersion.cs
  64. 30 30
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_EmissiveStrength.cs
  65. 27 27
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_IOR.cs
  66. 29 29
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Iridescence.cs
  67. 53 53
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_LightsPunctual.cs
  68. 38 38
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Sheen.cs
  69. 33 33
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Specular.cs
  70. 36 36
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_SpecularGlossiness.cs
  71. 27 27
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_TextureBasisU.cs
  72. 39 39
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_TextureTransform.cs
  73. 27 27
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Transmission.cs
  74. 27 27
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Unlit.cs
  75. 33 33
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Volume.cs
  76. 2 2
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_XmpJsonLD.cs
  77. 24 24
      build/SharpGLTF.codeGen.Extensions.Khronos/Ext.MSFT_TextureDDS.cs
  78. 84 0
      build/SharpGLTF.codeGen.Extensions.Khronos/KhronosExtensions.cs
  79. 12 0
      build/SharpGLTF.codeGen.Extensions.Khronos/SharpGLTF.codeGen.Extensions.Khronos.csproj

+ 28 - 0
SharpGLTF.sln

@@ -79,6 +79,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGLTF.Ext.Agi", "src\Sh
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharpGLTF.Ext.3DTiles.Tests", "tests\SharpGLTF.Ext.3DTiles.Tests\SharpGLTF.Ext.3DTiles.Tests.csproj", "{373DF570-9782-419E-9AED-04BF2F1B2D89}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGLTF.CodeGen.Core", "build\SharpGLTF.CodeGen.Core\SharpGLTF.CodeGen.Core.csproj", "{35553DE5-C37C-431A-B6E9-A72D84AABDB9}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGLTF.codeGen.Extensions.Khronos", "build\SharpGLTF.codeGen.Extensions.Khronos\SharpGLTF.codeGen.Extensions.Khronos.csproj", "{688D381F-262F-48CF-B3B7-10EC757C3854}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGLTF.CodeGen.Extensions.AGI", "build\SharpGLTF.CodeGen.Extensions.AGI\SharpGLTF.CodeGen.Extensions.AGI.csproj", "{9F601A55-5AD0-4323-824F-AF7AC4ABEA7F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpGLTF.CodeGen.Extensions.Cesium", "build\SharpGLTF.CodeGen.Extensions.Cesium\SharpGLTF.CodeGen.Extensions.Cesium.csproj", "{93100BDB-1DDF-42B9-8C0D-816A0306A5EE}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -161,6 +169,22 @@ Global
 		{373DF570-9782-419E-9AED-04BF2F1B2D89}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{373DF570-9782-419E-9AED-04BF2F1B2D89}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{373DF570-9782-419E-9AED-04BF2F1B2D89}.Release|Any CPU.Build.0 = Release|Any CPU
+		{35553DE5-C37C-431A-B6E9-A72D84AABDB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{35553DE5-C37C-431A-B6E9-A72D84AABDB9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{35553DE5-C37C-431A-B6E9-A72D84AABDB9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{35553DE5-C37C-431A-B6E9-A72D84AABDB9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{688D381F-262F-48CF-B3B7-10EC757C3854}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{688D381F-262F-48CF-B3B7-10EC757C3854}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{688D381F-262F-48CF-B3B7-10EC757C3854}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{688D381F-262F-48CF-B3B7-10EC757C3854}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9F601A55-5AD0-4323-824F-AF7AC4ABEA7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9F601A55-5AD0-4323-824F-AF7AC4ABEA7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9F601A55-5AD0-4323-824F-AF7AC4ABEA7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9F601A55-5AD0-4323-824F-AF7AC4ABEA7F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{93100BDB-1DDF-42B9-8C0D-816A0306A5EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{93100BDB-1DDF-42B9-8C0D-816A0306A5EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{93100BDB-1DDF-42B9-8C0D-816A0306A5EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{93100BDB-1DDF-42B9-8C0D-816A0306A5EE}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -185,6 +209,10 @@ Global
 		{F98E7E4B-EF27-48A0-BA56-730F14CEEEE1} = {072B725F-773F-4751-9616-E9778897C1D2}
 		{6AB07AED-3DCE-422D-BE87-9379806F685C} = {072B725F-773F-4751-9616-E9778897C1D2}
 		{373DF570-9782-419E-9AED-04BF2F1B2D89} = {0CBF510D-D836-40BA-95EC-E93FDBB90632}
+		{35553DE5-C37C-431A-B6E9-A72D84AABDB9} = {D7D51F42-D08C-4DDA-88DA-AF008F10B644}
+		{688D381F-262F-48CF-B3B7-10EC757C3854} = {D7D51F42-D08C-4DDA-88DA-AF008F10B644}
+		{9F601A55-5AD0-4323-824F-AF7AC4ABEA7F} = {D7D51F42-D08C-4DDA-88DA-AF008F10B644}
+		{93100BDB-1DDF-42B9-8C0D-816A0306A5EE} = {D7D51F42-D08C-4DDA-88DA-AF008F10B644}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {1D7BBAD9-834C-4981-AC96-0AA5226FC43F}

+ 92 - 92
build/SharpGLTF.CodeGen/CodeGen/CodeEmitUtils.cs → build/SharpGLTF.CodeGen.Core/CodeGen/CodeEmitUtils.cs

@@ -1,92 +1,92 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace SharpGLTF.CodeGen
-{
-    /// <summary>
-    /// Text processing extensions to facilitate source code emission.
-    /// </summary>
-    static class CodeEmitUtils
-    {
-        public static string Indent(this string text, int indent)
-        {
-            while (indent > 0) { text = $"\t{text}"; --indent; }
-
-            return text;
-        }
-
-        public static void EmitLine(this StringBuilder sb, int indent, string text)
-        {
-            text = text.Indent(indent);
-            sb.AppendLine(text);
-        }
-
-        public static void EmitBlock(this StringBuilder sb, int indent, string body)
-        {
-            sb.EmitLine(indent, "{");
-
-            var lines = body.Split(new[] { "\r\n", "\r", "\n" },StringSplitOptions.None);
-
-            foreach (var line in lines)
-            {
-                sb.EmitLine(indent + 1, line);
-            }
-
-            sb.EmitLine(indent, "}");
-        }
-
-        public static IEnumerable<string> AsCodeBlock(this IEnumerable<string> lines)
-        {
-            yield return "{";
-
-            foreach (var l in lines) yield return $"\t{l}";
-
-            yield return "}";
-        }
-        
-        public static IEnumerable<string> Indent(this IEnumerable<string> lines, int indent)
-        {
-            foreach (var l in lines) yield return l.Indent(indent);            
-        }
-        
-        public static IEnumerable<string> EmitSummary(this string description, int indent)
-        {
-            if (string.IsNullOrWhiteSpace(description)) yield break;
-
-            description = _ReplaceDescriptionKeywords(description);
-
-            var lines = description
-                .Split("  ")
-                .Select(item => item.Trim())
-                .ToList();
-
-            yield return "/// <summary>".Indent(indent);
-            foreach(var l in lines) yield return $"/// {l}";
-            yield return "/// </summary>".Indent(indent);
-        }
-
-        private static string _ReplaceDescriptionKeywords(string description)
-        {
-            while(true)
-            {
-                var (start, len) = _FindDescriptionKeyword(description);
-                if (start < 0) return description;
-
-                var block = description.Substring(start , len);
-                var name = block.Substring(2, block.Length - 4);
-
-                description = description.Replace(block, $"<see cref=\"{name}\"/>", StringComparison.Ordinal);
-            }
-        }
-
-        private static (int start,int len) _FindDescriptionKeyword(string description)
-        {
-            int start = description.IndexOf("`\"");
-            var end = description.IndexOf("\"`");
-            if (start < 0 || end < 0 || start >= end) return (-1, -1);
-            return (start, end - start + 2);
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace SharpGLTF.CodeGen
+{
+    /// <summary>
+    /// Text processing extensions to facilitate source code emission.
+    /// </summary>
+    static class CodeEmitUtils
+    {
+        public static string Indent(this string text, int indent)
+        {
+            while (indent > 0) { text = $"\t{text}"; --indent; }
+
+            return text;
+        }
+
+        public static void EmitLine(this StringBuilder sb, int indent, string text)
+        {
+            text = text.Indent(indent);
+            sb.AppendLine(text);
+        }
+
+        public static void EmitBlock(this StringBuilder sb, int indent, string body)
+        {
+            sb.EmitLine(indent, "{");
+
+            var lines = body.Split(new[] { "\r\n", "\r", "\n" },StringSplitOptions.None);
+
+            foreach (var line in lines)
+            {
+                sb.EmitLine(indent + 1, line);
+            }
+
+            sb.EmitLine(indent, "}");
+        }
+
+        public static IEnumerable<string> AsCodeBlock(this IEnumerable<string> lines)
+        {
+            yield return "{";
+
+            foreach (var l in lines) yield return $"\t{l}";
+
+            yield return "}";
+        }
+        
+        public static IEnumerable<string> Indent(this IEnumerable<string> lines, int indent)
+        {
+            foreach (var l in lines) yield return l.Indent(indent);            
+        }
+        
+        public static IEnumerable<string> EmitSummary(this string description, int indent)
+        {
+            if (string.IsNullOrWhiteSpace(description)) yield break;
+
+            description = _ReplaceDescriptionKeywords(description);
+
+            var lines = description
+                .Split("  ")
+                .Select(item => item.Trim())
+                .ToList();
+
+            yield return "/// <summary>".Indent(indent);
+            foreach(var l in lines) yield return $"/// {l}";
+            yield return "/// </summary>".Indent(indent);
+        }
+
+        private static string _ReplaceDescriptionKeywords(string description)
+        {
+            while(true)
+            {
+                var (start, len) = _FindDescriptionKeyword(description);
+                if (start < 0) return description;
+
+                var block = description.Substring(start , len);
+                var name = block.Substring(2, block.Length - 4);
+
+                description = description.Replace(block, $"<see cref=\"{name}\"/>", StringComparison.Ordinal);
+            }
+        }
+
+        private static (int start,int len) _FindDescriptionKeyword(string description)
+        {
+            int start = description.IndexOf("`\"");
+            var end = description.IndexOf("\"`");
+            if (start < 0 || end < 0 || start >= end) return (-1, -1);
+            return (start, end - start + 2);
+        }
+    }
+}

+ 842 - 842
build/SharpGLTF.CodeGen/CodeGen/EmitCSharp.cs → build/SharpGLTF.CodeGen.Core/CodeGen/EmitCSharp.cs

@@ -1,842 +1,842 @@
-// #define USENEWTONSOFT
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-
-using static System.FormattableString;
-
-namespace SharpGLTF.CodeGen
-{
-    using SchemaReflection;
-
-    /// <summary>
-    /// Takes a <see cref="SchemaReflection.SchemaType.Context"/> and emits
-    /// all its enums and classes as c# source code
-    /// </summary>
-    class CSharpEmitter
-    {
-        #region runtime types
-
-        class _RuntimeType
-        {
-            internal _RuntimeType(SchemaType t) { _PersistentType = t; }
-
-            private readonly SchemaType _PersistentType;
-
-            public string RuntimeNamespace { get; set; }
-
-            public string RuntimeName { get; set; }
-
-            public List<string> Comments { get; } = new List<string>();
-
-            private readonly Dictionary<string, _RuntimeField> _Fields = new Dictionary<string, _RuntimeField>();
-            private readonly Dictionary<string, _RuntimeEnum> _Enums = new Dictionary<string, _RuntimeEnum>();            
-
-            public _RuntimeField UseField(FieldInfo finfo)
-            {
-                var key = $"{finfo.PersistentName}";
-
-                if (_Fields.TryGetValue(key, out _RuntimeField rfield)) return rfield;
-
-                rfield = new _RuntimeField(finfo);
-
-                _Fields[key] = rfield;
-
-                return rfield;
-            }
-
-            public _RuntimeEnum UseEnum(string name)
-            {
-                var key = name;
-
-                if (_Enums.TryGetValue(key, out _RuntimeEnum renum)) return renum;
-
-                renum = new _RuntimeEnum(name);
-
-                _Enums[key] = renum;
-
-                return renum;
-            }
-        }
-
-        class _RuntimeEnum
-        {
-            internal _RuntimeEnum(string name) { _Name = name; }
-
-            private readonly string _Name;
-        }
-
-        class _RuntimeField
-        {
-            internal _RuntimeField(FieldInfo f) { _PersistentField = f; }
-
-            private readonly FieldInfo _PersistentField;
-
-            public string PrivateField { get; set; }
-            public string PublicProperty { get; set; }
-
-            public string CollectionContainer { get; set; }
-            public string DictionaryContainer { get; set; }
-
-            // MinVal, MaxVal, readonly, static
-
-            // serialization sections
-            // deserialization sections
-            // validation sections
-            // clone sections
-        }        
-
-        private readonly Dictionary<string, _RuntimeType> _Types = new Dictionary<string, _RuntimeType>();
-
-        private string _DefaultCollectionContainer = "TItem[]";
-
-        #endregion
-
-        #region setup & declaration        
-
-        private static string _SanitizeName(string name)
-        {
-            return name.Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase);
-        }
-
-        private _RuntimeType _UseType(SchemaType stype)
-        {
-            var key = $"{stype.PersistentName}";
-
-            if (_Types.TryGetValue(key, out _RuntimeType rtype)) return rtype;
-
-            rtype = new _RuntimeType(stype)
-            {
-                RuntimeName = _SanitizeName(stype.PersistentName)
-            };
-
-            _Types[key] = rtype;
-
-            return rtype;
-        }
-
-        private bool _TryGetType(SchemaType stype, out _RuntimeType rtype)
-        {
-            var key = $"{stype.PersistentName}";
-
-            return _Types.TryGetValue(key, out rtype);
-        }
-
-        private _RuntimeField _UseField(FieldInfo finfo) { return _UseType(finfo.DeclaringClass).UseField(finfo); }
-
-        public void SetRuntimeName(SchemaType stype, string newName, string runtimeNamespace = null)
-        {
-            var t = _UseType(stype);
-
-            t.RuntimeNamespace = runtimeNamespace;
-            t.RuntimeName = newName;
-        }
-
-        public void AddRuntimeComment(string persistentName, string comment)
-        {
-            if (!_Types.TryGetValue(persistentName, out _RuntimeType t)) return;
-
-            t.Comments.Add(comment);           
-        }
-
-        public IReadOnlyList<string> GetRuntimeComments(SchemaType cls)
-        {
-            return !_TryGetType(cls, out var rtype)
-                ? Array.Empty<string>()
-                : (IReadOnlyList<string>)rtype.Comments;
-        }
-
-        public void SetRuntimeName(string persistentName, string runtimeName, string runtimeNamespace = null)
-        {
-            if (!_Types.TryGetValue(persistentName, out _RuntimeType t)) return;
-
-            t.RuntimeNamespace = runtimeNamespace;
-            t.RuntimeName = runtimeName;
-        }
-
-        public string GetRuntimeName(string persistentName)
-        {
-            return _Types[persistentName].RuntimeName;
-        }
-
-        public string GetRuntimeNamespace(string persistentName)
-        {
-            return _Types[persistentName].RuntimeNamespace ?? Constants.OutputNamespace;
-        }
-
-        public void SetFieldName(FieldInfo finfo, string name) { _UseField(finfo).PrivateField = name; }
-
-        public string GetFieldRuntimeName(FieldInfo finfo) { return _UseField(finfo).PrivateField; }
-
-        public void SetPropertyName(FieldInfo finfo, string name) { _UseField(finfo).PublicProperty = name; }
-
-        public string GetPropertyName(FieldInfo finfo) { return _UseField(finfo).PublicProperty; }
-
-
-
-        public void SetCollectionContainer(string container) { _DefaultCollectionContainer = container; }
-
-        public void SetCollectionContainer(FieldInfo finfo, string container) { _UseField(finfo).CollectionContainer = container; }        
-
-        public void SetFieldToChildrenList(SchemaType.Context ctx, string persistentName, string fieldName)
-        {
-            var classType = ctx.FindClass(persistentName);
-            if (classType == null) return;
-            var field = classType.UseField(fieldName);
-            var runtimeName = this.GetRuntimeName(persistentName);
-            this.SetCollectionContainer(field, $"ChildrenList<TItem,{runtimeName}>");
-        }
-
-        public void SetFieldToChildrenDictionary(SchemaType.Context ctx, string persistentName, string fieldName)
-        {
-            var classType = ctx.FindClass(persistentName);
-            if (classType == null) return;
-            var field = classType.UseField(fieldName);
-            var runtimeName = this.GetRuntimeName(persistentName);
-            this.SetCollectionContainer(field, $"ChildrenDictionary<TItem,{runtimeName}>");
-        }
-
-        public void DeclareClass(ClassType type)
-        {
-            _UseType(type);
-
-            foreach(var f in type.Fields)
-            {
-                var runtimeName = _SanitizeName(f.PersistentName).Replace("@","at", StringComparison.Ordinal);
-
-                SetFieldName(f, $"_{runtimeName}");
-                SetPropertyName(f, runtimeName);
-            }
-        }
-
-        public void DeclareEnum(EnumType type)
-        {
-            _UseType(type);
-
-            foreach (var f in type.Values)
-            {
-                // SetFieldName(f, $"_{runtimeName}");
-                // SetPropertyName(f, runtimeName);
-            }
-        }
-
-        public void DeclareContext(SchemaType.Context context)
-        {
-            foreach(var ctype in context.Classes)
-            {
-                DeclareClass(ctype);
-            }
-
-            foreach (var etype in context.Enumerations)
-            {
-                DeclareEnum(etype);
-            }
-        }
-
-        internal string _GetRuntimeName(SchemaType type) { return _GetRuntimeName(type, null); }
-
-        private string _GetRuntimeName(SchemaType type, _RuntimeField extra)
-        {
-            switch (type)
-            {
-                case null: throw new ArgumentNullException(nameof(type));
-
-                case ObjectType anyType: return anyType.PersistentName;
-
-                case StringType strType: return strType.PersistentName;
-
-                case BlittableType blitType:
-                    {
-                        var tname = blitType.DataType.Name;
-
-                        return blitType.IsNullable ? $"{tname}?" : tname;
-                    }
-
-                case ArrayType arrayType:
-                    {
-                        var container = extra?.CollectionContainer;
-                        if (string.IsNullOrWhiteSpace(container)) container = _DefaultCollectionContainer;
-
-                        return container.Replace("TItem", _GetRuntimeName(arrayType.ItemType), StringComparison.Ordinal);
-                    }
-
-                case DictionaryType dictType:
-                    {
-                        var key = _GetRuntimeName(dictType.KeyType);
-                        var val = _GetRuntimeName(dictType.ValueType);
-
-                        var container = extra?.CollectionContainer ?? string.Empty;
-
-                        if (container.StartsWith("ChildrenDictionary<"))
-                        {
-                            if (key == "String") return container.Replace("TItem", val, StringComparison.Ordinal);
-                        }
-
-                        return $"Dictionary<{key},{val}>";
-                    }
-
-                case EnumType enumType: return _UseType(enumType).RuntimeName;
-
-                case ClassType classType: return _UseType(classType).RuntimeName;
-
-                default: throw new NotImplementedException(type.PersistentName);
-            }
-        }
-
-        private string _GetConstantRuntimeName(SchemaType type)
-        {
-            switch (type)
-            {
-                case StringType strType: return $"const {typeof(string).Name}";
-
-                case BlittableType blitType:
-                    {
-                        var tname = blitType.DataType.Name;
-
-                        if (blitType.DataType == typeof(int)) return $"const {tname}";
-                        if (blitType.DataType == typeof(float)) return $"const {tname}";
-                        if (blitType.DataType == typeof(double)) return $"const {tname}";
-
-                        return $"static readonly {tname}";
-                    }
-
-                case EnumType enumType: return $"const {_UseType(enumType).RuntimeName}";
-
-                case ArrayType aType: return $"static readonly {_UseType(aType).RuntimeName}";
-
-                default: throw new NotImplementedException();
-            }
-        }
-
-        internal Object _GetConstantRuntimeValue(SchemaType type, Object value)
-        {
-            ArgumentNullException.ThrowIfNull(value);
-
-            switch (type)
-            {
-                case StringType _:
-
-                    return value is string
-                        ? value
-                        : Convert.ChangeType(value, typeof(string), System.Globalization.CultureInfo.InvariantCulture);
-
-                case BlittableType btype:
-                    {
-                        if (btype.DataType == typeof(bool).GetTypeInfo())
-                        {
-                            if (value is bool) return value;
-
-                            var str = value as string;
-
-                            if (str.Equals("FALSE", StringComparison.OrdinalIgnoreCase)) return false;
-                            if (str.Equals("TRUE", StringComparison.OrdinalIgnoreCase)) return true;
-                            throw new NotImplementedException();
-                        }
-
-                        return value is string
-                            ? value
-                            : Convert.ChangeType(value, btype.DataType.AsType(), System.Globalization.CultureInfo.InvariantCulture);
-                    }
-
-                case EnumType etype:
-                    {
-                        var etypeName = _GetRuntimeName(type);
-
-                        if (value is string) return $"{etypeName}.{value}";
-                        else return $"({etypeName}){value}";
-                    }
-
-                case ArrayType aType:
-                    {
-                        var atypeName = _GetRuntimeName(type);
-
-                        return value.ToString();
-                    }
-
-                default: throw new NotImplementedException();
-            }
-        }        
-
-        #endregion
-
-        #region emit
-
-        public string EmitContext(SchemaType.Context context)
-        {
-            var sb = new StringBuilder();
-
-            sb.AppendLine("// <auto-generated/>");
-            sb.AppendLine();
-
-            sb.AppendLine("//------------------------------------------------------------------------------------------------");
-            sb.AppendLine("//      This file has been programatically generated; DON´T EDIT!");
-            sb.AppendLine("//------------------------------------------------------------------------------------------------");
-
-            sb.AppendLine();            
-            
-            sb.AppendLine("#pragma warning disable SA1001");
-            sb.AppendLine("#pragma warning disable SA1027");
-            sb.AppendLine("#pragma warning disable SA1028");
-            sb.AppendLine("#pragma warning disable SA1121");
-            sb.AppendLine("#pragma warning disable SA1205");
-            sb.AppendLine("#pragma warning disable SA1309");
-            sb.AppendLine("#pragma warning disable SA1402");
-            sb.AppendLine("#pragma warning disable SA1505");
-            sb.AppendLine("#pragma warning disable SA1507");
-            sb.AppendLine("#pragma warning disable SA1508");
-            sb.AppendLine("#pragma warning disable SA1652");
-
-            sb.AppendLine();
-
-            sb.AppendLine("using System;");
-            sb.AppendLine("using System.Collections.Generic;");
-            sb.AppendLine("using System.Linq;");
-            sb.AppendLine("using System.Text;");
-            sb.AppendLine("using System.Numerics;");
-            sb.AppendLine("using System.Text.Json;");
-
-            sb.AppendLine();
-
-            sb.AppendLine("using JSONREADER = System.Text.Json.Utf8JsonReader;");
-            sb.AppendLine("using JSONWRITER = System.Text.Json.Utf8JsonWriter;");
-            sb.AppendLine("using FIELDINFO = SharpGLTF.Reflection.FieldInfo;");
-
-            sb.AppendLine();
-
-            string currentNamespace = null;
-
-            void _setCurrentNamespace(string ns)
-            {
-                if (currentNamespace == ns) return;
-                if (currentNamespace != null) sb.AppendLine("}");
-                currentNamespace = ns;
-                if (currentNamespace != null)
-                {
-                    sb.AppendLine();
-                    sb.AppendLine($"namespace {currentNamespace}");
-                    sb.AppendLine("{");
-
-                    sb.AppendLine("using Collections;".Indent(1));
-                    sb.AppendLine();
-                }
-            }            
-
-            foreach (var etype in context.Enumerations)
-            {
-                _setCurrentNamespace(GetRuntimeNamespace(etype.PersistentName));
-
-                var cout = EmitEnum(etype);
-
-                sb.AppendLine(cout);
-                sb.AppendLine();
-            }
-
-            foreach (var ctype in context.Classes)
-            {
-                if (ctype.IgnoredByEmitter) continue;
-
-                _setCurrentNamespace(GetRuntimeNamespace(ctype.PersistentName));
-
-                var cout = EmitClass(ctype);
-
-                sb.AppendLine(cout);
-                sb.AppendLine();
-            }
-
-            _setCurrentNamespace(null);
-
-            return sb.ToString();
-        }
-
-        public string EmitEnum(EnumType type)
-        {
-            var sb = new StringBuilder();
-
-            foreach (var l in type.Description.EmitSummary(0)) sb.EmitLine(1, l);
-
-            sb.EmitLine(1, $"public enum {_GetRuntimeName(type)}");
-            sb.EmitLine(1, "{");
-
-            if (type.UseIntegers)
-            {
-                foreach (var kvp in type.Values)
-                {
-                    var k =  kvp.Key;
-
-                    sb.EmitLine(2, $"{k} = {kvp.Value},");
-                }
-            }
-            else
-            {
-                foreach (var kvp in type.Values)
-                {
-                    var k = kvp.Key;
-
-                    sb.EmitLine(2, $"{k},");
-                }
-            }            
-
-            sb.EmitLine(1, "}");
-
-            return sb.ToString();
-        }
-
-        public string EmitClass(ClassType type)
-        {
-            var xclass = new CSharpClassEmitter(this)
-            {
-                ClassSummary = type.Description,
-                SchemaName = type.ShortIdentifier,
-                ClassDeclaration = _GetClassDeclaration(type),
-                HasBaseClass = type.BaseClass != null
-            };
-
-            xclass.AddComments(type);
-            xclass.AddFields(type);            
-
-            return String.Join("\r\n",xclass.EmitCode().Indent(1));            
-        }
-
-        private string _GetClassDeclaration(ClassType type)
-        {
-            var classDecl = string.Empty;            
-            classDecl += "partial ";
-            classDecl += "class ";
-            classDecl += _GetRuntimeName(type);
-            if (type.BaseClass != null) classDecl += $" : {_GetRuntimeName(type.BaseClass)}";
-            return classDecl;
-        }
-
-        internal IEnumerable<string> _GetClassField(FieldInfo f)
-        {            
-            var tdecl = _GetRuntimeName(f.FieldType, _UseField(f));
-            var fname = GetFieldRuntimeName(f);
-
-            string defval = string.Empty;
-
-            if (f.DefaultValue != null)
-            {
-                var tconst = _GetConstantRuntimeName(f.FieldType);
-                var vconst = _GetConstantRuntimeValue(f.FieldType, f.DefaultValue);
-
-                // fix boolean value
-                if (vconst is Boolean bconst) vconst = bconst ? "true" : "false";
-
-                defval = $"{fname}Default";
-
-                yield return Invariant($"private {tconst} {defval} = {vconst};");
-            }
-
-            if (f.ExclusiveMinimumValue != null)
-            {
-                var tconst = _GetConstantRuntimeName(f.FieldType);
-                var vconst = _GetConstantRuntimeValue(f.FieldType, f.ExclusiveMinimumValue);
-                yield return Invariant($"private {tconst} {fname}ExclusiveMinimum = {vconst};");
-            }
-
-            if (f.InclusiveMinimumValue != null)
-            {
-                var tconst = _GetConstantRuntimeName(f.FieldType);
-                var vconst = _GetConstantRuntimeValue(f.FieldType, f.InclusiveMinimumValue);
-                yield return Invariant($"private {tconst} {fname}Minimum = {vconst};");
-            }
-
-            if (f.InclusiveMaximumValue != null)
-            {
-                var tconst = _GetConstantRuntimeName(f.FieldType);
-                var vconst = _GetConstantRuntimeValue(f.FieldType, f.InclusiveMaximumValue);
-                yield return Invariant($"private {tconst} {fname}Maximum = {vconst};");
-            }
-
-            if (f.ExclusiveMaximumValue != null)
-            {
-                var tconst = _GetConstantRuntimeName(f.FieldType);
-                var vconst = _GetConstantRuntimeValue(f.FieldType, f.ExclusiveMaximumValue);
-                yield return Invariant($"private {tconst} {fname}ExclusiveMaximum = {vconst};");
-            }
-
-            if (f.MinItems > 0)
-            {                    
-                yield return $"private const int {fname}MinItems = {f.MinItems};";
-            }
-
-            if (f.MaxItems > 0 && f.MaxItems < int.MaxValue)
-            {                    
-                yield return $"private const int {fname}MaxItems = {f.MaxItems};";
-            }
-
-            if (f.FieldType is EnumType etype && etype.IsNullable) tdecl = tdecl + "?";            
-
-            yield return string.IsNullOrEmpty(defval) ? $"private {tdecl} {fname};" : $"private {tdecl} {fname} = {defval};";
-
-            yield return string.Empty;
-        }            
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Utility class to emit a <see cref="SchemaReflection.ClassType"/>
-    /// as c# source code
-    /// </summary>
-    class CSharpClassEmitter
-    {
-        #region constructor
-
-        public CSharpClassEmitter(CSharpEmitter emitter)
-        {
-            _Emitter = emitter;
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly CSharpEmitter _Emitter;
-
-        private readonly List<string> _Comments = new List<string>();
-
-        private readonly List<string> _Fields = new List<string>();
-        private readonly List<string> _SerializerBody = new List<string>();
-        private readonly List<string> _DeserializerSwitchBody = new List<string>();
-
-        private readonly List<string> _FieldsNamesReflection = new List<string>();
-        private readonly List<string> _FieldsSwitchReflection = new List<string>();
-
-        public string ClassSummary { get; set; }
-
-        /// <summary>
-        /// The name used in the schema $id field, minus the prefix and suffix
-        /// </summary>
-        public string SchemaName { get; set; }
-
-        /// <summary>
-        /// Represents the Runtime Class Name
-        /// </summary>
-        public string ClassDeclaration { get; set; }
-
-        public bool HasBaseClass { get; set; }
-
-        private const string _READERMODIFIER = "ref ";
-
-        #endregion
-
-        #region API
-
-        public void AddComments(ClassType type)
-        {
-            _Comments.AddRange(_Emitter.GetRuntimeComments(type));
-        }
-
-        public void AddFields(ClassType type)
-        {
-            foreach (var f in type.Fields)
-            {
-                var trname = _Emitter._GetRuntimeName(f.FieldType);
-                var frname = _Emitter.GetFieldRuntimeName(f);
-
-                _Fields.AddRange(_Emitter._GetClassField(f));
-
-                AddFieldReflection(f);
-
-                // serialization
-
-                if (f.FieldType is EnumType etype) // special case for enums
-                {
-                    // emit serializer
-                    var smethod = etype.UseIntegers ? "SerializePropertyEnumValue" : "SerializePropertyEnumSymbol";
-                    smethod = $"{smethod}<{trname}>(writer, \"{f.PersistentName}\", {frname}";
-                    if (f.DefaultValue != null) smethod += $", {frname}Default";
-                    smethod += ");";
-                    this.AddFieldSerializerCase(smethod);
-
-                    // emit deserializer
-                    this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(etype)}>({_READERMODIFIER}reader);");
-
-                    continue;
-                }
-
-                this.AddFieldSerializerCase(_GetJSonSerializerMethod(f));
-                this.AddFieldDeserializerCase(f.PersistentName, _GetJSonDeserializerMethod(f));
-            }
-        }
-
-        private void AddFieldReflection(FieldInfo finfo)
-        {
-            var trname = _Emitter._GetRuntimeName(finfo.FieldType);
-            var frname = _Emitter.GetFieldRuntimeName(finfo);
-
-            trname = trname.Replace("?", ""); // since we're adding the default value, there's no need for nullable values.
-
-            var vtype = $"typeof({trname})";
-            var getter = $"instance => instance.{frname}";            
-
-            if (finfo.DefaultValue != null)
-            {
-                var vconst = _Emitter._GetConstantRuntimeValue(finfo.FieldType, finfo.DefaultValue);
-                // fix boolean value            
-                if (vconst is Boolean bconst) vconst = bconst ? "true" : "false";                
-
-                getter += FormattableString.Invariant($" ?? {vconst}");
-            }
-
-            // _FieldsReflection.Add($"yield return FIELDINFO.From(\"{finfo.PersistentName}\",this, {getter});");
-
-            _FieldsNamesReflection.Add(finfo.PersistentName);
-            _FieldsSwitchReflection.Add($"case \"{finfo.PersistentName}\": value = FIELDINFO.From(\"{finfo.PersistentName}\",this, {getter}); return true;");
-        }
-
-        private string _GetJSonSerializerMethod(FieldInfo f)
-        {
-            var pname = f.PersistentName;
-            var fname = _Emitter.GetFieldRuntimeName(f);
-
-            if (f.FieldType is ClassType ctype)
-            {
-                return $"SerializePropertyObject(writer, \"{pname}\", {fname});";
-            }
-
-            if (f.FieldType is ArrayType atype)
-            {
-                if (f.MinItems > 0) return $"SerializeProperty(writer, \"{pname}\", {fname}, {fname}MinItems);";
-
-                return $"SerializeProperty(writer,\"{pname}\",{fname});";
-            }
-
-            if (f.DefaultValue != null) return $"SerializeProperty(writer, \"{pname}\", {fname}, {fname}Default);";
-
-            return $"SerializeProperty(writer, \"{pname}\", {fname});";
-        }
-
-        private string _GetJSonDeserializerMethod(FieldInfo f)
-        {
-            var fname = _Emitter.GetFieldRuntimeName(f);
-
-            var ownerTypeName = _Emitter._GetRuntimeName(f.DeclaringClass);
-
-            if (f.FieldType is ArrayType atype)
-            {
-                var titem = _Emitter._GetRuntimeName(atype.ItemType);
-                return $"DeserializePropertyList<{ownerTypeName}, {titem}>({_READERMODIFIER}reader, this, {fname});";
-            }
-            else if (f.FieldType is DictionaryType dtype)
-            {
-                var titem = _Emitter._GetRuntimeName(dtype.ValueType);
-                return $"DeserializePropertyDictionary<{ownerTypeName}, {titem}>({_READERMODIFIER}reader, this, {fname});";
-            }
-            
-            var fieldTypeName = _Emitter._GetRuntimeName(f.FieldType);            
-
-            return $"DeserializePropertyValue<{ownerTypeName}, {fieldTypeName}>({_READERMODIFIER}reader, this, out {fname});";
-        }        
-
-        public void AddFieldSerializerCase(string line) { _SerializerBody.Add(line); }
-
-        public void AddFieldDeserializerCase(string persistentName, string line)
-        {
-            _DeserializerSwitchBody.Add($"case \"{persistentName}\": {line} break;");            
-        }
-
-        public IEnumerable<string> EmitCode()
-        {
-            #if USENEWTONSOFT
-            var readerType = "JsonReader";
-            var writerType = "JsonWriter";
-            #else
-            var readerType = "ref JSONREADER";
-            var writerType = "JSONWRITER";
-            #endif
-
-            foreach (var l in _Comments) yield return $"// {l}";
-
-            foreach (var l in ClassSummary.EmitSummary(0)) yield return l;
-
-            yield return "#if NET6_0_OR_GREATER";
-            yield return "[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]";
-            yield return "#endif";
-
-            yield return "[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"SharpGLTF.CodeGen\", \"1.0.0.0\")]";
-
-            yield return ClassDeclaration;
-            yield return "{";
-
-            yield return string.Empty;
-
-            yield return "#region reflection".Indent(1);
-            yield return string.Empty;
-
-            yield return $"public const string SCHEMANAME = \"{SchemaName}\";".Indent(1);
-
-            var pointerPathModifier = HasBaseClass ? "override" : "virtual";
-            yield return $"protected {pointerPathModifier} string GetSchemaName() => SCHEMANAME;".Indent(1);            
-
-            yield return string.Empty;
-
-            yield return $"protected override IEnumerable<string> ReflectFieldsNames()".Indent(1);
-            yield return "{".Indent(1);            
-            foreach (var l in _FieldsNamesReflection) yield return $"yield return \"{l}\";".Indent(2);
-            if (HasBaseClass) yield return "foreach(var f in base.ReflectFieldsNames()) yield return f;".Indent(2);
-            yield return "}".Indent(1);
-
-            yield return $"protected override bool TryReflectField(string name, out FIELDINFO value)".Indent(1);
-            yield return "{".Indent(1);
-            yield return "switch(name)".Indent(2);
-            yield return "{".Indent(2);
-            foreach (var l in _FieldsSwitchReflection.Indent(3)) yield return l;
-            if (HasBaseClass) yield return "default: return base.TryReflectField(name, out value);".Indent(3);            
-            yield return "}".Indent(2);
-            yield return "}".Indent(1);
-
-            yield return string.Empty;
-            yield return "#endregion".Indent(1);
-
-            yield return string.Empty;
-
-            yield return "#region data".Indent(1);
-            yield return string.Empty;
-
-            foreach (var l in _Fields.Indent(1)) yield return l;
-
-            yield return "#endregion".Indent(1);
-
-            yield return string.Empty;
-
-            yield return "#region serialization".Indent(1);
-            yield return string.Empty;
-
-            // yield return "/// <inheritdoc />".Indent(1);
-            yield return $"protected override void SerializeProperties({writerType} writer)".Indent(1);
-            yield return "{".Indent(1);
-            if (HasBaseClass) yield return "base.SerializeProperties(writer);".Indent(2);
-            foreach (var l in _SerializerBody.Indent(2)) yield return l;
-            yield return "}".Indent(1);
-
-            yield return string.Empty;
-
-            // yield return "/// <inheritdoc />".Indent(1);
-            yield return $"protected override void DeserializeProperty(string jsonPropertyName, {readerType} reader)".Indent(1);
-            yield return "{".Indent(1);
-            yield return "switch (jsonPropertyName)".Indent(2);
-            yield return "{".Indent(2);
-
-            foreach (var l in _DeserializerSwitchBody.Indent(3)) yield return l;
-            if (HasBaseClass) yield return $"default: base.DeserializeProperty(jsonPropertyName,{_READERMODIFIER}reader); break;".Indent(3);
-            else yield return "default: throw new NotImplementedException();".Indent(3);
-
-            yield return "}".Indent(2);
-            yield return "}".Indent(1);
-
-            yield return string.Empty;
-            yield return "#endregion".Indent(1);
-
-            yield return string.Empty;            
-
-            yield return "}";
-        }
-
-        #endregion
-    }
-}
+// #define USENEWTONSOFT
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+using static System.FormattableString;
+
+namespace SharpGLTF.CodeGen
+{
+    using SchemaReflection;
+
+    /// <summary>
+    /// Takes a <see cref="SchemaReflection.SchemaType.Context"/> and emits
+    /// all its enums and classes as c# source code
+    /// </summary>
+    public class CSharpEmitter
+    {
+        #region runtime types
+
+        class _RuntimeType
+        {
+            internal _RuntimeType(SchemaType t) { _PersistentType = t; }
+
+            private readonly SchemaType _PersistentType;
+
+            public string RuntimeNamespace { get; set; }
+
+            public string RuntimeName { get; set; }
+
+            public List<string> Comments { get; } = new List<string>();
+
+            private readonly Dictionary<string, _RuntimeField> _Fields = new Dictionary<string, _RuntimeField>();
+            private readonly Dictionary<string, _RuntimeEnum> _Enums = new Dictionary<string, _RuntimeEnum>();            
+
+            public _RuntimeField UseField(FieldInfo finfo)
+            {
+                var key = $"{finfo.PersistentName}";
+
+                if (_Fields.TryGetValue(key, out _RuntimeField rfield)) return rfield;
+
+                rfield = new _RuntimeField(finfo);
+
+                _Fields[key] = rfield;
+
+                return rfield;
+            }
+
+            public _RuntimeEnum UseEnum(string name)
+            {
+                var key = name;
+
+                if (_Enums.TryGetValue(key, out _RuntimeEnum renum)) return renum;
+
+                renum = new _RuntimeEnum(name);
+
+                _Enums[key] = renum;
+
+                return renum;
+            }
+        }
+
+        class _RuntimeEnum
+        {
+            internal _RuntimeEnum(string name) { _Name = name; }
+
+            private readonly string _Name;
+        }
+
+        class _RuntimeField
+        {
+            internal _RuntimeField(FieldInfo f) { _PersistentField = f; }
+
+            private readonly FieldInfo _PersistentField;
+
+            public string PrivateField { get; set; }
+            public string PublicProperty { get; set; }
+
+            public string CollectionContainer { get; set; }
+            public string DictionaryContainer { get; set; }
+
+            // MinVal, MaxVal, readonly, static
+
+            // serialization sections
+            // deserialization sections
+            // validation sections
+            // clone sections
+        }        
+
+        private readonly Dictionary<string, _RuntimeType> _Types = new Dictionary<string, _RuntimeType>();
+
+        private string _DefaultCollectionContainer = "TItem[]";
+
+        #endregion
+
+        #region setup & declaration        
+
+        private static string _SanitizeName(string name)
+        {
+            return name.Replace(" ", string.Empty, StringComparison.OrdinalIgnoreCase);
+        }
+
+        private _RuntimeType _UseType(SchemaType stype)
+        {
+            var key = $"{stype.PersistentName}";
+
+            if (_Types.TryGetValue(key, out _RuntimeType rtype)) return rtype;
+
+            rtype = new _RuntimeType(stype)
+            {
+                RuntimeName = _SanitizeName(stype.PersistentName)
+            };
+
+            _Types[key] = rtype;
+
+            return rtype;
+        }
+
+        private bool _TryGetType(SchemaType stype, out _RuntimeType rtype)
+        {
+            var key = $"{stype.PersistentName}";
+
+            return _Types.TryGetValue(key, out rtype);
+        }
+
+        private _RuntimeField _UseField(FieldInfo finfo) { return _UseType(finfo.DeclaringClass).UseField(finfo); }
+
+        public void SetRuntimeName(SchemaType stype, string newName, string runtimeNamespace = null)
+        {
+            var t = _UseType(stype);
+
+            t.RuntimeNamespace = runtimeNamespace;
+            t.RuntimeName = newName;
+        }
+
+        public void AddRuntimeComment(string persistentName, string comment)
+        {
+            if (!_Types.TryGetValue(persistentName, out _RuntimeType t)) return;
+
+            t.Comments.Add(comment);           
+        }
+
+        public IReadOnlyList<string> GetRuntimeComments(SchemaType cls)
+        {
+            return !_TryGetType(cls, out var rtype)
+                ? Array.Empty<string>()
+                : (IReadOnlyList<string>)rtype.Comments;
+        }
+
+        public void SetRuntimeName(string persistentName, string runtimeName, string runtimeNamespace = null)
+        {
+            if (!_Types.TryGetValue(persistentName, out _RuntimeType t)) return;
+
+            t.RuntimeNamespace = runtimeNamespace;
+            t.RuntimeName = runtimeName;
+        }
+
+        public string GetRuntimeName(string persistentName)
+        {
+            return _Types[persistentName].RuntimeName;
+        }
+
+        public string GetRuntimeNamespace(string persistentName)
+        {
+            return _Types[persistentName].RuntimeNamespace ?? Constants.OutputNamespace;
+        }
+
+        public void SetFieldName(FieldInfo finfo, string name) { _UseField(finfo).PrivateField = name; }
+
+        public string GetFieldRuntimeName(FieldInfo finfo) { return _UseField(finfo).PrivateField; }
+
+        public void SetPropertyName(FieldInfo finfo, string name) { _UseField(finfo).PublicProperty = name; }
+
+        public string GetPropertyName(FieldInfo finfo) { return _UseField(finfo).PublicProperty; }
+
+
+
+        public void SetCollectionContainer(string container) { _DefaultCollectionContainer = container; }
+
+        public void SetCollectionContainer(FieldInfo finfo, string container) { _UseField(finfo).CollectionContainer = container; }        
+
+        public void SetFieldToChildrenList(SchemaType.Context ctx, string persistentName, string fieldName)
+        {
+            var classType = ctx.FindClass(persistentName);
+            if (classType == null) return;
+            var field = classType.UseField(fieldName);
+            var runtimeName = this.GetRuntimeName(persistentName);
+            this.SetCollectionContainer(field, $"ChildrenList<TItem,{runtimeName}>");
+        }
+
+        public void SetFieldToChildrenDictionary(SchemaType.Context ctx, string persistentName, string fieldName)
+        {
+            var classType = ctx.FindClass(persistentName);
+            if (classType == null) return;
+            var field = classType.UseField(fieldName);
+            var runtimeName = this.GetRuntimeName(persistentName);
+            this.SetCollectionContainer(field, $"ChildrenDictionary<TItem,{runtimeName}>");
+        }
+
+        public void DeclareClass(ClassType type)
+        {
+            _UseType(type);
+
+            foreach(var f in type.Fields)
+            {
+                var runtimeName = _SanitizeName(f.PersistentName).Replace("@","at", StringComparison.Ordinal);
+
+                SetFieldName(f, $"_{runtimeName}");
+                SetPropertyName(f, runtimeName);
+            }
+        }
+
+        public void DeclareEnum(EnumType type)
+        {
+            _UseType(type);
+
+            foreach (var f in type.Values)
+            {
+                // SetFieldName(f, $"_{runtimeName}");
+                // SetPropertyName(f, runtimeName);
+            }
+        }
+
+        public void DeclareContext(SchemaType.Context context)
+        {
+            foreach(var ctype in context.Classes)
+            {
+                DeclareClass(ctype);
+            }
+
+            foreach (var etype in context.Enumerations)
+            {
+                DeclareEnum(etype);
+            }
+        }
+
+        internal string _GetRuntimeName(SchemaType type) { return _GetRuntimeName(type, null); }
+
+        private string _GetRuntimeName(SchemaType type, _RuntimeField extra)
+        {
+            switch (type)
+            {
+                case null: throw new ArgumentNullException(nameof(type));
+
+                case ObjectType anyType: return anyType.PersistentName;
+
+                case StringType strType: return strType.PersistentName;
+
+                case BlittableType blitType:
+                    {
+                        var tname = blitType.DataType.Name;
+
+                        return blitType.IsNullable ? $"{tname}?" : tname;
+                    }
+
+                case ArrayType arrayType:
+                    {
+                        var container = extra?.CollectionContainer;
+                        if (string.IsNullOrWhiteSpace(container)) container = _DefaultCollectionContainer;
+
+                        return container.Replace("TItem", _GetRuntimeName(arrayType.ItemType), StringComparison.Ordinal);
+                    }
+
+                case DictionaryType dictType:
+                    {
+                        var key = _GetRuntimeName(dictType.KeyType);
+                        var val = _GetRuntimeName(dictType.ValueType);
+
+                        var container = extra?.CollectionContainer ?? string.Empty;
+
+                        if (container.StartsWith("ChildrenDictionary<"))
+                        {
+                            if (key == "String") return container.Replace("TItem", val, StringComparison.Ordinal);
+                        }
+
+                        return $"Dictionary<{key},{val}>";
+                    }
+
+                case EnumType enumType: return _UseType(enumType).RuntimeName;
+
+                case ClassType classType: return _UseType(classType).RuntimeName;
+
+                default: throw new NotImplementedException(type.PersistentName);
+            }
+        }
+
+        private string _GetConstantRuntimeName(SchemaType type)
+        {
+            switch (type)
+            {
+                case StringType strType: return $"const {typeof(string).Name}";
+
+                case BlittableType blitType:
+                    {
+                        var tname = blitType.DataType.Name;
+
+                        if (blitType.DataType == typeof(int)) return $"const {tname}";
+                        if (blitType.DataType == typeof(float)) return $"const {tname}";
+                        if (blitType.DataType == typeof(double)) return $"const {tname}";
+
+                        return $"static readonly {tname}";
+                    }
+
+                case EnumType enumType: return $"const {_UseType(enumType).RuntimeName}";
+
+                case ArrayType aType: return $"static readonly {_UseType(aType).RuntimeName}";
+
+                default: throw new NotImplementedException();
+            }
+        }
+
+        internal Object _GetConstantRuntimeValue(SchemaType type, Object value)
+        {
+            ArgumentNullException.ThrowIfNull(value);
+
+            switch (type)
+            {
+                case StringType _:
+
+                    return value is string
+                        ? value
+                        : Convert.ChangeType(value, typeof(string), System.Globalization.CultureInfo.InvariantCulture);
+
+                case BlittableType btype:
+                    {
+                        if (btype.DataType == typeof(bool).GetTypeInfo())
+                        {
+                            if (value is bool) return value;
+
+                            var str = value as string;
+
+                            if (str.Equals("FALSE", StringComparison.OrdinalIgnoreCase)) return false;
+                            if (str.Equals("TRUE", StringComparison.OrdinalIgnoreCase)) return true;
+                            throw new NotImplementedException();
+                        }
+
+                        return value is string
+                            ? value
+                            : Convert.ChangeType(value, btype.DataType.AsType(), System.Globalization.CultureInfo.InvariantCulture);
+                    }
+
+                case EnumType etype:
+                    {
+                        var etypeName = _GetRuntimeName(type);
+
+                        if (value is string) return $"{etypeName}.{value}";
+                        else return $"({etypeName}){value}";
+                    }
+
+                case ArrayType aType:
+                    {
+                        var atypeName = _GetRuntimeName(type);
+
+                        return value.ToString();
+                    }
+
+                default: throw new NotImplementedException();
+            }
+        }        
+
+        #endregion
+
+        #region emit
+
+        public string EmitContext(SchemaType.Context context)
+        {
+            var sb = new StringBuilder();
+
+            sb.AppendLine("// <auto-generated/>");
+            sb.AppendLine();
+
+            sb.AppendLine("//------------------------------------------------------------------------------------------------");
+            sb.AppendLine("//      This file has been programatically generated; DON´T EDIT!");
+            sb.AppendLine("//------------------------------------------------------------------------------------------------");
+
+            sb.AppendLine();            
+            
+            sb.AppendLine("#pragma warning disable SA1001");
+            sb.AppendLine("#pragma warning disable SA1027");
+            sb.AppendLine("#pragma warning disable SA1028");
+            sb.AppendLine("#pragma warning disable SA1121");
+            sb.AppendLine("#pragma warning disable SA1205");
+            sb.AppendLine("#pragma warning disable SA1309");
+            sb.AppendLine("#pragma warning disable SA1402");
+            sb.AppendLine("#pragma warning disable SA1505");
+            sb.AppendLine("#pragma warning disable SA1507");
+            sb.AppendLine("#pragma warning disable SA1508");
+            sb.AppendLine("#pragma warning disable SA1652");
+
+            sb.AppendLine();
+
+            sb.AppendLine("using System;");
+            sb.AppendLine("using System.Collections.Generic;");
+            sb.AppendLine("using System.Linq;");
+            sb.AppendLine("using System.Text;");
+            sb.AppendLine("using System.Numerics;");
+            sb.AppendLine("using System.Text.Json;");
+
+            sb.AppendLine();
+
+            sb.AppendLine("using JSONREADER = System.Text.Json.Utf8JsonReader;");
+            sb.AppendLine("using JSONWRITER = System.Text.Json.Utf8JsonWriter;");
+            sb.AppendLine("using FIELDINFO = SharpGLTF.Reflection.FieldInfo;");
+
+            sb.AppendLine();
+
+            string currentNamespace = null;
+
+            void _setCurrentNamespace(string ns)
+            {
+                if (currentNamespace == ns) return;
+                if (currentNamespace != null) sb.AppendLine("}");
+                currentNamespace = ns;
+                if (currentNamespace != null)
+                {
+                    sb.AppendLine();
+                    sb.AppendLine($"namespace {currentNamespace}");
+                    sb.AppendLine("{");
+
+                    sb.AppendLine("using Collections;".Indent(1));
+                    sb.AppendLine();
+                }
+            }            
+
+            foreach (var etype in context.Enumerations)
+            {
+                _setCurrentNamespace(GetRuntimeNamespace(etype.PersistentName));
+
+                var cout = EmitEnum(etype);
+
+                sb.AppendLine(cout);
+                sb.AppendLine();
+            }
+
+            foreach (var ctype in context.Classes)
+            {
+                if (ctype.IgnoredByEmitter) continue;
+
+                _setCurrentNamespace(GetRuntimeNamespace(ctype.PersistentName));
+
+                var cout = EmitClass(ctype);
+
+                sb.AppendLine(cout);
+                sb.AppendLine();
+            }
+
+            _setCurrentNamespace(null);
+
+            return sb.ToString();
+        }
+
+        public string EmitEnum(EnumType type)
+        {
+            var sb = new StringBuilder();
+
+            foreach (var l in type.Description.EmitSummary(0)) sb.EmitLine(1, l);
+
+            sb.EmitLine(1, $"public enum {_GetRuntimeName(type)}");
+            sb.EmitLine(1, "{");
+
+            if (type.UseIntegers)
+            {
+                foreach (var kvp in type.Values)
+                {
+                    var k =  kvp.Key;
+
+                    sb.EmitLine(2, $"{k} = {kvp.Value},");
+                }
+            }
+            else
+            {
+                foreach (var kvp in type.Values)
+                {
+                    var k = kvp.Key;
+
+                    sb.EmitLine(2, $"{k},");
+                }
+            }            
+
+            sb.EmitLine(1, "}");
+
+            return sb.ToString();
+        }
+
+        public string EmitClass(ClassType type)
+        {
+            var xclass = new CSharpClassEmitter(this)
+            {
+                ClassSummary = type.Description,
+                SchemaName = type.ShortIdentifier,
+                ClassDeclaration = _GetClassDeclaration(type),
+                HasBaseClass = type.BaseClass != null
+            };
+
+            xclass.AddComments(type);
+            xclass.AddFields(type);            
+
+            return String.Join("\r\n",xclass.EmitCode().Indent(1));            
+        }
+
+        private string _GetClassDeclaration(ClassType type)
+        {
+            var classDecl = string.Empty;            
+            classDecl += "partial ";
+            classDecl += "class ";
+            classDecl += _GetRuntimeName(type);
+            if (type.BaseClass != null) classDecl += $" : {_GetRuntimeName(type.BaseClass)}";
+            return classDecl;
+        }
+
+        internal IEnumerable<string> _GetClassField(FieldInfo f)
+        {            
+            var tdecl = _GetRuntimeName(f.FieldType, _UseField(f));
+            var fname = GetFieldRuntimeName(f);
+
+            string defval = string.Empty;
+
+            if (f.DefaultValue != null)
+            {
+                var tconst = _GetConstantRuntimeName(f.FieldType);
+                var vconst = _GetConstantRuntimeValue(f.FieldType, f.DefaultValue);
+
+                // fix boolean value
+                if (vconst is Boolean bconst) vconst = bconst ? "true" : "false";
+
+                defval = $"{fname}Default";
+
+                yield return Invariant($"private {tconst} {defval} = {vconst};");
+            }
+
+            if (f.ExclusiveMinimumValue != null)
+            {
+                var tconst = _GetConstantRuntimeName(f.FieldType);
+                var vconst = _GetConstantRuntimeValue(f.FieldType, f.ExclusiveMinimumValue);
+                yield return Invariant($"private {tconst} {fname}ExclusiveMinimum = {vconst};");
+            }
+
+            if (f.InclusiveMinimumValue != null)
+            {
+                var tconst = _GetConstantRuntimeName(f.FieldType);
+                var vconst = _GetConstantRuntimeValue(f.FieldType, f.InclusiveMinimumValue);
+                yield return Invariant($"private {tconst} {fname}Minimum = {vconst};");
+            }
+
+            if (f.InclusiveMaximumValue != null)
+            {
+                var tconst = _GetConstantRuntimeName(f.FieldType);
+                var vconst = _GetConstantRuntimeValue(f.FieldType, f.InclusiveMaximumValue);
+                yield return Invariant($"private {tconst} {fname}Maximum = {vconst};");
+            }
+
+            if (f.ExclusiveMaximumValue != null)
+            {
+                var tconst = _GetConstantRuntimeName(f.FieldType);
+                var vconst = _GetConstantRuntimeValue(f.FieldType, f.ExclusiveMaximumValue);
+                yield return Invariant($"private {tconst} {fname}ExclusiveMaximum = {vconst};");
+            }
+
+            if (f.MinItems > 0)
+            {                    
+                yield return $"private const int {fname}MinItems = {f.MinItems};";
+            }
+
+            if (f.MaxItems > 0 && f.MaxItems < int.MaxValue)
+            {                    
+                yield return $"private const int {fname}MaxItems = {f.MaxItems};";
+            }
+
+            if (f.FieldType is EnumType etype && etype.IsNullable) tdecl = tdecl + "?";            
+
+            yield return string.IsNullOrEmpty(defval) ? $"private {tdecl} {fname};" : $"private {tdecl} {fname} = {defval};";
+
+            yield return string.Empty;
+        }            
+
+        #endregion
+    }
+
+    /// <summary>
+    /// Utility class to emit a <see cref="SchemaReflection.ClassType"/>
+    /// as c# source code
+    /// </summary>
+    class CSharpClassEmitter
+    {
+        #region constructor
+
+        public CSharpClassEmitter(CSharpEmitter emitter)
+        {
+            _Emitter = emitter;
+        }
+
+        #endregion
+
+        #region data
+
+        private readonly CSharpEmitter _Emitter;
+
+        private readonly List<string> _Comments = new List<string>();
+
+        private readonly List<string> _Fields = new List<string>();
+        private readonly List<string> _SerializerBody = new List<string>();
+        private readonly List<string> _DeserializerSwitchBody = new List<string>();
+
+        private readonly List<string> _FieldsNamesReflection = new List<string>();
+        private readonly List<string> _FieldsSwitchReflection = new List<string>();
+
+        public string ClassSummary { get; set; }
+
+        /// <summary>
+        /// The name used in the schema $id field, minus the prefix and suffix
+        /// </summary>
+        public string SchemaName { get; set; }
+
+        /// <summary>
+        /// Represents the Runtime Class Name
+        /// </summary>
+        public string ClassDeclaration { get; set; }
+
+        public bool HasBaseClass { get; set; }
+
+        private const string _READERMODIFIER = "ref ";
+
+        #endregion
+
+        #region API
+
+        public void AddComments(ClassType type)
+        {
+            _Comments.AddRange(_Emitter.GetRuntimeComments(type));
+        }
+
+        public void AddFields(ClassType type)
+        {
+            foreach (var f in type.Fields)
+            {
+                var trname = _Emitter._GetRuntimeName(f.FieldType);
+                var frname = _Emitter.GetFieldRuntimeName(f);
+
+                _Fields.AddRange(_Emitter._GetClassField(f));
+
+                AddFieldReflection(f);
+
+                // serialization
+
+                if (f.FieldType is EnumType etype) // special case for enums
+                {
+                    // emit serializer
+                    var smethod = etype.UseIntegers ? "SerializePropertyEnumValue" : "SerializePropertyEnumSymbol";
+                    smethod = $"{smethod}<{trname}>(writer, \"{f.PersistentName}\", {frname}";
+                    if (f.DefaultValue != null) smethod += $", {frname}Default";
+                    smethod += ");";
+                    this.AddFieldSerializerCase(smethod);
+
+                    // emit deserializer
+                    this.AddFieldDeserializerCase(f.PersistentName, $"{frname} = DeserializePropertyValue<{_Emitter._GetRuntimeName(etype)}>({_READERMODIFIER}reader);");
+
+                    continue;
+                }
+
+                this.AddFieldSerializerCase(_GetJSonSerializerMethod(f));
+                this.AddFieldDeserializerCase(f.PersistentName, _GetJSonDeserializerMethod(f));
+            }
+        }
+
+        private void AddFieldReflection(FieldInfo finfo)
+        {
+            var trname = _Emitter._GetRuntimeName(finfo.FieldType);
+            var frname = _Emitter.GetFieldRuntimeName(finfo);
+
+            trname = trname.Replace("?", ""); // since we're adding the default value, there's no need for nullable values.
+
+            var vtype = $"typeof({trname})";
+            var getter = $"instance => instance.{frname}";            
+
+            if (finfo.DefaultValue != null)
+            {
+                var vconst = _Emitter._GetConstantRuntimeValue(finfo.FieldType, finfo.DefaultValue);
+                // fix boolean value            
+                if (vconst is Boolean bconst) vconst = bconst ? "true" : "false";                
+
+                getter += FormattableString.Invariant($" ?? {vconst}");
+            }
+
+            // _FieldsReflection.Add($"yield return FIELDINFO.From(\"{finfo.PersistentName}\",this, {getter});");
+
+            _FieldsNamesReflection.Add(finfo.PersistentName);
+            _FieldsSwitchReflection.Add($"case \"{finfo.PersistentName}\": value = FIELDINFO.From(\"{finfo.PersistentName}\",this, {getter}); return true;");
+        }
+
+        private string _GetJSonSerializerMethod(FieldInfo f)
+        {
+            var pname = f.PersistentName;
+            var fname = _Emitter.GetFieldRuntimeName(f);
+
+            if (f.FieldType is ClassType ctype)
+            {
+                return $"SerializePropertyObject(writer, \"{pname}\", {fname});";
+            }
+
+            if (f.FieldType is ArrayType atype)
+            {
+                if (f.MinItems > 0) return $"SerializeProperty(writer, \"{pname}\", {fname}, {fname}MinItems);";
+
+                return $"SerializeProperty(writer,\"{pname}\",{fname});";
+            }
+
+            if (f.DefaultValue != null) return $"SerializeProperty(writer, \"{pname}\", {fname}, {fname}Default);";
+
+            return $"SerializeProperty(writer, \"{pname}\", {fname});";
+        }
+
+        private string _GetJSonDeserializerMethod(FieldInfo f)
+        {
+            var fname = _Emitter.GetFieldRuntimeName(f);
+
+            var ownerTypeName = _Emitter._GetRuntimeName(f.DeclaringClass);
+
+            if (f.FieldType is ArrayType atype)
+            {
+                var titem = _Emitter._GetRuntimeName(atype.ItemType);
+                return $"DeserializePropertyList<{ownerTypeName}, {titem}>({_READERMODIFIER}reader, this, {fname});";
+            }
+            else if (f.FieldType is DictionaryType dtype)
+            {
+                var titem = _Emitter._GetRuntimeName(dtype.ValueType);
+                return $"DeserializePropertyDictionary<{ownerTypeName}, {titem}>({_READERMODIFIER}reader, this, {fname});";
+            }
+            
+            var fieldTypeName = _Emitter._GetRuntimeName(f.FieldType);            
+
+            return $"DeserializePropertyValue<{ownerTypeName}, {fieldTypeName}>({_READERMODIFIER}reader, this, out {fname});";
+        }        
+
+        public void AddFieldSerializerCase(string line) { _SerializerBody.Add(line); }
+
+        public void AddFieldDeserializerCase(string persistentName, string line)
+        {
+            _DeserializerSwitchBody.Add($"case \"{persistentName}\": {line} break;");            
+        }
+
+        public IEnumerable<string> EmitCode()
+        {
+            #if USENEWTONSOFT
+            var readerType = "JsonReader";
+            var writerType = "JsonWriter";
+            #else
+            var readerType = "ref JSONREADER";
+            var writerType = "JSONWRITER";
+            #endif
+
+            foreach (var l in _Comments) yield return $"// {l}";
+
+            foreach (var l in ClassSummary.EmitSummary(0)) yield return l;
+
+            yield return "#if NET6_0_OR_GREATER";
+            yield return "[System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)]";
+            yield return "#endif";
+
+            yield return "[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"SharpGLTF.CodeGen\", \"1.0.0.0\")]";
+
+            yield return ClassDeclaration;
+            yield return "{";
+
+            yield return string.Empty;
+
+            yield return "#region reflection".Indent(1);
+            yield return string.Empty;
+
+            yield return $"public const string SCHEMANAME = \"{SchemaName}\";".Indent(1);
+
+            var pointerPathModifier = HasBaseClass ? "override" : "virtual";
+            yield return $"protected {pointerPathModifier} string GetSchemaName() => SCHEMANAME;".Indent(1);            
+
+            yield return string.Empty;
+
+            yield return $"protected override IEnumerable<string> ReflectFieldsNames()".Indent(1);
+            yield return "{".Indent(1);            
+            foreach (var l in _FieldsNamesReflection) yield return $"yield return \"{l}\";".Indent(2);
+            if (HasBaseClass) yield return "foreach(var f in base.ReflectFieldsNames()) yield return f;".Indent(2);
+            yield return "}".Indent(1);
+
+            yield return $"protected override bool TryReflectField(string name, out FIELDINFO value)".Indent(1);
+            yield return "{".Indent(1);
+            yield return "switch(name)".Indent(2);
+            yield return "{".Indent(2);
+            foreach (var l in _FieldsSwitchReflection.Indent(3)) yield return l;
+            if (HasBaseClass) yield return "default: return base.TryReflectField(name, out value);".Indent(3);            
+            yield return "}".Indent(2);
+            yield return "}".Indent(1);
+
+            yield return string.Empty;
+            yield return "#endregion".Indent(1);
+
+            yield return string.Empty;
+
+            yield return "#region data".Indent(1);
+            yield return string.Empty;
+
+            foreach (var l in _Fields.Indent(1)) yield return l;
+
+            yield return "#endregion".Indent(1);
+
+            yield return string.Empty;
+
+            yield return "#region serialization".Indent(1);
+            yield return string.Empty;
+
+            // yield return "/// <inheritdoc />".Indent(1);
+            yield return $"protected override void SerializeProperties({writerType} writer)".Indent(1);
+            yield return "{".Indent(1);
+            if (HasBaseClass) yield return "base.SerializeProperties(writer);".Indent(2);
+            foreach (var l in _SerializerBody.Indent(2)) yield return l;
+            yield return "}".Indent(1);
+
+            yield return string.Empty;
+
+            // yield return "/// <inheritdoc />".Indent(1);
+            yield return $"protected override void DeserializeProperty(string jsonPropertyName, {readerType} reader)".Indent(1);
+            yield return "{".Indent(1);
+            yield return "switch (jsonPropertyName)".Indent(2);
+            yield return "{".Indent(2);
+
+            foreach (var l in _DeserializerSwitchBody.Indent(3)) yield return l;
+            if (HasBaseClass) yield return $"default: base.DeserializeProperty(jsonPropertyName,{_READERMODIFIER}reader); break;".Indent(3);
+            else yield return "default: throw new NotImplementedException();".Indent(3);
+
+            yield return "}".Indent(2);
+            yield return "}".Indent(1);
+
+            yield return string.Empty;
+            yield return "#endregion".Indent(1);
+
+            yield return string.Empty;            
+
+            yield return "}";
+        }
+
+        #endregion
+    }
+}

+ 88 - 0
build/SharpGLTF.CodeGen.Core/Constants.cs

@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF
+{
+    static class Constants
+    {
+        #region root paths
+
+        public static string RemoteSchemaRepo = "https://github.com/KhronosGroup/glTF.git";
+
+        /// <summary>
+        /// Program directory
+        /// </summary>
+        public static string ProgramDirectory => System.IO.Path.GetDirectoryName(typeof(Constants).Assembly.Location);
+
+        /// <summary>
+        /// Directory where the schema is downloaded and used as source
+        /// </summary>
+        public static string LocalRepoDirectory => System.IO.Path.Combine(ProgramDirectory, "glTF");
+
+        #endregion
+
+        #region main schema paths
+
+        /// <summary>
+        /// Directory of the main schema within the download repo directory
+        /// </summary>
+        public static string MainSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "specification", "2.0", "schema");
+
+        /// <summary>
+        /// schema source code file path
+        /// </summary>
+        public static string MainSchemaFile => System.IO.Path.Combine(MainSchemaDir, "glTF.schema.json");
+
+        #endregion
+
+        #region extension paths        
+        private static string ArchivedSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Archived");
+        private static string KhronosSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Khronos");
+        private static string VendorSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Vendor");
+
+        internal static string ArchivedExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(ArchivedSchemaDir, ext, "schema", json);
+        }
+
+        internal static string KhronosExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(KhronosSchemaDir, ext, "schema", json);
+        }
+        
+        internal static string VendorExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(VendorSchemaDir, ext, "schema", json);
+        }
+
+        internal static string CustomExtensionsPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(ProgramDirectory, "Schemas", ext, "schema", json);
+        }
+
+
+        #endregion
+
+        #region code generation output paths
+
+        /// <summary>
+        /// directory within the solution where the generated code is emitted
+        /// </summary>
+        public static string TargetProjectDirectory => "src\\SharpGLTF.Core\\Schema2\\Generated";
+        public static string CesiumProjectDirectory => "src\\SharpGLTF.Ext.3DTiles\\Schema2\\Generated";
+        public static string AgiProjectDirectory => "src\\SharpGLTF.Ext.Agi\\Schema2\\Generated";
+
+
+        /// <summary>
+        /// namespace of the emitted generated code
+        /// </summary>
+        public static string OutputNamespace => "SharpGLTF.Schema2";
+
+        public static string CesiumNameSpace => "SharpGLTF.Schema2.Tiles3D";
+
+        public static string AgiNameSpace => "SharpGLTF.Schema2.AGI";
+
+        #endregion
+    }
+}

+ 137 - 137
build/SharpGLTF.CodeGen/MainSchemaProcessor.cs → build/SharpGLTF.CodeGen.Core/MainSchemaProcessor.cs

@@ -1,137 +1,137 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using SharpGLTF.CodeGen;
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class MainSchemaProcessor : SchemaProcessor
-    {
-        public override IEnumerable<(string TargetFileName, SchemaType.Context Schema)> ReadSchema()
-        {
-            // load and process schema
-            var ctx = SchemaProcessing.LoadSchemaContext(Constants.MainSchemaFile);
-
-            // Ignore "glTF Property" because it is completely hand coded.
-            ctx.IgnoredByCodeEmitter("glTF Property");
-
-            // We will mimeType "anyof" as a plain string.
-            ctx.Remove("image/jpeg-image/png");
-
-            // replace Image.mimeType type from an Enum to String, so we can serialize it with more formats if required
-            ctx.FindClass("Image")
-                .GetField("mimeType")
-                .FieldType = ctx.UseString();
-
-            // replace Node.Matrix, Node.Rotation, Node.Scale and Node.Translation with System.Numerics.Vectors types
-            var node = ctx.FindClass("Node");
-
-            // the default values of the transform properties is both a "known value" and null, so
-            // we preffer to set here the "known value" since it's also used to check whether
-            // the value should be serialized.
-            // But then, we need to set the values to null in the Node Constructor,
-            // because Matrix and SRT are mutually exclusive.
-            node.GetField("matrix").SetDataType(typeof(System.Numerics.Matrix4x4), true).SetDefaultValue("System.Numerics.Matrix4x4.Identity").SetItemsRange(0);
-            node.GetField("scale").SetDataType(typeof(System.Numerics.Vector3), true).SetDefaultValue("Vector3.One").SetItemsRange(0);
-            node.GetField("rotation").SetDataType(typeof(System.Numerics.Quaternion), true).SetDefaultValue("Quaternion.Identity").SetItemsRange(0);            
-            node.GetField("translation").SetDataType(typeof(System.Numerics.Vector3), true).SetDefaultValue("Vector3.Zero").SetItemsRange(0);
-
-            // replace Material.emissiveFactor with System.Numerics.Vectors types
-            ctx.FindClass("Material")
-                .GetField("emissiveFactor")
-                .SetDataType(typeof(System.Numerics.Vector3), true)
-                .SetDefaultValue("Vector3.Zero")
-                .SetItemsRange(0);
-
-            // replace Material.baseColorFactor with System.Numerics.Vectors types
-            ctx.FindClass("Material PBR Metallic Roughness")
-                .GetField("baseColorFactor")
-                .SetDataType(typeof(System.Numerics.Vector4), true)
-                .SetDefaultValue("Vector4.One")
-                .SetItemsRange(0);
-
-            ctx.FindEnum("LINEAR-NEAREST")
-                .SetValue("DEFAULT", 0);
-
-            ctx.FindEnum("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST")
-                .SetValue("DEFAULT", 0);
-
-            // Accessor.type is declared as AnyOfEnum, but also as a STRING,
-            // which can be used by extensions to store non standard values like MAT4x3
-            ctx.FindClass("Accessor")
-                .GetField("type").SetDataType(typeof(string), true);
-
-            // Since DimensionType can have additional values other than the ones defined by the schema
-            // we need a "special" value to define it
-            ctx.FindEnum("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4")
-                .SetValue("CUSTOM", 0);
-
-            yield return ("gltf.g", ctx);
-        }
-
-        public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetCollectionContainer("List<TItem>");
-
-            const string rootName = "ModelRoot";
-
-            newEmitter.SetRuntimeName("glTF", rootName);
-            newEmitter.SetRuntimeName("glTF Property", "ExtraProperties");
-            newEmitter.SetRuntimeName("glTF Child of Root Property", "LogicalChildOfRoot");
-
-            newEmitter.SetRuntimeName("Sampler", "TextureSampler");
-
-            newEmitter.SetRuntimeName("UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "IndexEncodingType");
-            newEmitter.SetRuntimeName("BYTE-FLOAT-SHORT-UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "EncodingType");
-            newEmitter.SetRuntimeName("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4", "DimensionType");
-            newEmitter.SetRuntimeName("rotation-scale-translation-weights", "PropertyPath");
-            newEmitter.SetRuntimeName("ARRAY_BUFFER-ELEMENT_ARRAY_BUFFER", "BufferMode");
-            newEmitter.SetRuntimeName("orthographic-perspective", "CameraType");
-            newEmitter.SetRuntimeName("BLEND-MASK-OPAQUE", "AlphaMode");
-            newEmitter.SetRuntimeName("LINE_LOOP-LINE_STRIP-LINES-POINTS-TRIANGLE_FAN-TRIANGLE_STRIP-TRIANGLES", "PrimitiveType");
-            newEmitter.SetRuntimeName("CUBICSPLINE-LINEAR-STEP", "AnimationInterpolationMode");
-            newEmitter.SetRuntimeName("LINEAR-NEAREST", "TextureInterpolationFilter");
-            newEmitter.SetRuntimeName("CLAMP_TO_EDGE-MIRRORED_REPEAT-REPEAT", "TextureWrapMode");
-            newEmitter.SetRuntimeName("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST", "TextureMipMapFilter");
-
-            // add "pointer" enum value to PropertyPath, which is required by KHR_animation_pointer
-            var propertyPathEnum = ctx.FindEnum("rotation-scale-translation-weights");            
-            propertyPathEnum?.SetValue("pointer", 0);
-
-            var meshClass = ctx.FindClass("Mesh");
-            if (meshClass != null)
-            {
-                newEmitter.SetCollectionContainer(meshClass.UseField("primitives"), "ChildrenList<TItem,Mesh>");
-            }
-
-            var animationClass = ctx.FindClass("Animation");
-            if (animationClass != null)
-            {
-                newEmitter.SetCollectionContainer(animationClass.UseField("channels"), "ChildrenList<TItem,Animation>");
-                newEmitter.SetCollectionContainer(animationClass.UseField("samplers"), "ChildrenList<TItem,Animation>");
-            }
-
-            var classes = ctx.Classes.ToArray();
-            var fields = classes
-                .SelectMany(item => item.Fields)
-                .ToArray();
-
-            foreach (var f in fields)
-            {
-                if (f.FieldType is ArrayType atype)
-                {
-                    if (atype.ItemType is ClassType ctype)
-                    {
-                        if (ctype.BaseClass != null && ctype.BaseClass.PersistentName == "glTF Child of Root Property")
-                        {
-                            newEmitter.SetCollectionContainer(f, $"ChildrenList<TItem,{rootName}>");
-                        }
-                    }
-                }
-            }
-        }        
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using SharpGLTF.CodeGen;
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    public class MainSchemaProcessor : SchemaProcessor
+    {
+        public override IEnumerable<(string TargetFileName, SchemaType.Context Schema)> ReadSchema()
+        {
+            // load and process schema
+            var ctx = SchemaProcessing.LoadSchemaContext(Constants.MainSchemaFile);
+
+            // Ignore "glTF Property" because it is completely hand coded.
+            ctx.IgnoredByCodeEmitter("glTF Property");
+
+            // We will mimeType "anyof" as a plain string.
+            ctx.Remove("image/jpeg-image/png");
+
+            // replace Image.mimeType type from an Enum to String, so we can serialize it with more formats if required
+            ctx.FindClass("Image")
+                .GetField("mimeType")
+                .FieldType = ctx.UseString();
+
+            // replace Node.Matrix, Node.Rotation, Node.Scale and Node.Translation with System.Numerics.Vectors types
+            var node = ctx.FindClass("Node");
+
+            // the default values of the transform properties is both a "known value" and null, so
+            // we preffer to set here the "known value" since it's also used to check whether
+            // the value should be serialized.
+            // But then, we need to set the values to null in the Node Constructor,
+            // because Matrix and SRT are mutually exclusive.
+            node.GetField("matrix").SetDataType(typeof(System.Numerics.Matrix4x4), true).SetDefaultValue("System.Numerics.Matrix4x4.Identity").SetItemsRange(0);
+            node.GetField("scale").SetDataType(typeof(System.Numerics.Vector3), true).SetDefaultValue("Vector3.One").SetItemsRange(0);
+            node.GetField("rotation").SetDataType(typeof(System.Numerics.Quaternion), true).SetDefaultValue("Quaternion.Identity").SetItemsRange(0);            
+            node.GetField("translation").SetDataType(typeof(System.Numerics.Vector3), true).SetDefaultValue("Vector3.Zero").SetItemsRange(0);
+
+            // replace Material.emissiveFactor with System.Numerics.Vectors types
+            ctx.FindClass("Material")
+                .GetField("emissiveFactor")
+                .SetDataType(typeof(System.Numerics.Vector3), true)
+                .SetDefaultValue("Vector3.Zero")
+                .SetItemsRange(0);
+
+            // replace Material.baseColorFactor with System.Numerics.Vectors types
+            ctx.FindClass("Material PBR Metallic Roughness")
+                .GetField("baseColorFactor")
+                .SetDataType(typeof(System.Numerics.Vector4), true)
+                .SetDefaultValue("Vector4.One")
+                .SetItemsRange(0);
+
+            ctx.FindEnum("LINEAR-NEAREST")
+                .SetValue("DEFAULT", 0);
+
+            ctx.FindEnum("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST")
+                .SetValue("DEFAULT", 0);
+
+            // Accessor.type is declared as AnyOfEnum, but also as a STRING,
+            // which can be used by extensions to store non standard values like MAT4x3
+            ctx.FindClass("Accessor")
+                .GetField("type").SetDataType(typeof(string), true);
+
+            // Since DimensionType can have additional values other than the ones defined by the schema
+            // we need a "special" value to define it
+            ctx.FindEnum("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4")
+                .SetValue("CUSTOM", 0);
+
+            yield return ("gltf.g", ctx);
+        }
+
+        public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetCollectionContainer("List<TItem>");
+
+            const string rootName = "ModelRoot";
+
+            newEmitter.SetRuntimeName("glTF", rootName);
+            newEmitter.SetRuntimeName("glTF Property", "ExtraProperties");
+            newEmitter.SetRuntimeName("glTF Child of Root Property", "LogicalChildOfRoot");
+
+            newEmitter.SetRuntimeName("Sampler", "TextureSampler");
+
+            newEmitter.SetRuntimeName("UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "IndexEncodingType");
+            newEmitter.SetRuntimeName("BYTE-FLOAT-SHORT-UNSIGNED_BYTE-UNSIGNED_INT-UNSIGNED_SHORT", "EncodingType");
+            newEmitter.SetRuntimeName("MAT2-MAT3-MAT4-SCALAR-VEC2-VEC3-VEC4", "DimensionType");
+            newEmitter.SetRuntimeName("rotation-scale-translation-weights", "PropertyPath");
+            newEmitter.SetRuntimeName("ARRAY_BUFFER-ELEMENT_ARRAY_BUFFER", "BufferMode");
+            newEmitter.SetRuntimeName("orthographic-perspective", "CameraType");
+            newEmitter.SetRuntimeName("BLEND-MASK-OPAQUE", "AlphaMode");
+            newEmitter.SetRuntimeName("LINE_LOOP-LINE_STRIP-LINES-POINTS-TRIANGLE_FAN-TRIANGLE_STRIP-TRIANGLES", "PrimitiveType");
+            newEmitter.SetRuntimeName("CUBICSPLINE-LINEAR-STEP", "AnimationInterpolationMode");
+            newEmitter.SetRuntimeName("LINEAR-NEAREST", "TextureInterpolationFilter");
+            newEmitter.SetRuntimeName("CLAMP_TO_EDGE-MIRRORED_REPEAT-REPEAT", "TextureWrapMode");
+            newEmitter.SetRuntimeName("LINEAR-LINEAR_MIPMAP_LINEAR-LINEAR_MIPMAP_NEAREST-NEAREST-NEAREST_MIPMAP_LINEAR-NEAREST_MIPMAP_NEAREST", "TextureMipMapFilter");
+
+            // add "pointer" enum value to PropertyPath, which is required by KHR_animation_pointer
+            var propertyPathEnum = ctx.FindEnum("rotation-scale-translation-weights");            
+            propertyPathEnum?.SetValue("pointer", 0);
+
+            var meshClass = ctx.FindClass("Mesh");
+            if (meshClass != null)
+            {
+                newEmitter.SetCollectionContainer(meshClass.UseField("primitives"), "ChildrenList<TItem,Mesh>");
+            }
+
+            var animationClass = ctx.FindClass("Animation");
+            if (animationClass != null)
+            {
+                newEmitter.SetCollectionContainer(animationClass.UseField("channels"), "ChildrenList<TItem,Animation>");
+                newEmitter.SetCollectionContainer(animationClass.UseField("samplers"), "ChildrenList<TItem,Animation>");
+            }
+
+            var classes = ctx.Classes.ToArray();
+            var fields = classes
+                .SelectMany(item => item.Fields)
+                .ToArray();
+
+            foreach (var f in fields)
+            {
+                if (f.FieldType is ArrayType atype)
+                {
+                    if (atype.ItemType is ClassType ctype)
+                    {
+                        if (ctype.BaseClass != null && ctype.BaseClass.PersistentName == "glTF Child of Root Property")
+                        {
+                            newEmitter.SetCollectionContainer(f, $"ChildrenList<TItem,{rootName}>");
+                        }
+                    }
+                }
+            }
+        }        
+    }
+}

+ 38 - 38
build/SharpGLTF.CodeGen/SchemaDownload.cs → build/SharpGLTF.CodeGen.Core/SchemaDownload.cs

@@ -1,38 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace SharpGLTF
-{
-    /// <summary>
-    /// Utility class to download the gltf2 schema from github
-    /// </summary>
-    static class SchemaDownload
-    {
-        public static void Syncronize(string remoteUrl, string localDirectory)
-        {
-            if (LibGit2Sharp.Repository.Discover(localDirectory) == null)
-            {
-                Console.WriteLine($"Cloning {remoteUrl} can take several minutes; Please wait...");
-
-                LibGit2Sharp.Repository.Clone(remoteUrl, localDirectory);
-
-                Console.WriteLine($"... Clone Completed");
-
-                return;
-            }
-
-            using (var repo = new LibGit2Sharp.Repository(localDirectory))
-            {
-                var options = new LibGit2Sharp.PullOptions
-                {
-                    FetchOptions = new LibGit2Sharp.FetchOptions()
-                };
-
-                var r = LibGit2Sharp.Commands.Pull(repo, new LibGit2Sharp.Signature("Anonymous", "[email protected]", new DateTimeOffset(DateTime.Now)), options);
-
-                Console.WriteLine($"{remoteUrl} is {r.Status}");
-            }
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF
+{
+    /// <summary>
+    /// Utility class to download the gltf2 schema from github
+    /// </summary>
+    public static class SchemaDownload
+    {
+        public static void Syncronize(string remoteUrl, string localDirectory)
+        {
+            if (LibGit2Sharp.Repository.Discover(localDirectory) == null)
+            {
+                Console.WriteLine($"Cloning {remoteUrl} can take several minutes; Please wait...");
+
+                LibGit2Sharp.Repository.Clone(remoteUrl, localDirectory);
+
+                Console.WriteLine($"... Clone Completed");
+
+                return;
+            }
+
+            using (var repo = new LibGit2Sharp.Repository(localDirectory))
+            {
+                var options = new LibGit2Sharp.PullOptions
+                {
+                    FetchOptions = new LibGit2Sharp.FetchOptions()
+                };
+
+                var r = LibGit2Sharp.Commands.Pull(repo, new LibGit2Sharp.Signature("Anonymous", "[email protected]", new DateTimeOffset(DateTime.Now)), options);
+
+                Console.WriteLine($"{remoteUrl} is {r.Status}");
+            }
+        }
+    }
+}

+ 119 - 119
build/SharpGLTF.CodeGen/SchemaProcessing.cs → build/SharpGLTF.CodeGen.Core/SchemaProcessing.cs

@@ -1,119 +1,119 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using SharpGLTF.CodeGen;
-using SharpGLTF.SchemaReflection;
-
-using System.Threading.Tasks;
-
-using NJsonSchema.References;
-
-using JSONSCHEMA = NJsonSchema.JsonSchema;
-
-namespace SharpGLTF
-{
-    static class SchemaProcessing
-    {
-        #region schema loader
-
-        public static SchemaType.Context LoadExtensionSchemaContext(string srcSchema)
-        {
-            var context = LoadSchemaContext(srcSchema);
-            context.IgnoredByCodeEmittierMainSchema();
-            return context;
-        }
-
-        public static SchemaType.Context LoadSchemaContext(string srcSchema)
-        {
-            var schema = LoadSchema(srcSchema);
-
-            var settings = new NJsonSchema.CodeGeneration.CSharp.CSharpGeneratorSettings
-            {
-
-                Namespace = "glTf.POCO",
-                ClassStyle = NJsonSchema.CodeGeneration.CSharp.CSharpClassStyle.Poco
-            };
-
-            var ctypes = new NJsonSchema.CodeGeneration.CSharp.CSharpTypeResolver(settings);
-            ctypes.Resolve(schema, false, null);
-
-            return SchemaTypesReader.Generate(ctypes);
-        }
-
-        private static JSONSCHEMA LoadSchema(string filePath)
-        {
-            // https://blogs.msdn.microsoft.com/benjaminperkins/2017/03/08/how-to-call-an-async-method-from-a-console-app-main-method/
-
-            if (!System.IO.File.Exists(filePath)) throw new System.IO.FileNotFoundException(nameof(filePath), filePath);
-
-            return JSONSCHEMA
-                .FromFileAsync(filePath, s => _Resolver(s, filePath))
-                .ConfigureAwait(false)
-                .GetAwaiter()
-                .GetResult();
-        }
-
-        static NJsonSchema.JsonReferenceResolver _Resolver(JSONSCHEMA schema, string basePath)
-        {
-            var generator = new NJsonSchema.NewtonsoftJson.Generation.NewtonsoftJsonSchemaGeneratorSettings();
-
-            var solver = new NJsonSchema.JsonSchemaAppender(schema, generator.TypeNameGenerator);
-
-            return new MyReferenceResolver(solver);
-        }
-
-        class MyReferenceResolver : NJsonSchema.JsonReferenceResolver
-        {
-            public MyReferenceResolver(NJsonSchema.JsonSchemaAppender resolver) : base(resolver) { }
-
-            public override Task<IJsonReference> ResolveFileReferenceAsync(string filePath, System.Threading.CancellationToken cancellationToken)
-            {
-                if (System.IO.File.Exists(filePath)) return base.ResolveFileReferenceAsync(filePath, cancellationToken);
-
-                filePath = System.IO.Path.GetFileName(filePath);
-                filePath = System.IO.Path.Combine(Constants.MainSchemaDir, filePath);
-
-                if (System.IO.File.Exists(filePath)) return base.ResolveFileReferenceAsync(filePath, cancellationToken);
-
-                throw new System.IO.FileNotFoundException(filePath);
-            }
-        }
-
-        #endregion
-
-        public static void EmitCodeFromSchema(string projectPath, string dstFile, SchemaType.Context ctx, IReadOnlyList<SchemaProcessor> extensions)
-        {
-            var newEmitter = new CSharpEmitter();
-            newEmitter.DeclareContext(ctx);           
-
-            foreach(var ext in extensions)
-            {
-                ext.PrepareTypes(newEmitter, ctx);
-            }
-
-            var textOut = newEmitter.EmitContext(ctx);
-
-            var dstDir = _FindTargetDirectory(projectPath);
-            var dstPath = System.IO.Path.Combine(dstDir, $"{dstFile}.cs");
-
-            System.IO.File.WriteAllText(dstPath, textOut);
-        }
-
-        private static string _FindTargetDirectory(string dstDir)
-        {
-            var dir = Constants.LocalRepoDirectory;
-
-            while (dir.Length > 3)
-            {
-                var xdir = System.IO.Path.Combine(dir, dstDir);
-                if (System.IO.Directory.Exists(xdir)) return xdir;
-
-                dir = System.IO.Path.GetDirectoryName(dir); // move up
-            }
-
-            return null;
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using SharpGLTF.CodeGen;
+using SharpGLTF.SchemaReflection;
+
+using System.Threading.Tasks;
+
+using NJsonSchema.References;
+
+using JSONSCHEMA = NJsonSchema.JsonSchema;
+
+namespace SharpGLTF
+{
+    public static class SchemaProcessing
+    {
+        #region schema loader
+
+        public static SchemaType.Context LoadExtensionSchemaContext(string srcSchema)
+        {
+            var context = LoadSchemaContext(srcSchema);
+            context.IgnoredByCodeEmittierMainSchema();
+            return context;
+        }
+
+        public static SchemaType.Context LoadSchemaContext(string srcSchema)
+        {
+            var schema = LoadSchema(srcSchema);
+
+            var settings = new NJsonSchema.CodeGeneration.CSharp.CSharpGeneratorSettings
+            {
+
+                Namespace = "glTf.POCO",
+                ClassStyle = NJsonSchema.CodeGeneration.CSharp.CSharpClassStyle.Poco
+            };
+
+            var ctypes = new NJsonSchema.CodeGeneration.CSharp.CSharpTypeResolver(settings);
+            ctypes.Resolve(schema, false, null);
+
+            return SchemaTypesReader.Generate(ctypes);
+        }
+
+        private static JSONSCHEMA LoadSchema(string filePath)
+        {
+            // https://blogs.msdn.microsoft.com/benjaminperkins/2017/03/08/how-to-call-an-async-method-from-a-console-app-main-method/
+
+            if (!System.IO.File.Exists(filePath)) throw new System.IO.FileNotFoundException(nameof(filePath), filePath);
+
+            return JSONSCHEMA
+                .FromFileAsync(filePath, s => _Resolver(s, filePath))
+                .ConfigureAwait(false)
+                .GetAwaiter()
+                .GetResult();
+        }
+
+        static NJsonSchema.JsonReferenceResolver _Resolver(JSONSCHEMA schema, string basePath)
+        {
+            var generator = new NJsonSchema.NewtonsoftJson.Generation.NewtonsoftJsonSchemaGeneratorSettings();
+
+            var solver = new NJsonSchema.JsonSchemaAppender(schema, generator.TypeNameGenerator);
+
+            return new MyReferenceResolver(solver);
+        }
+
+        class MyReferenceResolver : NJsonSchema.JsonReferenceResolver
+        {
+            public MyReferenceResolver(NJsonSchema.JsonSchemaAppender resolver) : base(resolver) { }
+
+            public override Task<IJsonReference> ResolveFileReferenceAsync(string filePath, System.Threading.CancellationToken cancellationToken)
+            {
+                if (System.IO.File.Exists(filePath)) return base.ResolveFileReferenceAsync(filePath, cancellationToken);
+
+                filePath = System.IO.Path.GetFileName(filePath);
+                filePath = System.IO.Path.Combine(Constants.MainSchemaDir, filePath);
+
+                if (System.IO.File.Exists(filePath)) return base.ResolveFileReferenceAsync(filePath, cancellationToken);
+
+                throw new System.IO.FileNotFoundException(filePath);
+            }
+        }
+
+        #endregion
+
+        public static void EmitCodeFromSchema(string projectPath, string dstFile, SchemaType.Context ctx, IReadOnlyList<SchemaProcessor> extensions)
+        {
+            var newEmitter = new CSharpEmitter();
+            newEmitter.DeclareContext(ctx);           
+
+            foreach(var ext in extensions)
+            {
+                ext.PrepareTypes(newEmitter, ctx);
+            }
+
+            var textOut = newEmitter.EmitContext(ctx);
+
+            var dstDir = _FindTargetDirectory(projectPath);
+            var dstPath = System.IO.Path.Combine(dstDir, $"{dstFile}.cs");
+
+            System.IO.File.WriteAllText(dstPath, textOut);
+        }
+
+        private static string _FindTargetDirectory(string dstDir)
+        {
+            var dir = Constants.LocalRepoDirectory;
+
+            while (dir.Length > 3)
+            {
+                var xdir = System.IO.Path.Combine(dir, dstDir);
+                if (System.IO.Directory.Exists(xdir)) return xdir;
+
+                dir = System.IO.Path.GetDirectoryName(dir); // move up
+            }
+
+            return null;
+        }
+    }
+}

+ 15 - 15
build/SharpGLTF.CodeGen/SchemaProcessor.cs → build/SharpGLTF.CodeGen.Core/SchemaProcessor.cs

@@ -1,15 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace SharpGLTF
-{
-    abstract class SchemaProcessor
-    {
-        public virtual string GetTargetProject() { return Constants.TargetProjectDirectory; }
-
-        public abstract IEnumerable<(string TargetFileName, SchemaReflection.SchemaType.Context Schema)> ReadSchema();
-
-        public abstract void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaReflection.SchemaType.Context ctx);
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF
+{
+    public abstract class SchemaProcessor
+    {
+        public virtual string GetTargetProject() { return Constants.TargetProjectDirectory; }
+
+        public abstract IEnumerable<(string TargetFileName, SchemaReflection.SchemaType.Context Schema)> ReadSchema();
+
+        public abstract void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaReflection.SchemaType.Context ctx);
+    }
+}

+ 460 - 460
build/SharpGLTF.CodeGen/SchemaReflection/SchemaTypes.cs → build/SharpGLTF.CodeGen.Core/SchemaReflection/SchemaTypes.cs

@@ -1,460 +1,460 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-
-namespace SharpGLTF.SchemaReflection
-{
-    /// <summary>
-    /// Base class for all schema Types
-    /// </summary>
-    /// <remarks>
-    /// Derived classes:
-    /// - <see cref="StringType"/><br/>
-    /// - <see cref="ObjectType"/><br/>
-    /// - <see cref="BlittableType"/><br/>
-    /// - <see cref="EnumType"/><br/>
-    /// - <see cref="ArrayType"/><br/>
-    /// - <see cref="DictionaryType"/><br/>
-    /// - <see cref="ClassType"/><br/>
-    /// - <see cref="ReferenceType"/><br/>
-    /// </remarks>
-    public abstract partial class SchemaType
-    {
-        #region constructor
-
-        protected SchemaType(Context ctx) { _Owner = ctx; }
-
-        #endregion
-
-        #region data
-
-        /// <summary>
-        /// context where this type is stored
-        /// </summary>
-        private readonly Context _Owner;        
-
-        /// <summary>
-        /// identifier used for serialization and deserialization
-        /// </summary>
-        public abstract string PersistentName { get; }
-
-        /// <summary>
-        /// This is the value usually found in the schema's "$id:"
-        /// </summary>
-        /// <example>
-        /// material.occlusionTextureInfo.schema.json
-        /// </example>
-        public string Identifier { get; set; }
-
-        public String Description { get; set; }
-
-        #endregion
-
-        #region properties
-
-        /// <summary>
-        /// Short version of <see cref="Identifier"/>
-        /// </summary>
-        /// <example>
-        /// occlusionTextureInfo
-        /// </example>
-        public string ShortIdentifier
-        {
-            get
-            {
-                var id = this.Identifier.Replace(".schema.json","", StringComparison.OrdinalIgnoreCase);
-                var idx = id.LastIndexOf('.');
-                return idx < 0 ? id : id.Substring(idx+1);
-            }
-        }
-            
-
-        
-
-        public Context Owner => _Owner;
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Represents a <see cref="String"/> type.
-    /// </summary>
-    [System.Diagnostics.DebuggerDisplay("StringType {PersistentName}")]
-    public sealed class StringType : SchemaType
-    {
-        #region constructor
-
-        internal StringType(Context ctx) : base(ctx) { }
-
-        #endregion
-
-        #region properties
-
-        public override string PersistentName => typeof(String).Name;
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Represents an undefined <see cref="Object"/> type.
-    /// </summary>
-    /// <remarks>
-    /// undefined objects are serialized/deserialized as <see cref="System.Text.Json.Nodes.JsonNode"/>
-    /// </remarks>
-    [System.Diagnostics.DebuggerDisplay("ObjectType {PersistentName}")]
-    public sealed class ObjectType : SchemaType
-    {
-        #region constructor
-
-        internal ObjectType(Context ctx) : base(ctx) { }
-
-        #endregion
-
-        #region properties
-
-        public override string PersistentName => typeof(System.Text.Json.Nodes.JsonNode).FullName;
-
-        #endregion
-    }
-
-    /// <summary>
-    /// Represents a "by value" type <see cref="Boolean"/>, <see cref="Int32"/>, <see cref="Single"/>, etc
-    /// </summary>
-    /// <remarks>
-    /// This type can optionally be set as nullable.
-    /// </remarks>
-    [System.Diagnostics.DebuggerDisplay("BlittableType {PersistentName}")]
-    public sealed class BlittableType : SchemaType
-    {
-        #region constructor        
-
-        internal BlittableType(Context ctx, TypeInfo t, bool isNullable) : base(ctx)
-        {
-            if (t == typeof(String).GetTypeInfo()) isNullable = false;
-
-            _Type = t;
-            _IsNullable = isNullable;
-        }
-
-        #endregion
-
-        #region data
-
-        // https://en.wikipedia.org/wiki/Blittable_types
-
-        private readonly TypeInfo _Type;
-        private readonly Boolean _IsNullable;
-
-        #endregion
-
-        #region properties
-
-        public TypeInfo DataType => _Type;
-
-        public bool IsNullable => _IsNullable;
-
-        public override string PersistentName => _IsNullable ? $"{_Type.Name}?" : _Type.Name;
-
-        #endregion
-    }    
-
-    [System.Diagnostics.DebuggerDisplay("EnumType {PersistentName}")]
-    public sealed class EnumType : SchemaType
-    {
-        #region constructor
-
-        internal EnumType(Context ctx, string name, bool isNullable) : base(ctx)
-        {
-            _PersistentName = name;
-            _IsNullable = isNullable;
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly String _PersistentName;
-        private readonly Boolean _IsNullable;
-
-        private bool _UseIntegers;
-
-        private readonly Dictionary<string, int> _Values = new Dictionary<string, int>();
-
-        #endregion
-
-        #region properties
-
-        public bool IsNullable => _IsNullable;
-
-        public override string PersistentName => _PersistentName;
-        
-        public bool UseIntegers { get => _UseIntegers; set => _UseIntegers = value; }
-
-        public SchemaType ItemType => UseIntegers ? (SchemaType)Owner.UseBlittable(typeof(int).GetTypeInfo()) : Owner.UseString();
-
-        public IEnumerable<KeyValuePair<string, int>> Values => _Values;
-
-        #endregion
-
-        #region API
-
-        public void SetValue(string key, int val) { _Values[key] = val; }
-
-        #endregion
-    }
-
-    [System.Diagnostics.DebuggerDisplay("ArrayType {PersistentName}")]
-    public sealed class ArrayType : SchemaType
-    {
-        #region constructor
-
-        internal ArrayType(Context ctx, SchemaType element) : base(ctx)
-        {
-            _ItemType = element;
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly SchemaType _ItemType;
-
-        public SchemaType ItemType => _ItemType;
-
-        #endregion
-
-        #region properties
-
-        public override string PersistentName => $"{_ItemType.PersistentName}[]";
-
-        #endregion
-    }    
-
-    [System.Diagnostics.DebuggerDisplay("DictionaryType {PersistentName}")]
-    public sealed class DictionaryType : SchemaType
-    {
-        #region lifecycle
-
-        internal DictionaryType(Context ctx, SchemaType key,SchemaType val) : base(ctx)
-        {            
-            _KeyType = key;
-            _ValueType = val;
-        }
-
-        #endregion
-
-        #region data
-        
-        private readonly SchemaType _KeyType;
-        private readonly SchemaType _ValueType;
-
-        #endregion
-
-        #region properties
-
-        public SchemaType KeyType => _KeyType;
-
-        public SchemaType ValueType => _ValueType;
-
-        public override string PersistentName => $"<{_KeyType.PersistentName},{_ValueType.PersistentName}>[]";
-
-        #endregion       
-    }
-
-    /// <summary>
-    /// Represents a field property within a <see cref="ClassType"/>
-    /// </summary>
-    [System.Diagnostics.DebuggerDisplay("FieldInfo {_FieldType} {FieldType.PersistentName} {PersistentName}")]
-    public sealed class FieldInfo
-    {
-        #region lifecycle
-
-        internal FieldInfo(ClassType owner, string name)
-        {
-            _Owner = owner;
-            _PersistentName = name;
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly ClassType _Owner;
-        private readonly String _PersistentName;
-        private SchemaType _FieldType;
-
-        private Object _ExclusiveMinimumValue;
-        private Object _InclusiveMinimumValue;
-
-        private Object _DefaultValue;
-
-        private Object _InclusiveMaximumValue;
-        private Object _ExclusiveMaximumValue;
-
-        private int _MinItems;
-        private int _MaxItems;
-
-        #endregion
-
-        #region properties
-
-        public ClassType DeclaringClass => _Owner;
-
-        public String Description { get; set; }
-
-        public String PersistentName => _PersistentName;
-
-        public SchemaType FieldType { get => _FieldType; set => _FieldType = value; }
-        
-        public Object ExclusiveMinimumValue { get => _ExclusiveMinimumValue; set => _ExclusiveMinimumValue = value; }
-        public Object InclusiveMinimumValue { get => _InclusiveMinimumValue; set => _InclusiveMinimumValue = value; }
-        public Object DefaultValue { get => _DefaultValue; set => _DefaultValue = value; }
-        public Object InclusiveMaximumValue { get => _InclusiveMaximumValue; set => _InclusiveMaximumValue = value; }
-        public Object ExclusiveMaximumValue { get => _ExclusiveMaximumValue; set => _ExclusiveMaximumValue = value; }
-
-        public int MinItems { get => _MinItems; set => _MinItems = value; }
-        public int MaxItems { get => _MaxItems; set => _MaxItems = value; }
-
-        #endregion
-
-        #region fluent api
-
-        public FieldInfo SetDataType(SchemaType type) { _FieldType = type; return this; }
-
-        public FieldInfo SetDataType(Type type, bool isNullable)
-        {
-            if (type == typeof(string)) { _FieldType = DeclaringClass.Owner.UseString(); return this; }
-
-            _FieldType = DeclaringClass.Owner.UseBlittable(type.GetTypeInfo(), isNullable);
-            return this;
-        }
-
-        public FieldInfo RemoveDefaultValue() { _DefaultValue = null; return this; }
-
-        public FieldInfo SetDefaultValue(string defval) { _DefaultValue = defval; return this; }
-
-        public FieldInfo SetLimits(Decimal? min, Decimal? max) { _InclusiveMinimumValue = min; _InclusiveMaximumValue = max; return this; }
-
-        public FieldInfo SetItemsRange(int min, int max = int.MaxValue) { _MinItems = min; _MaxItems = max; return this; }
-
-        #endregion
-
-        #region comparer helper
-
-        private sealed class _Comparer : IEqualityComparer<FieldInfo> , IComparer<FieldInfo>
-        {
-            public int Compare(FieldInfo x, FieldInfo y)
-            {
-                var xx = _Adjust(x._PersistentName);
-                var yy = _Adjust(y._PersistentName);
-
-                return string.CompareOrdinal(xx, yy);
-            }
-
-            private static string _Adjust(string name)
-            {
-                if (name.StartsWith("asset")) return "____" + name;
-                if (name.StartsWith("extensions")) return "___" + name;
-                return name;
-            }
-
-            public bool Equals(FieldInfo x, FieldInfo y) { return Compare(x,y) == 0; }
-
-            public int GetHashCode(FieldInfo obj) { return obj._PersistentName.GetHashCode(StringComparison.Ordinal); }
-        }
-
-        private static readonly _Comparer _DefaultComparer = new _Comparer();
-
-        public static IEqualityComparer<FieldInfo> EqualityComparer => _DefaultComparer;
-
-        public static IComparer<FieldInfo> Comparer => _DefaultComparer;
-
-        #endregion
-    }
-
-    [System.Diagnostics.DebuggerDisplay("ClassType {PersistentName} : {BaseClass.PersistentName}")]
-    public sealed class ClassType : SchemaType
-    {
-        #region constructor
-
-        internal ClassType(Context ctx, string name) : base(ctx)
-        {
-            _PersistentName = name;            
-        }
-
-        #endregion
-
-        #region data
-
-        private readonly String _PersistentName;        
-
-        private readonly SortedSet<FieldInfo> _Fields = new SortedSet<FieldInfo>(FieldInfo.Comparer);
-
-        private ClassType _BaseClass;        
-
-        /// <summary>
-        /// True to prevent to codegen emitter to emit this class
-        /// </summary>
-        public bool IgnoredByEmitter { get; set; }
-
-        #endregion
-
-        #region properties
-        public override string PersistentName => _PersistentName;
-        public IEnumerable<FieldInfo> Fields => _Fields;
-        public ClassType BaseClass { get => _BaseClass; set => _BaseClass = value; }
-
-        #endregion
-
-        #region API
-
-        public FieldInfo GetField(string name)
-        {
-            return _Fields.First(item => item.PersistentName == name);
-        }
-
-        public FieldInfo UseField(string name)
-        {
-            var f = new FieldInfo(this, name);
-
-            _Fields.Add(f);
-
-            return GetField(name);
-        }
-
-        #endregion
-    }
-
-    /// <summary>
-    /// not used
-    /// </summary>
-    public sealed class ReferenceType : SchemaType
-    {
-        #region constructor
-
-        internal ReferenceType(Context ctx, SchemaType refType) : base(ctx)
-        {
-            _ReferencedType = refType;
-        }
-
-        #endregion
-
-        #region data
-
-        // In code it has the representation List<Node>();
-        // In serialization, it has the representation List<int>();
-
-        private readonly SchemaType _ReferencedType;
-
-        #pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
-        public override string PersistentName => throw new NotImplementedException();
-        #pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
-
-        #endregion
-    }
-
-        
-
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace SharpGLTF.SchemaReflection
+{
+    /// <summary>
+    /// Base class for all schema Types
+    /// </summary>
+    /// <remarks>
+    /// Derived classes:
+    /// - <see cref="StringType"/><br/>
+    /// - <see cref="ObjectType"/><br/>
+    /// - <see cref="BlittableType"/><br/>
+    /// - <see cref="EnumType"/><br/>
+    /// - <see cref="ArrayType"/><br/>
+    /// - <see cref="DictionaryType"/><br/>
+    /// - <see cref="ClassType"/><br/>
+    /// - <see cref="ReferenceType"/><br/>
+    /// </remarks>
+    public abstract partial class SchemaType
+    {
+        #region constructor
+
+        protected SchemaType(Context ctx) { _Owner = ctx; }
+
+        #endregion
+
+        #region data
+
+        /// <summary>
+        /// context where this type is stored
+        /// </summary>
+        private readonly Context _Owner;        
+
+        /// <summary>
+        /// identifier used for serialization and deserialization
+        /// </summary>
+        public abstract string PersistentName { get; }
+
+        /// <summary>
+        /// This is the value usually found in the schema's "$id:"
+        /// </summary>
+        /// <example>
+        /// material.occlusionTextureInfo.schema.json
+        /// </example>
+        public string Identifier { get; set; }
+
+        public String Description { get; set; }
+
+        #endregion
+
+        #region properties
+
+        /// <summary>
+        /// Short version of <see cref="Identifier"/>
+        /// </summary>
+        /// <example>
+        /// occlusionTextureInfo
+        /// </example>
+        public string ShortIdentifier
+        {
+            get
+            {
+                var id = this.Identifier.Replace(".schema.json","", StringComparison.OrdinalIgnoreCase);
+                var idx = id.LastIndexOf('.');
+                return idx < 0 ? id : id.Substring(idx+1);
+            }
+        }
+            
+
+        
+
+        public Context Owner => _Owner;
+
+        #endregion
+    }
+
+    /// <summary>
+    /// Represents a <see cref="String"/> type.
+    /// </summary>
+    [System.Diagnostics.DebuggerDisplay("StringType {PersistentName}")]
+    public sealed class StringType : SchemaType
+    {
+        #region constructor
+
+        internal StringType(Context ctx) : base(ctx) { }
+
+        #endregion
+
+        #region properties
+
+        public override string PersistentName => typeof(String).Name;
+
+        #endregion
+    }
+
+    /// <summary>
+    /// Represents an undefined <see cref="Object"/> type.
+    /// </summary>
+    /// <remarks>
+    /// undefined objects are serialized/deserialized as <see cref="System.Text.Json.Nodes.JsonNode"/>
+    /// </remarks>
+    [System.Diagnostics.DebuggerDisplay("ObjectType {PersistentName}")]
+    public sealed class ObjectType : SchemaType
+    {
+        #region constructor
+
+        internal ObjectType(Context ctx) : base(ctx) { }
+
+        #endregion
+
+        #region properties
+
+        public override string PersistentName => typeof(System.Text.Json.Nodes.JsonNode).FullName;
+
+        #endregion
+    }
+
+    /// <summary>
+    /// Represents a "by value" type <see cref="Boolean"/>, <see cref="Int32"/>, <see cref="Single"/>, etc
+    /// </summary>
+    /// <remarks>
+    /// This type can optionally be set as nullable.
+    /// </remarks>
+    [System.Diagnostics.DebuggerDisplay("BlittableType {PersistentName}")]
+    public sealed class BlittableType : SchemaType
+    {
+        #region constructor        
+
+        internal BlittableType(Context ctx, TypeInfo t, bool isNullable) : base(ctx)
+        {
+            if (t == typeof(String).GetTypeInfo()) isNullable = false;
+
+            _Type = t;
+            _IsNullable = isNullable;
+        }
+
+        #endregion
+
+        #region data
+
+        // https://en.wikipedia.org/wiki/Blittable_types
+
+        private readonly TypeInfo _Type;
+        private readonly Boolean _IsNullable;
+
+        #endregion
+
+        #region properties
+
+        public TypeInfo DataType => _Type;
+
+        public bool IsNullable => _IsNullable;
+
+        public override string PersistentName => _IsNullable ? $"{_Type.Name}?" : _Type.Name;
+
+        #endregion
+    }    
+
+    [System.Diagnostics.DebuggerDisplay("EnumType {PersistentName}")]
+    public sealed class EnumType : SchemaType
+    {
+        #region constructor
+
+        internal EnumType(Context ctx, string name, bool isNullable) : base(ctx)
+        {
+            _PersistentName = name;
+            _IsNullable = isNullable;
+        }
+
+        #endregion
+
+        #region data
+
+        private readonly String _PersistentName;
+        private readonly Boolean _IsNullable;
+
+        private bool _UseIntegers;
+
+        private readonly Dictionary<string, int> _Values = new Dictionary<string, int>();
+
+        #endregion
+
+        #region properties
+
+        public bool IsNullable => _IsNullable;
+
+        public override string PersistentName => _PersistentName;
+        
+        public bool UseIntegers { get => _UseIntegers; set => _UseIntegers = value; }
+
+        public SchemaType ItemType => UseIntegers ? (SchemaType)Owner.UseBlittable(typeof(int).GetTypeInfo()) : Owner.UseString();
+
+        public IEnumerable<KeyValuePair<string, int>> Values => _Values;
+
+        #endregion
+
+        #region API
+
+        public void SetValue(string key, int val) { _Values[key] = val; }
+
+        #endregion
+    }
+
+    [System.Diagnostics.DebuggerDisplay("ArrayType {PersistentName}")]
+    public sealed class ArrayType : SchemaType
+    {
+        #region constructor
+
+        internal ArrayType(Context ctx, SchemaType element) : base(ctx)
+        {
+            _ItemType = element;
+        }
+
+        #endregion
+
+        #region data
+
+        private readonly SchemaType _ItemType;
+
+        public SchemaType ItemType => _ItemType;
+
+        #endregion
+
+        #region properties
+
+        public override string PersistentName => $"{_ItemType.PersistentName}[]";
+
+        #endregion
+    }    
+
+    [System.Diagnostics.DebuggerDisplay("DictionaryType {PersistentName}")]
+    public sealed class DictionaryType : SchemaType
+    {
+        #region lifecycle
+
+        internal DictionaryType(Context ctx, SchemaType key,SchemaType val) : base(ctx)
+        {            
+            _KeyType = key;
+            _ValueType = val;
+        }
+
+        #endregion
+
+        #region data
+        
+        private readonly SchemaType _KeyType;
+        private readonly SchemaType _ValueType;
+
+        #endregion
+
+        #region properties
+
+        public SchemaType KeyType => _KeyType;
+
+        public SchemaType ValueType => _ValueType;
+
+        public override string PersistentName => $"<{_KeyType.PersistentName},{_ValueType.PersistentName}>[]";
+
+        #endregion       
+    }
+
+    /// <summary>
+    /// Represents a field property within a <see cref="ClassType"/>
+    /// </summary>
+    [System.Diagnostics.DebuggerDisplay("FieldInfo {_FieldType} {FieldType.PersistentName} {PersistentName}")]
+    public sealed class FieldInfo
+    {
+        #region lifecycle
+
+        internal FieldInfo(ClassType owner, string name)
+        {
+            _Owner = owner;
+            _PersistentName = name;
+        }
+
+        #endregion
+
+        #region data
+
+        private readonly ClassType _Owner;
+        private readonly String _PersistentName;
+        private SchemaType _FieldType;
+
+        private Object _ExclusiveMinimumValue;
+        private Object _InclusiveMinimumValue;
+
+        private Object _DefaultValue;
+
+        private Object _InclusiveMaximumValue;
+        private Object _ExclusiveMaximumValue;
+
+        private int _MinItems;
+        private int _MaxItems;
+
+        #endregion
+
+        #region properties
+
+        public ClassType DeclaringClass => _Owner;
+
+        public String Description { get; set; }
+
+        public String PersistentName => _PersistentName;
+
+        public SchemaType FieldType { get => _FieldType; set => _FieldType = value; }
+        
+        public Object ExclusiveMinimumValue { get => _ExclusiveMinimumValue; set => _ExclusiveMinimumValue = value; }
+        public Object InclusiveMinimumValue { get => _InclusiveMinimumValue; set => _InclusiveMinimumValue = value; }
+        public Object DefaultValue { get => _DefaultValue; set => _DefaultValue = value; }
+        public Object InclusiveMaximumValue { get => _InclusiveMaximumValue; set => _InclusiveMaximumValue = value; }
+        public Object ExclusiveMaximumValue { get => _ExclusiveMaximumValue; set => _ExclusiveMaximumValue = value; }
+
+        public int MinItems { get => _MinItems; set => _MinItems = value; }
+        public int MaxItems { get => _MaxItems; set => _MaxItems = value; }
+
+        #endregion
+
+        #region fluent api
+
+        public FieldInfo SetDataType(SchemaType type) { _FieldType = type; return this; }
+
+        public FieldInfo SetDataType(Type type, bool isNullable)
+        {
+            if (type == typeof(string)) { _FieldType = DeclaringClass.Owner.UseString(); return this; }
+
+            _FieldType = DeclaringClass.Owner.UseBlittable(type.GetTypeInfo(), isNullable);
+            return this;
+        }
+
+        public FieldInfo RemoveDefaultValue() { _DefaultValue = null; return this; }
+
+        public FieldInfo SetDefaultValue(string defval) { _DefaultValue = defval; return this; }
+
+        public FieldInfo SetLimits(Decimal? min, Decimal? max) { _InclusiveMinimumValue = min; _InclusiveMaximumValue = max; return this; }
+
+        public FieldInfo SetItemsRange(int min, int max = int.MaxValue) { _MinItems = min; _MaxItems = max; return this; }
+
+        #endregion
+
+        #region comparer helper
+
+        private sealed class _Comparer : IEqualityComparer<FieldInfo> , IComparer<FieldInfo>
+        {
+            public int Compare(FieldInfo x, FieldInfo y)
+            {
+                var xx = _Adjust(x._PersistentName);
+                var yy = _Adjust(y._PersistentName);
+
+                return string.CompareOrdinal(xx, yy);
+            }
+
+            private static string _Adjust(string name)
+            {
+                if (name.StartsWith("asset")) return "____" + name;
+                if (name.StartsWith("extensions")) return "___" + name;
+                return name;
+            }
+
+            public bool Equals(FieldInfo x, FieldInfo y) { return Compare(x,y) == 0; }
+
+            public int GetHashCode(FieldInfo obj) { return obj._PersistentName.GetHashCode(StringComparison.Ordinal); }
+        }
+
+        private static readonly _Comparer _DefaultComparer = new _Comparer();
+
+        public static IEqualityComparer<FieldInfo> EqualityComparer => _DefaultComparer;
+
+        public static IComparer<FieldInfo> Comparer => _DefaultComparer;
+
+        #endregion
+    }
+
+    [System.Diagnostics.DebuggerDisplay("ClassType {PersistentName} : {BaseClass.PersistentName}")]
+    public sealed class ClassType : SchemaType
+    {
+        #region constructor
+
+        internal ClassType(Context ctx, string name) : base(ctx)
+        {
+            _PersistentName = name;            
+        }
+
+        #endregion
+
+        #region data
+
+        private readonly String _PersistentName;        
+
+        private readonly SortedSet<FieldInfo> _Fields = new SortedSet<FieldInfo>(FieldInfo.Comparer);
+
+        private ClassType _BaseClass;        
+
+        /// <summary>
+        /// True to prevent to codegen emitter to emit this class
+        /// </summary>
+        public bool IgnoredByEmitter { get; set; }
+
+        #endregion
+
+        #region properties
+        public override string PersistentName => _PersistentName;
+        public IEnumerable<FieldInfo> Fields => _Fields;
+        public ClassType BaseClass { get => _BaseClass; set => _BaseClass = value; }
+
+        #endregion
+
+        #region API
+
+        public FieldInfo GetField(string name)
+        {
+            return _Fields.First(item => item.PersistentName == name);
+        }
+
+        public FieldInfo UseField(string name)
+        {
+            var f = new FieldInfo(this, name);
+
+            _Fields.Add(f);
+
+            return GetField(name);
+        }
+
+        #endregion
+    }
+
+    /// <summary>
+    /// not used
+    /// </summary>
+    public sealed class ReferenceType : SchemaType
+    {
+        #region constructor
+
+        internal ReferenceType(Context ctx, SchemaType refType) : base(ctx)
+        {
+            _ReferencedType = refType;
+        }
+
+        #endregion
+
+        #region data
+
+        // In code it has the representation List<Node>();
+        // In serialization, it has the representation List<int>();
+
+        private readonly SchemaType _ReferencedType;
+
+        #pragma warning disable CA1065 // Do not raise exceptions in unexpected locations
+        public override string PersistentName => throw new NotImplementedException();
+        #pragma warning restore CA1065 // Do not raise exceptions in unexpected locations
+
+        #endregion
+    }
+
+        
+
+}

+ 112 - 112
build/SharpGLTF.CodeGen/SchemaReflection/SchemaTypesContext.cs → build/SharpGLTF.CodeGen.Core/SchemaReflection/SchemaTypesContext.cs

@@ -1,112 +1,112 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-
-namespace SharpGLTF.SchemaReflection
-{
-    public partial class SchemaType
-    {
-        /// <summary>
-        /// Collection class that contains all the types found in a json schema.
-        /// </summary>
-        public sealed class Context
-        {
-            #region data
-
-            private readonly Dictionary<string, SchemaType> _Types = new Dictionary<string, SchemaType>();            
-
-            #endregion
-
-            #region properties
-
-            /// <summary>
-            /// returns all the <see cref="enum"/> types.
-            /// </summary>
-            public IEnumerable<EnumType> Enumerations => _Types.Values.OfType<EnumType>();
-
-            /// <summary>
-            /// returns all the <see cref="class"/> types.
-            /// </summary>
-            public IEnumerable<ClassType> Classes => _Types.Values.OfType<ClassType>();
-
-            #endregion
-
-            #region API
-
-            /// <summary>
-            /// Creates a new type or uses an existing one if it already exists.
-            /// </summary>
-            /// <param name="item">a newly created type</param>
-            /// <returns>A stored type if it already exist, or the newly created type</returns>
-            private SchemaType _UseOrCreate(SchemaType item)
-            {
-                if (_Types.TryGetValue(item.PersistentName, out SchemaType value)) return value;
-
-                _Types[item.PersistentName] = item;
-
-                return item;
-            }
-
-            public ObjectType UseAnyType() { return (ObjectType)_UseOrCreate( new ObjectType(this) ); }
-
-            public StringType UseString() { return (StringType)_UseOrCreate( new StringType(this) ); }
-
-            public EnumType FindEnum(string persistentName) { return Enumerations.FirstOrDefault(item => item.PersistentName == persistentName); }
-
-            public ArrayType UseArray(SchemaType elementType) { return (ArrayType)_UseOrCreate( new ArrayType(this, elementType) ); }
-
-            public ClassType FindClass(string persistentName) { return Classes.FirstOrDefault(item => item.PersistentName == persistentName); }
-
-            public ClassType UseClass(string name) { return (ClassType)_UseOrCreate(new ClassType(this, name)); }
-
-            public BlittableType UseBlittable(TypeInfo t, bool isNullable = false)
-            {
-                if (t == null || !t.IsValueType) throw new ArgumentException(nameof(t));
-
-                var item = new BlittableType(this, t, isNullable);
-                return (BlittableType)_UseOrCreate(item);
-            }
-
-            public EnumType UseEnum(string name, bool isNullable = false)
-            {
-                var item = new EnumType(this, name, isNullable);
-                return (EnumType)_UseOrCreate(item);
-            }
-
-            public EnumType GetEnum(string name)
-            {
-                return _Types.TryGetValue(name, out SchemaType etype) ? etype as EnumType : null;
-            }            
-
-            public DictionaryType UseDictionary(SchemaType key, SchemaType val)
-            {                
-                return (DictionaryType)_UseOrCreate( new DictionaryType(this, key, val) );
-            }            
-
-            public void Remove(SchemaType type) { _Types.Remove(type.PersistentName); }
-
-            public void Remove(string persistentName) { _Types.Remove(persistentName); }
-
-            public void IgnoredByCodeEmitter(string persistentName)
-            {
-                var ct = Classes.FirstOrDefault(item => item.PersistentName == persistentName);
-
-                if (ct != null) ct.IgnoredByEmitter = true;            
-            }
-
-            public void IgnoredByCodeEmittierMainSchema()
-            {
-                IgnoredByCodeEmitter("glTF Property");                
-                IgnoredByCodeEmitter("glTF Child of Root Property");
-                IgnoredByCodeEmitter("Texture Info");
-                IgnoredByCodeEmitter("Material Normal Texture Info");
-            }
-
-
-
-            #endregion
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace SharpGLTF.SchemaReflection
+{
+    public partial class SchemaType
+    {
+        /// <summary>
+        /// Collection class that contains all the types found in a json schema.
+        /// </summary>
+        public sealed class Context
+        {
+            #region data
+
+            private readonly Dictionary<string, SchemaType> _Types = new Dictionary<string, SchemaType>();            
+
+            #endregion
+
+            #region properties
+
+            /// <summary>
+            /// returns all the <see cref="enum"/> types.
+            /// </summary>
+            public IEnumerable<EnumType> Enumerations => _Types.Values.OfType<EnumType>();
+
+            /// <summary>
+            /// returns all the <see cref="class"/> types.
+            /// </summary>
+            public IEnumerable<ClassType> Classes => _Types.Values.OfType<ClassType>();
+
+            #endregion
+
+            #region API
+
+            /// <summary>
+            /// Creates a new type or uses an existing one if it already exists.
+            /// </summary>
+            /// <param name="item">a newly created type</param>
+            /// <returns>A stored type if it already exist, or the newly created type</returns>
+            private SchemaType _UseOrCreate(SchemaType item)
+            {
+                if (_Types.TryGetValue(item.PersistentName, out SchemaType value)) return value;
+
+                _Types[item.PersistentName] = item;
+
+                return item;
+            }
+
+            public ObjectType UseAnyType() { return (ObjectType)_UseOrCreate( new ObjectType(this) ); }
+
+            public StringType UseString() { return (StringType)_UseOrCreate( new StringType(this) ); }
+
+            public EnumType FindEnum(string persistentName) { return Enumerations.FirstOrDefault(item => item.PersistentName == persistentName); }
+
+            public ArrayType UseArray(SchemaType elementType) { return (ArrayType)_UseOrCreate( new ArrayType(this, elementType) ); }
+
+            public ClassType FindClass(string persistentName) { return Classes.FirstOrDefault(item => item.PersistentName == persistentName); }
+
+            public ClassType UseClass(string name) { return (ClassType)_UseOrCreate(new ClassType(this, name)); }
+
+            public BlittableType UseBlittable(TypeInfo t, bool isNullable = false)
+            {
+                if (t == null || !t.IsValueType) throw new ArgumentException(nameof(t));
+
+                var item = new BlittableType(this, t, isNullable);
+                return (BlittableType)_UseOrCreate(item);
+            }
+
+            public EnumType UseEnum(string name, bool isNullable = false)
+            {
+                var item = new EnumType(this, name, isNullable);
+                return (EnumType)_UseOrCreate(item);
+            }
+
+            public EnumType GetEnum(string name)
+            {
+                return _Types.TryGetValue(name, out SchemaType etype) ? etype as EnumType : null;
+            }            
+
+            public DictionaryType UseDictionary(SchemaType key, SchemaType val)
+            {                
+                return (DictionaryType)_UseOrCreate( new DictionaryType(this, key, val) );
+            }            
+
+            public void Remove(SchemaType type) { _Types.Remove(type.PersistentName); }
+
+            public void Remove(string persistentName) { _Types.Remove(persistentName); }
+
+            public void IgnoredByCodeEmitter(string persistentName)
+            {
+                var ct = Classes.FirstOrDefault(item => item.PersistentName == persistentName);
+
+                if (ct != null) ct.IgnoredByEmitter = true;            
+            }
+
+            public void IgnoredByCodeEmittierMainSchema()
+            {
+                IgnoredByCodeEmitter("glTF Property");                
+                IgnoredByCodeEmitter("glTF Child of Root Property");
+                IgnoredByCodeEmitter("Texture Info");
+                IgnoredByCodeEmitter("Material Normal Texture Info");
+            }
+
+
+
+            #endregion
+        }
+    }
+}

+ 299 - 299
build/SharpGLTF.CodeGen/SchemaReflection/SchemaTypesReader.cs → build/SharpGLTF.CodeGen.Core/SchemaReflection/SchemaTypesReader.cs

@@ -1,299 +1,299 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-
-using JSONSCHEMA = NJsonSchema.JsonSchema;
-
-namespace SharpGLTF.SchemaReflection
-{
-    /// <summary>
-    /// Utility class that reads a json schema and creates a <see cref="SchemaType.Context"/>
-    /// Which is a collection of Schema Types resembling <see cref="System.Type"/>
-    /// </summary>
-    static class SchemaTypesReader
-    {
-        // issues related to gltf2 schema parsing:
-        // https://github.com/RSuter/NJsonSchema
-        // https://github.com/RSuter/NJsonSchema/issues/378
-        // https://github.com/RSuter/NJsonSchema/issues/377
-
-        #region API
-
-        public static SchemaType.Context Generate(NJsonSchema.CodeGeneration.CSharp.CSharpTypeResolver types)
-        {
-            var context = new SchemaType.Context();
-
-            foreach(var t in types.Types.Keys)
-            {
-                context._UseType(t);
-            }
-
-            return context;
-        }
-
-        #endregion
-
-        #region core
-
-        private static SchemaType _UseType(this SchemaType.Context ctx, JSONSCHEMA schema, bool isRequired = true)
-        {
-            ArgumentNullException.ThrowIfNull(ctx);
-            ArgumentNullException.ThrowIfNull(schema);
-
-            if (schema is NJsonSchema.JsonSchemaProperty prop)
-            {
-                // System.Diagnostics.Debug.Assert(prop.Name != "scene");
-
-                isRequired &= prop.IsRequired;                
-            }
-
-            if (_IsStringType(schema))
-            {
-                return ctx.UseString();
-            }
-
-            if (_IsBlittableType(schema))
-            {
-                bool isNullable = !isRequired;
-
-                if (schema.Type == NJsonSchema.JsonObjectType.Integer) return ctx.UseBlittable(typeof(Int32).GetTypeInfo(), isNullable);
-                if (schema.Type == NJsonSchema.JsonObjectType.Number) return ctx.UseBlittable(typeof(Double).GetTypeInfo(), isNullable);
-                if (schema.Type == NJsonSchema.JsonObjectType.Boolean) return ctx.UseBlittable(typeof(Boolean).GetTypeInfo(), isNullable);                
-                throw new NotImplementedException();
-            }            
-
-            if (schema.HasReference) return ctx._UseType(schema.ActualTypeSchema, isRequired); // we could have our own ref
-
-            if (schema.IsArray)
-            {
-                return ctx.UseArray(ctx._UseType(schema.Item.ActualSchema));
-            }
-
-            if (_IsEnumeration(schema))
-            {
-                if (schema is NJsonSchema.JsonSchemaProperty property)
-                {
-                    bool isNullable = !isRequired;
-
-                    var dict = new Dictionary<string, Int64>();
-
-                    foreach (var v in property.AnyOf)
-                    {
-                        var key = v.Description;
-                        var val = v.Enumeration?.FirstOrDefault();
-                        var ext = v.ExtensionData?.FirstOrDefault() ?? default;                        
-
-                        if (val is String txt)
-                        {
-                            System.Diagnostics.Debug.Assert(v.Type == NJsonSchema.JsonObjectType.None);
-
-                            key = txt; val = (Int64)0;
-                        }
-
-                        if (v.Type == NJsonSchema.JsonObjectType.None && ext.Key == "const")
-                        {
-                            key = (string)ext.Value; val = (Int64)0;
-                        }
-
-                        if (v.Type == NJsonSchema.JsonObjectType.Integer && ext.Key == "const")
-                        {
-                            val = (Int64)ext.Value;
-                        }
-
-                        System.Diagnostics.Debug.Assert(key != null || dict.Count > 0);
-
-                        if (string.IsNullOrWhiteSpace(key)) continue;
-
-                        dict[key] = (Int64)val;
-                    }
-
-                    // JSon Schema AnyOf enumerations are basically anonymous, so we create
-                    // a "shared name" with a concatenation of all the values:
-
-                    var name = string.Join("-", dict.Keys.OrderBy(item => item));                    
-
-                    var etype = ctx.UseEnum(name, isNullable);
-
-                    etype.Identifier = _GetSchemaIdentifier(schema);
-                    etype.Description = schema.Description;
-
-                    foreach (var kvp in dict) etype.SetValue(kvp.Key, (int)kvp.Value);
-
-                    if (dict.Values.Distinct().Count() > 1) etype.UseIntegers = true;                    
-
-                    return etype;
-                }
-
-                throw new NotImplementedException();                
-            }
-
-            if (_IsDictionary(schema))
-            {
-                var key = ctx.UseString();
-                var val = ctx._UseType(_GetDictionaryValue(schema));
-
-                return ctx.UseDictionary(key, val);
-            }
-
-            if (_IsClass(schema))
-            {
-                var classDecl = ctx.UseClass(schema.Title);
-
-                classDecl.Identifier = _GetSchemaIdentifier(schema);
-                classDecl.Description = schema.Description;
-
-                // process base class                
-
-                if (schema.InheritedSchema != null) classDecl.BaseClass = ctx._UseType(schema.InheritedSchema) as ClassType;
-
-                // filter declared properties
-
-                var keys = _GetProperyNames(schema);
-                if (schema.InheritedSchema != null) // filter our parent properties
-                {
-                    var baseKeys = _GetInheritedPropertyNames(schema).ToArray();
-                    keys = keys.Except(baseKeys).ToArray();
-                }
-                
-                // process declared properties
-
-                var props = keys.Select(key => schema.Properties.Values.FirstOrDefault(item => item.Name == key));
-
-                var required = schema.RequiredProperties;
-
-                // System.Diagnostics.Debug.Assert(schema.Title != "Buffer View");
-
-                foreach(var p in props)
-                {
-                    var field = classDecl.UseField(p.Name);
-
-                    field.Description = p.Description;
-
-                    field.FieldType = ctx._UseType(p, required.Contains(p.Name));
-
-                    field.ExclusiveMinimumValue = p.ExclusiveMinimum ?? (p.IsExclusiveMinimum ? p.Minimum : null);
-                    field.InclusiveMinimumValue = p.IsExclusiveMinimum ? null : p.Minimum;
-                    field.DefaultValue = p.Default;
-                    field.InclusiveMaximumValue = p.IsExclusiveMaximum ? null : p.Maximum;
-                    field.ExclusiveMaximumValue = p.ExclusiveMaximum ?? (p.IsExclusiveMaximum ? p.Maximum : null);
-
-                    field.MinItems = p.MinItems;
-                    field.MaxItems = p.MaxItems;
-                }
-
-
-                return classDecl;
-            }
-
-            if (schema.Type == NJsonSchema.JsonObjectType.Object) return ctx.UseAnyType();
-
-            if (schema.Type == NJsonSchema.JsonObjectType.None) return ctx.UseAnyType();
-
-            throw new NotImplementedException();
-        }
-
-        private static string _GetSchemaIdentifier(JSONSCHEMA schema)
-        {
-            if (schema.ExtensionData != null)
-            {
-                if (schema.ExtensionData.TryGetValue("$id", out var value) && value is string id)
-                {
-                    return id;
-                }
-            }
-
-            if (!string.IsNullOrWhiteSpace(schema.DocumentPath))
-            {
-                return System.IO.Path.GetFileName(schema.DocumentPath);
-            }
-
-            return null;
-
-            
-        }
-
-        private static bool _IsBlittableType(JSONSCHEMA schema)
-        {
-            if (schema == null) return false;
-            if (schema.Type == NJsonSchema.JsonObjectType.Boolean) return true;
-            if (schema.Type == NJsonSchema.JsonObjectType.Number) return true;
-            if (schema.Type == NJsonSchema.JsonObjectType.Integer) return true;            
-
-            return false;
-        }        
-
-        private static bool _IsStringType(JSONSCHEMA schema)
-        {
-            return schema.Type == NJsonSchema.JsonObjectType.String;
-        }
-
-        private static bool _IsEnumeration(JSONSCHEMA schema)
-        {
-            if (schema.Type != NJsonSchema.JsonObjectType.None) return false;
-
-            if (schema.IsArray || schema.IsDictionary) return false;
-
-            if (schema.AnyOf.Count == 0) return false;
-
-            // if (!schema.IsEnumeration) return false; // useless
-
-            return true;
-        }
-
-        private static bool _IsDictionary(JSONSCHEMA schema)
-        {
-            // if (schema.Type != NJsonSchema.JsonObjectType.Object) return false;
-
-            if (schema.AdditionalPropertiesSchema != null) return true;
-            if (schema.AllowAdditionalProperties == false && schema.PatternProperties.Any()) return true;            
-
-            return false;
-        }        
-
-        private static JSONSCHEMA _GetDictionaryValue(JSONSCHEMA schema)
-        {
-            if (schema.AdditionalPropertiesSchema != null)
-            {
-                return schema.AdditionalPropertiesSchema;
-            }
-
-            if (schema.AllowAdditionalProperties == false && schema.PatternProperties.Any())
-            {
-                var valueTypes = schema.PatternProperties.Values.ToArray();
-
-                if (valueTypes.Length == 1) return valueTypes.First();
-            }
-
-            throw new NotImplementedException();
-        }
-
-        private static bool _IsClass(JSONSCHEMA schema)
-        {
-            if (schema.Type != NJsonSchema.JsonObjectType.Object) return false;
-            
-            return !string.IsNullOrWhiteSpace(schema.Title);            
-        }
-
-        private static string[] _GetProperyNames(JSONSCHEMA schema)
-        {
-            return schema
-                    .Properties
-                    .Values
-                    .Select(item => item.Name)
-                    .ToArray();
-        }
-
-        private static string[] _GetInheritedPropertyNames(JSONSCHEMA schema)
-        {
-            if (schema?.InheritedSchema == null) return Enumerable.Empty<string>().ToArray();
-
-            return _GetInheritedPropertyNames(schema.InheritedSchema)
-                .Concat(_GetProperyNames(schema.InheritedSchema))
-                .ToArray();
-        }
-
-        #endregion
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+using JSONSCHEMA = NJsonSchema.JsonSchema;
+
+namespace SharpGLTF.SchemaReflection
+{
+    /// <summary>
+    /// Utility class that reads a json schema and creates a <see cref="SchemaType.Context"/>
+    /// Which is a collection of Schema Types resembling <see cref="System.Type"/>
+    /// </summary>
+    static class SchemaTypesReader
+    {
+        // issues related to gltf2 schema parsing:
+        // https://github.com/RSuter/NJsonSchema
+        // https://github.com/RSuter/NJsonSchema/issues/378
+        // https://github.com/RSuter/NJsonSchema/issues/377
+
+        #region API
+
+        public static SchemaType.Context Generate(NJsonSchema.CodeGeneration.CSharp.CSharpTypeResolver types)
+        {
+            var context = new SchemaType.Context();
+
+            foreach(var t in types.Types.Keys)
+            {
+                context._UseType(t);
+            }
+
+            return context;
+        }
+
+        #endregion
+
+        #region core
+
+        private static SchemaType _UseType(this SchemaType.Context ctx, JSONSCHEMA schema, bool isRequired = true)
+        {
+            ArgumentNullException.ThrowIfNull(ctx);
+            ArgumentNullException.ThrowIfNull(schema);
+
+            if (schema is NJsonSchema.JsonSchemaProperty prop)
+            {
+                // System.Diagnostics.Debug.Assert(prop.Name != "scene");
+
+                isRequired &= prop.IsRequired;                
+            }
+
+            if (_IsStringType(schema))
+            {
+                return ctx.UseString();
+            }
+
+            if (_IsBlittableType(schema))
+            {
+                bool isNullable = !isRequired;
+
+                if (schema.Type == NJsonSchema.JsonObjectType.Integer) return ctx.UseBlittable(typeof(Int32).GetTypeInfo(), isNullable);
+                if (schema.Type == NJsonSchema.JsonObjectType.Number) return ctx.UseBlittable(typeof(Double).GetTypeInfo(), isNullable);
+                if (schema.Type == NJsonSchema.JsonObjectType.Boolean) return ctx.UseBlittable(typeof(Boolean).GetTypeInfo(), isNullable);                
+                throw new NotImplementedException();
+            }            
+
+            if (schema.HasReference) return ctx._UseType(schema.ActualTypeSchema, isRequired); // we could have our own ref
+
+            if (schema.IsArray)
+            {
+                return ctx.UseArray(ctx._UseType(schema.Item.ActualSchema));
+            }
+
+            if (_IsEnumeration(schema))
+            {
+                if (schema is NJsonSchema.JsonSchemaProperty property)
+                {
+                    bool isNullable = !isRequired;
+
+                    var dict = new Dictionary<string, Int64>();
+
+                    foreach (var v in property.AnyOf)
+                    {
+                        var key = v.Description;
+                        var val = v.Enumeration?.FirstOrDefault();
+                        var ext = v.ExtensionData?.FirstOrDefault() ?? default;                        
+
+                        if (val is String txt)
+                        {
+                            System.Diagnostics.Debug.Assert(v.Type == NJsonSchema.JsonObjectType.None);
+
+                            key = txt; val = (Int64)0;
+                        }
+
+                        if (v.Type == NJsonSchema.JsonObjectType.None && ext.Key == "const")
+                        {
+                            key = (string)ext.Value; val = (Int64)0;
+                        }
+
+                        if (v.Type == NJsonSchema.JsonObjectType.Integer && ext.Key == "const")
+                        {
+                            val = (Int64)ext.Value;
+                        }
+
+                        System.Diagnostics.Debug.Assert(key != null || dict.Count > 0);
+
+                        if (string.IsNullOrWhiteSpace(key)) continue;
+
+                        dict[key] = (Int64)val;
+                    }
+
+                    // JSon Schema AnyOf enumerations are basically anonymous, so we create
+                    // a "shared name" with a concatenation of all the values:
+
+                    var name = string.Join("-", dict.Keys.OrderBy(item => item));                    
+
+                    var etype = ctx.UseEnum(name, isNullable);
+
+                    etype.Identifier = _GetSchemaIdentifier(schema);
+                    etype.Description = schema.Description;
+
+                    foreach (var kvp in dict) etype.SetValue(kvp.Key, (int)kvp.Value);
+
+                    if (dict.Values.Distinct().Count() > 1) etype.UseIntegers = true;                    
+
+                    return etype;
+                }
+
+                throw new NotImplementedException();                
+            }
+
+            if (_IsDictionary(schema))
+            {
+                var key = ctx.UseString();
+                var val = ctx._UseType(_GetDictionaryValue(schema));
+
+                return ctx.UseDictionary(key, val);
+            }
+
+            if (_IsClass(schema))
+            {
+                var classDecl = ctx.UseClass(schema.Title);
+
+                classDecl.Identifier = _GetSchemaIdentifier(schema);
+                classDecl.Description = schema.Description;
+
+                // process base class                
+
+                if (schema.InheritedSchema != null) classDecl.BaseClass = ctx._UseType(schema.InheritedSchema) as ClassType;
+
+                // filter declared properties
+
+                var keys = _GetProperyNames(schema);
+                if (schema.InheritedSchema != null) // filter our parent properties
+                {
+                    var baseKeys = _GetInheritedPropertyNames(schema).ToArray();
+                    keys = keys.Except(baseKeys).ToArray();
+                }
+                
+                // process declared properties
+
+                var props = keys.Select(key => schema.Properties.Values.FirstOrDefault(item => item.Name == key));
+
+                var required = schema.RequiredProperties;
+
+                // System.Diagnostics.Debug.Assert(schema.Title != "Buffer View");
+
+                foreach(var p in props)
+                {
+                    var field = classDecl.UseField(p.Name);
+
+                    field.Description = p.Description;
+
+                    field.FieldType = ctx._UseType(p, required.Contains(p.Name));
+
+                    field.ExclusiveMinimumValue = p.ExclusiveMinimum ?? (p.IsExclusiveMinimum ? p.Minimum : null);
+                    field.InclusiveMinimumValue = p.IsExclusiveMinimum ? null : p.Minimum;
+                    field.DefaultValue = p.Default;
+                    field.InclusiveMaximumValue = p.IsExclusiveMaximum ? null : p.Maximum;
+                    field.ExclusiveMaximumValue = p.ExclusiveMaximum ?? (p.IsExclusiveMaximum ? p.Maximum : null);
+
+                    field.MinItems = p.MinItems;
+                    field.MaxItems = p.MaxItems;
+                }
+
+
+                return classDecl;
+            }
+
+            if (schema.Type == NJsonSchema.JsonObjectType.Object) return ctx.UseAnyType();
+
+            if (schema.Type == NJsonSchema.JsonObjectType.None) return ctx.UseAnyType();
+
+            throw new NotImplementedException();
+        }
+
+        private static string _GetSchemaIdentifier(JSONSCHEMA schema)
+        {
+            if (schema.ExtensionData != null)
+            {
+                if (schema.ExtensionData.TryGetValue("$id", out var value) && value is string id)
+                {
+                    return id;
+                }
+            }
+
+            if (!string.IsNullOrWhiteSpace(schema.DocumentPath))
+            {
+                return System.IO.Path.GetFileName(schema.DocumentPath);
+            }
+
+            return null;
+
+            
+        }
+
+        private static bool _IsBlittableType(JSONSCHEMA schema)
+        {
+            if (schema == null) return false;
+            if (schema.Type == NJsonSchema.JsonObjectType.Boolean) return true;
+            if (schema.Type == NJsonSchema.JsonObjectType.Number) return true;
+            if (schema.Type == NJsonSchema.JsonObjectType.Integer) return true;            
+
+            return false;
+        }        
+
+        private static bool _IsStringType(JSONSCHEMA schema)
+        {
+            return schema.Type == NJsonSchema.JsonObjectType.String;
+        }
+
+        private static bool _IsEnumeration(JSONSCHEMA schema)
+        {
+            if (schema.Type != NJsonSchema.JsonObjectType.None) return false;
+
+            if (schema.IsArray || schema.IsDictionary) return false;
+
+            if (schema.AnyOf.Count == 0) return false;
+
+            // if (!schema.IsEnumeration) return false; // useless
+
+            return true;
+        }
+
+        private static bool _IsDictionary(JSONSCHEMA schema)
+        {
+            // if (schema.Type != NJsonSchema.JsonObjectType.Object) return false;
+
+            if (schema.AdditionalPropertiesSchema != null) return true;
+            if (schema.AllowAdditionalProperties == false && schema.PatternProperties.Any()) return true;            
+
+            return false;
+        }        
+
+        private static JSONSCHEMA _GetDictionaryValue(JSONSCHEMA schema)
+        {
+            if (schema.AdditionalPropertiesSchema != null)
+            {
+                return schema.AdditionalPropertiesSchema;
+            }
+
+            if (schema.AllowAdditionalProperties == false && schema.PatternProperties.Any())
+            {
+                var valueTypes = schema.PatternProperties.Values.ToArray();
+
+                if (valueTypes.Length == 1) return valueTypes.First();
+            }
+
+            throw new NotImplementedException();
+        }
+
+        private static bool _IsClass(JSONSCHEMA schema)
+        {
+            if (schema.Type != NJsonSchema.JsonObjectType.Object) return false;
+            
+            return !string.IsNullOrWhiteSpace(schema.Title);            
+        }
+
+        private static string[] _GetProperyNames(JSONSCHEMA schema)
+        {
+            return schema
+                    .Properties
+                    .Values
+                    .Select(item => item.Name)
+                    .ToArray();
+        }
+
+        private static string[] _GetInheritedPropertyNames(JSONSCHEMA schema)
+        {
+            if (schema?.InheritedSchema == null) return Enumerable.Empty<string>().ToArray();
+
+            return _GetInheritedPropertyNames(schema.InheritedSchema)
+                .Concat(_GetProperyNames(schema.InheritedSchema))
+                .ToArray();
+        }
+
+        #endregion
+    }
+}

+ 14 - 0
build/SharpGLTF.CodeGen.Core/SharpGLTF.CodeGen.Core.csproj

@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>    
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>SharpGLTF</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="LibGit2Sharp" />
+    <PackageReference Include="NJsonSchema.CodeGeneration.CSharp" />
+    <PackageReference Include="NJsonSchema.NewtonsoftJson" />
+  </ItemGroup>  
+
+</Project>

+ 52 - 0
build/SharpGLTF.CodeGen.Extensions.AGI/AgiExtensions.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF
+{
+    public static class AgiExtensions
+    {
+        #region API
+
+        public static IEnumerable<SchemaProcessor> GetExtensionsProcessors()
+        {
+            yield return new AgiArticulationsExtension();
+            yield return new AgiStkMetadataExtension();
+        }
+
+        #endregion
+
+        #region root paths        
+
+        /// <summary>
+        /// Program directory
+        /// </summary>
+        public static string ProgramDirectory => System.IO.Path.GetDirectoryName(typeof(AgiExtensions).Assembly.Location);
+
+        /// <summary>
+        /// Directory where the schema is downloaded and used as source
+        /// </summary>
+        public static string LocalRepoDirectory => System.IO.Path.Combine(ProgramDirectory, "glTF");
+
+        #endregion        
+
+        #region extension paths        
+        
+        private static string VendorSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Vendor");        
+        
+        internal static string VendorExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(VendorSchemaDir, ext, "schema", json);
+        }
+
+        #endregion
+
+        #region code generation output paths
+       
+        public static string AgiProjectDirectory => "src\\SharpGLTF.Ext.Agi\\Schema2\\Generated";
+
+        public static string AgiNameSpace => "SharpGLTF.Schema2.AGI";
+
+        #endregion
+    }
+}

+ 54 - 54
build/SharpGLTF.CodeGen/Ext.AGI_Articulations.cs → build/SharpGLTF.CodeGen.Extensions.AGI/Ext.AGI_Articulations.cs

@@ -1,54 +1,54 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class AgiArticulationsExtension : SchemaProcessor
-    {
-        public override string GetTargetProject() { return Constants.AgiProjectDirectory; }
-        private static string RootSchemaUri => Constants.VendorExtensionPath("AGI_articulations", "glTF.AGI_articulations.schema.json");
-        private static string NodeSchemaUri => Constants.VendorExtensionPath("AGI_articulations", "node.AGI_articulations.schema.json");
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            yield return ("ext.AgiRootArticulations.g", ProcessRoot());
-            yield return ("ext.AgiNodeArticulations.g", ProcessNode());
-        }        
-
-        private static SchemaType.Context ProcessRoot()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(RootSchemaUri);
-
-            ctx.FindClass("Articulation")
-                .GetField("pointingVector")
-                .SetDataType(typeof(System.Numerics.Vector3), true)
-                .SetItemsRange(0);            
-
-            return ctx;
-        }
-
-        private static SchemaType.Context ProcessNode()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(NodeSchemaUri);
-
-            return ctx;
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName("AGI_stk_metadata glTF extension", "AgiRootStkMetadata", Constants.AgiNameSpace);
-            newEmitter.SetRuntimeName("AGI_articulations glTF extension", "AgiRootArticulations", Constants.AgiNameSpace);
-            newEmitter.SetRuntimeName("AGI_articulations glTF Node extension", "AgiNodeArticulations", Constants.AgiNameSpace);
-            newEmitter.SetRuntimeName("Articulation", "AgiArticulation", Constants.AgiNameSpace);
-            newEmitter.SetRuntimeName("Articulation Stage", "AgiArticulationStage", Constants.AgiNameSpace);
-            newEmitter.SetRuntimeName("uniformScale-xRotate-xScale-xTranslate-yRotate-yScale-yTranslate-zRotate-zScale-zTranslate", "AgiArticulationTransformType", Constants.AgiNameSpace);
-
-            newEmitter.SetFieldToChildrenList(ctx, "AGI_articulations glTF extension", "articulations");
-            newEmitter.SetFieldToChildrenList(ctx, "Articulation", "stages");
-            newEmitter.SetFieldToChildrenList(ctx, "AGI_stk_metadata glTF extension", "solarPanelGroups");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class AgiArticulationsExtension : SchemaProcessor
+    {
+        public override string GetTargetProject() { return AgiExtensions.AgiProjectDirectory; }
+        private static string RootSchemaUri => AgiExtensions.VendorExtensionPath("AGI_articulations", "glTF.AGI_articulations.schema.json");
+        private static string NodeSchemaUri => AgiExtensions.VendorExtensionPath("AGI_articulations", "node.AGI_articulations.schema.json");
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            yield return ("ext.AgiRootArticulations.g", ProcessRoot());
+            yield return ("ext.AgiNodeArticulations.g", ProcessNode());
+        }        
+
+        private static SchemaType.Context ProcessRoot()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(RootSchemaUri);
+
+            ctx.FindClass("Articulation")
+                .GetField("pointingVector")
+                .SetDataType(typeof(System.Numerics.Vector3), true)
+                .SetItemsRange(0);            
+
+            return ctx;
+        }
+
+        private static SchemaType.Context ProcessNode()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(NodeSchemaUri);
+
+            return ctx;
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName("AGI_stk_metadata glTF extension", "AgiRootStkMetadata", AgiExtensions.AgiNameSpace);
+            newEmitter.SetRuntimeName("AGI_articulations glTF extension", "AgiRootArticulations", AgiExtensions.AgiNameSpace);
+            newEmitter.SetRuntimeName("AGI_articulations glTF Node extension", "AgiNodeArticulations", AgiExtensions.AgiNameSpace);
+            newEmitter.SetRuntimeName("Articulation", "AgiArticulation", AgiExtensions.AgiNameSpace);
+            newEmitter.SetRuntimeName("Articulation Stage", "AgiArticulationStage", AgiExtensions.AgiNameSpace);
+            newEmitter.SetRuntimeName("uniformScale-xRotate-xScale-xTranslate-yRotate-yScale-yTranslate-zRotate-zScale-zTranslate", "AgiArticulationTransformType", AgiExtensions.AgiNameSpace);
+
+            newEmitter.SetFieldToChildrenList(ctx, "AGI_articulations glTF extension", "articulations");
+            newEmitter.SetFieldToChildrenList(ctx, "Articulation", "stages");
+            newEmitter.SetFieldToChildrenList(ctx, "AGI_stk_metadata glTF extension", "solarPanelGroups");
+        }
+    }
+}

+ 40 - 40
build/SharpGLTF.CodeGen/Ext.AGI_RootStkMetadata.cs → build/SharpGLTF.CodeGen.Extensions.AGI/Ext.AGI_RootStkMetadata.cs

@@ -1,40 +1,40 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class AgiStkMetadataExtension : SchemaProcessor
-    {
-        public override string GetTargetProject() { return Constants.AgiProjectDirectory; }
-        private static string RootSchemaUri => Constants.VendorExtensionPath("AGI_stk_metadata", "glTF.AGI_stk_metadata.schema.json");
-        private static string NodeSchemaUri => Constants.VendorExtensionPath("AGI_stk_metadata", "node.AGI_stk_metadata.schema.json");
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            yield return ("ext.AgiRootStkMetadata.g", ProcessRoot());
-            yield return ("ext.AgiNodeStkMetadata.g", ProcessNode());
-        }        
-
-        private static SchemaType.Context ProcessRoot()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(RootSchemaUri);
-            return ctx;
-        }
-
-        private static SchemaType.Context ProcessNode()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(NodeSchemaUri);            
-            return ctx;
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName("AGI_stk_metadata glTF extension", "AgiRootStkMetadata", Constants.AgiNameSpace);
-            newEmitter.SetRuntimeName("AGI_stk_metadata glTF Node extension", "AgiNodeStkMetadata", Constants.AgiNameSpace);
-            newEmitter.SetRuntimeName("Solar Panel Group", "AgiStkSolarPanelGroup", Constants.AgiNameSpace);
-        }        
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class AgiStkMetadataExtension : SchemaProcessor
+    {
+        public override string GetTargetProject() { return AgiExtensions.AgiProjectDirectory; }
+        private static string RootSchemaUri => AgiExtensions.VendorExtensionPath("AGI_stk_metadata", "glTF.AGI_stk_metadata.schema.json");
+        private static string NodeSchemaUri => AgiExtensions.VendorExtensionPath("AGI_stk_metadata", "node.AGI_stk_metadata.schema.json");
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            yield return ("ext.AgiRootStkMetadata.g", ProcessRoot());
+            yield return ("ext.AgiNodeStkMetadata.g", ProcessNode());
+        }        
+
+        private static SchemaType.Context ProcessRoot()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(RootSchemaUri);
+            return ctx;
+        }
+
+        private static SchemaType.Context ProcessNode()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(NodeSchemaUri);            
+            return ctx;
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName("AGI_stk_metadata glTF extension", "AgiRootStkMetadata", AgiExtensions.AgiNameSpace);
+            newEmitter.SetRuntimeName("AGI_stk_metadata glTF Node extension", "AgiNodeStkMetadata", AgiExtensions.AgiNameSpace);
+            newEmitter.SetRuntimeName("Solar Panel Group", "AgiStkSolarPanelGroup", AgiExtensions.AgiNameSpace);
+        }        
+    }
+}

+ 12 - 0
build/SharpGLTF.CodeGen.Extensions.AGI/SharpGLTF.CodeGen.Extensions.AGI.csproj

@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>SharpGLTF</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\SharpGLTF.CodeGen.Core\SharpGLTF.CodeGen.Core.csproj" />
+  </ItemGroup>
+
+</Project>

+ 81 - 0
build/SharpGLTF.CodeGen.Extensions.Cesium/CesiumExtensions.cs

@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF
+{
+    public static class CesiumExtensions
+    {
+        #region API
+
+        public static IEnumerable<SchemaProcessor> GetExtensionsProcessors()
+        {
+            yield return new CesiumPrimitiveOutlineExtension();
+
+            yield return new ExtMeshFeaturesExtension();
+            yield return new ExtInstanceFeaturesExtension();
+            yield return new ExtStructuralMetadataExtension();
+        }
+
+        #endregion
+
+        #region root paths
+
+        public static string RemoteSchemaRepo = "https://github.com/KhronosGroup/glTF.git";
+
+        /// <summary>
+        /// Program directory
+        /// </summary>
+        public static string ProgramDirectory => System.IO.Path.GetDirectoryName(typeof(CesiumExtensions).Assembly.Location);
+
+        /// <summary>
+        /// Directory where the schema is downloaded and used as source
+        /// </summary>
+        public static string LocalRepoDirectory => System.IO.Path.Combine(ProgramDirectory, "glTF");
+
+        #endregion        
+
+        #region extension paths        
+        private static string ArchivedSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Archived");
+        private static string KhronosSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Khronos");
+        private static string VendorSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Vendor");
+
+        internal static string ArchivedExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(ArchivedSchemaDir, ext, "schema", json);
+        }
+
+        internal static string KhronosExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(KhronosSchemaDir, ext, "schema", json);
+        }
+        
+        internal static string VendorExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(VendorSchemaDir, ext, "schema", json);
+        }
+
+        internal static string CustomExtensionsPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(ProgramDirectory, "Schemas", ext, "schema", json);
+        }
+
+
+        #endregion
+
+        #region code generation output paths
+
+        /// <summary>
+        /// directory within the solution where the generated code is emitted
+        /// </summary>
+        
+        public static string CesiumProjectDirectory => "src\\SharpGLTF.Ext.3DTiles\\Schema2\\Generated";
+        public static string AgiProjectDirectory => "src\\SharpGLTF.Ext.Agi\\Schema2\\Generated";        
+
+        public static string CesiumNameSpace => "SharpGLTF.Schema2.Tiles3D";
+
+        public static string AgiNameSpace => "SharpGLTF.Schema2.AGI";
+
+        #endregion
+    }
+}

+ 3 - 3
build/SharpGLTF.CodeGen/Ext.CESIUM_primitive_outline.cs → build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.CESIUM_primitive_outline.cs

@@ -6,13 +6,13 @@ namespace SharpGLTF
 {
     class CesiumPrimitiveOutlineExtension : SchemaProcessor
     {
-        public override string GetTargetProject() { return Constants.CesiumProjectDirectory; }
+        public override string GetTargetProject() { return CesiumExtensions.CesiumProjectDirectory; }
 
-        private static string RootSchemaUri => Constants.VendorExtensionPath("CESIUM_primitive_outline", "primitive.CESIUM_primitive_outline.schema.json");
+        private static string RootSchemaUri => CesiumExtensions.VendorExtensionPath("CESIUM_primitive_outline", "primitive.CESIUM_primitive_outline.schema.json");
 
         public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx)
         {
-            newEmitter.SetRuntimeName("CESIUM_primitive_outline glTF primitive extension", "CesiumPrimitiveOutline", Constants.CesiumNameSpace);
+            newEmitter.SetRuntimeName("CESIUM_primitive_outline glTF primitive extension", "CesiumPrimitiveOutline", CesiumExtensions.CesiumNameSpace);
         }        
 
         public override IEnumerable<(string TargetFileName, SchemaType.Context Schema)> ReadSchema()

+ 4 - 4
build/SharpGLTF.CodeGen/Ext.EXT_InstanceFeatures.cs → build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.EXT_InstanceFeatures.cs

@@ -6,14 +6,14 @@ namespace SharpGLTF
 {
     class ExtInstanceFeaturesExtension : SchemaProcessor
     {
-        public override string GetTargetProject() { return Constants.CesiumProjectDirectory; }
+        public override string GetTargetProject() { return CesiumExtensions.CesiumProjectDirectory; }
 
-        private static string NodeSchemaUri => Constants.CustomExtensionsPath("EXT_instance_features", "node.EXT_instance_features.schema.json");
+        private static string NodeSchemaUri => CesiumExtensions.CustomExtensionsPath("EXT_instance_features", "node.EXT_instance_features.schema.json");
 
         public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx)
         {            
-            newEmitter.SetRuntimeName("EXT_instance_features glTF Node extension", "MeshExtInstanceFeatures", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Feature ID in EXT_instance_features", "MeshExtInstanceFeatureID", Constants.CesiumNameSpace);         
+            newEmitter.SetRuntimeName("EXT_instance_features glTF Node extension", "MeshExtInstanceFeatures", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Feature ID in EXT_instance_features", "MeshExtInstanceFeatureID", CesiumExtensions.CesiumNameSpace);         
 
             newEmitter.SetFieldToChildrenList(ctx, "EXT_instance_features glTF Node extension", "featureIds");
         }

+ 5 - 5
build/SharpGLTF.CodeGen/Ext.EXT_MeshFeatures.cs → build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.EXT_MeshFeatures.cs

@@ -7,17 +7,17 @@ namespace SharpGLTF
 {
     class ExtMeshFeaturesExtension : SchemaProcessor
     {
-        public override string GetTargetProject() { return Constants.CesiumProjectDirectory; }
+        public override string GetTargetProject() { return CesiumExtensions.CesiumProjectDirectory; }
     
-        private static string RootSchemaUri => Constants.CustomExtensionsPath("EXT_mesh_features", "mesh.primitive.EXT_mesh_features.schema.json");
+        private static string RootSchemaUri => CesiumExtensions.CustomExtensionsPath("EXT_mesh_features", "mesh.primitive.EXT_mesh_features.schema.json");
     
         const string ExtensionFeatureIdTextureName = "Feature ID Texture in EXT_mesh_features";
     
         public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx)
         {
-            newEmitter.SetRuntimeName("EXT_mesh_features glTF Mesh Primitive extension", "MeshExtMeshFeatures", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Feature ID in EXT_mesh_features", "MeshExtMeshFeatureID", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName(ExtensionFeatureIdTextureName, "MeshExtMeshFeatureIDTexture", Constants.CesiumNameSpace);
+            newEmitter.SetRuntimeName("EXT_mesh_features glTF Mesh Primitive extension", "MeshExtMeshFeatures", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Feature ID in EXT_mesh_features", "MeshExtMeshFeatureID", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName(ExtensionFeatureIdTextureName, "MeshExtMeshFeatureIDTexture", CesiumExtensions.CesiumNameSpace);
 
             newEmitter.SetFieldToChildrenList(ctx, "EXT_mesh_features glTF Mesh Primitive extension", "featureIds");
         }

+ 21 - 21
build/SharpGLTF.CodeGen/Ext.EXT_Structural_Metadata.cs → build/SharpGLTF.CodeGen.Extensions.Cesium/Ext.EXT_Structural_Metadata.cs

@@ -6,12 +6,12 @@ namespace SharpGLTF
 {
     class ExtStructuralMetadataExtension : SchemaProcessor
     {
-        public override string GetTargetProject() { return Constants.CesiumProjectDirectory; }
+        public override string GetTargetProject() { return CesiumExtensions.CesiumProjectDirectory; }
 
         const string ExtensionPropertyTexturePropertyName = "Property Texture Property in EXT_structural_metadata";
 
-        private static string RootSchemaUri => Constants.CustomExtensionsPath("EXT_structural_metadata", "glTF.EXT_structural_metadata.schema.json");
-        private static string MeshPrimitiveSchemaUri => Constants.CustomExtensionsPath("EXT_structural_metadata", "mesh.primitive.EXT_structural_metadata.schema.json");
+        private static string RootSchemaUri => CesiumExtensions.CustomExtensionsPath("EXT_structural_metadata", "glTF.EXT_structural_metadata.schema.json");
+        private static string MeshPrimitiveSchemaUri => CesiumExtensions.CustomExtensionsPath("EXT_structural_metadata", "mesh.primitive.EXT_structural_metadata.schema.json");
 
         public override IEnumerable<(string TargetFileName, SchemaType.Context Schema)> ReadSchema()
         {
@@ -41,24 +41,24 @@ namespace SharpGLTF
 
         public override void PrepareTypes(CSharpEmitter newEmitter, SchemaType.Context ctx)
         {
-            newEmitter.SetRuntimeName("EXT_structural_metadata glTF Mesh Primitive extension", "ExtStructuralMetadataMeshPrimitive", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("EXT_structural_metadata glTF extension", "EXTStructuralMetadataRoot", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Property Table in EXT_structural_metadata", "PropertyTable", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Schema in EXT_structural_metadata", "StructuralMetadataSchema", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Property Table Property in EXT_structural_metadata", "PropertyTableProperty", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Property Texture in EXT_structural_metadata", "PropertyTexture", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Property Texture Property in EXT_structural_metadata", "PropertyTextureProperty", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Property Attribute Property in EXT_structural_metadata", "PropertyAttributeProperty", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Class Property in EXT_structural_metadata", "StructuralMetadataClassProperty", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Class in EXT_structural_metadata", "StructuralMetadataClass", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Enum Value in EXT_structural_metadata", "StructuralMetadataEnumValue", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Enum in EXT_structural_metadata", "StructuralMetadataEnum", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("Property Attribute in EXT_structural_metadata", "PropertyAttribute", Constants.CesiumNameSpace);
-
-            newEmitter.SetRuntimeName("BOOLEAN-ENUM-MAT2-MAT3-MAT4-SCALAR-STRING-VEC2-VEC3-VEC4", "ElementType", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("FLOAT32-FLOAT64-INT16-INT32-INT64-INT8-UINT16-UINT32-UINT64-UINT8", "DataType", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("INT16-INT32-INT64-INT8-UINT16-UINT32-UINT64-UINT8", "IntegerType", Constants.CesiumNameSpace);
-            newEmitter.SetRuntimeName("UINT16-UINT32-UINT64-UINT8", "ArrayOffsetType", Constants.CesiumNameSpace);
+            newEmitter.SetRuntimeName("EXT_structural_metadata glTF Mesh Primitive extension", "ExtStructuralMetadataMeshPrimitive", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("EXT_structural_metadata glTF extension", "EXTStructuralMetadataRoot", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Property Table in EXT_structural_metadata", "PropertyTable", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Schema in EXT_structural_metadata", "StructuralMetadataSchema", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Property Table Property in EXT_structural_metadata", "PropertyTableProperty", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Property Texture in EXT_structural_metadata", "PropertyTexture", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Property Texture Property in EXT_structural_metadata", "PropertyTextureProperty", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Property Attribute Property in EXT_structural_metadata", "PropertyAttributeProperty", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Class Property in EXT_structural_metadata", "StructuralMetadataClassProperty", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Class in EXT_structural_metadata", "StructuralMetadataClass", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Enum Value in EXT_structural_metadata", "StructuralMetadataEnumValue", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Enum in EXT_structural_metadata", "StructuralMetadataEnum", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("Property Attribute in EXT_structural_metadata", "PropertyAttribute", CesiumExtensions.CesiumNameSpace);
+
+            newEmitter.SetRuntimeName("BOOLEAN-ENUM-MAT2-MAT3-MAT4-SCALAR-STRING-VEC2-VEC3-VEC4", "ElementType", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("FLOAT32-FLOAT64-INT16-INT32-INT64-INT8-UINT16-UINT32-UINT64-UINT8", "DataType", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("INT16-INT32-INT64-INT8-UINT16-UINT32-UINT64-UINT8", "IntegerType", CesiumExtensions.CesiumNameSpace);
+            newEmitter.SetRuntimeName("UINT16-UINT32-UINT64-UINT8", "ArrayOffsetType", CesiumExtensions.CesiumNameSpace);
 
             newEmitter.SetFieldToChildrenList(ctx, "EXT_structural_metadata glTF extension", "propertyTables");
             newEmitter.SetFieldToChildrenList(ctx, "EXT_structural_metadata glTF extension", "propertyAttributes");

+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_instance_features/README.md → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/README.md


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_instance_features/schema/featureId.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/schema/featureId.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_instance_features/schema/featureIdAttribute.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/schema/featureIdAttribute.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_instance_features/schema/node.EXT_instance_features.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_instance_features/schema/node.EXT_instance_features.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_mesh_features/README.md → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/README.md


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_mesh_features/schema/featureId.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/featureId.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_mesh_features/schema/featureIdAttribute.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/featureIdAttribute.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_mesh_features/schema/featureIdTexture.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/featureIdTexture.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_mesh_features/schema/mesh.primitive.EXT_mesh_features.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_mesh_features/schema/mesh.primitive.EXT_mesh_features.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/README.md → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/README.md


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/figures/property-attribute.png → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-attribute.png


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/figures/property-attribute.svg → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-attribute.svg


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/figures/property-table.png → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-table.png


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/figures/property-table.svg → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-table.svg


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/figures/property-texture.png → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-texture.png


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/figures/property-texture.svg → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/figures/property-texture.svg


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/EXT_structural_metadata.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/EXT_structural_metadata.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/class.property.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/class.property.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/class.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/class.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/definitions.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/definitions.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/enum.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/enum.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/enum.value.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/enum.value.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/glTF.EXT_structural_metadata.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/glTF.EXT_structural_metadata.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/mesh.primitive.EXT_structural_metadata.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/mesh.primitive.EXT_structural_metadata.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/propertyAttribute.property.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyAttribute.property.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/propertyAttribute.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyAttribute.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/propertyTable.property.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTable.property.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/propertyTable.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTable.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/propertyTexture.property.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTexture.property.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/propertyTexture.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/propertyTexture.schema.json


+ 0 - 0
build/SharpGLTF.CodeGen/Schemas/EXT_structural_metadata/schema/schema.schema.json → build/SharpGLTF.CodeGen.Extensions.Cesium/Schemas/EXT_structural_metadata/schema/schema.schema.json


+ 17 - 0
build/SharpGLTF.CodeGen.Extensions.Cesium/SharpGLTF.CodeGen.Extensions.Cesium.csproj

@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>SharpGLTF</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\SharpGLTF.CodeGen.Core\SharpGLTF.CodeGen.Core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Schemas\" />
+    <None Update="Schemas\**\*" CopyToOutputDirectory="PreserveNewest" />
+  </ItemGroup>
+
+</Project>

+ 1 - 64
build/SharpGLTF.CodeGen/Constants.cs

@@ -13,7 +13,7 @@ namespace SharpGLTF
         /// <summary>
         /// Program directory
         /// </summary>
-        public static string ProgramDirectory => System.IO.Path.GetDirectoryName(typeof(Program).Assembly.Location);
+        public static string ProgramDirectory => System.IO.Path.GetDirectoryName(typeof(Constants).Assembly.Location);
 
         /// <summary>
         /// Directory where the schema is downloaded and used as source
@@ -21,68 +21,5 @@ namespace SharpGLTF
         public static string LocalRepoDirectory => System.IO.Path.Combine(ProgramDirectory, "glTF");
 
         #endregion
-
-        #region main schema paths
-
-        /// <summary>
-        /// Directory of the main schema within the download repo directory
-        /// </summary>
-        public static string MainSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "specification", "2.0", "schema");
-
-        /// <summary>
-        /// schema source code file path
-        /// </summary>
-        public static string MainSchemaFile => System.IO.Path.Combine(MainSchemaDir, "glTF.schema.json");
-
-        #endregion
-
-        #region extension paths        
-        private static string ArchivedSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Archived");
-        private static string KhronosSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Khronos");
-        private static string VendorSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Vendor");
-
-        internal static string ArchivedExtensionPath(string ext, string json)
-        {
-            return System.IO.Path.Combine(ArchivedSchemaDir, ext, "schema", json);
-        }
-
-        internal static string KhronosExtensionPath(string ext, string json)
-        {
-            return System.IO.Path.Combine(KhronosSchemaDir, ext, "schema", json);
-        }
-        
-        internal static string VendorExtensionPath(string ext, string json)
-        {
-            return System.IO.Path.Combine(VendorSchemaDir, ext, "schema", json);
-        }
-
-        internal static string CustomExtensionsPath(string ext, string json)
-        {
-            return System.IO.Path.Combine(ProgramDirectory, "Schemas", ext, "schema", json);
-        }
-
-
-        #endregion
-
-        #region code generation output paths
-
-        /// <summary>
-        /// directory within the solution where the generated code is emitted
-        /// </summary>
-        public static string TargetProjectDirectory => "src\\SharpGLTF.Core\\Schema2\\Generated";
-        public static string CesiumProjectDirectory => "src\\SharpGLTF.Ext.3DTiles\\Schema2\\Generated";
-        public static string AgiProjectDirectory => "src\\SharpGLTF.Ext.Agi\\Schema2\\Generated";
-
-
-        /// <summary>
-        /// namespace of the emitted generated code
-        /// </summary>
-        public static string OutputNamespace => "SharpGLTF.Schema2";
-
-        public static string CesiumNameSpace => "SharpGLTF.Schema2.Tiles3D";
-
-        public static string AgiNameSpace => "SharpGLTF.Schema2.AGI";
-
-        #endregion
     }
 }

+ 5 - 43
build/SharpGLTF.CodeGen/Program.cs

@@ -23,52 +23,14 @@ namespace SharpGLTF
 
             processors.Add(new MainSchemaProcessor());
 
-            // ---------------------------------------------- Add extensions            
+            // ---------------------------------------------- Add Khronos Extensions
 
-            // material extensions       
-            processors.Add(new UnlitExtension());
-            processors.Add(new IorExtension());
-            processors.Add(new SheenExtension());            
-            processors.Add(new VolumeExtension());
-            processors.Add(new SpecularExtension());
-            processors.Add(new ClearCoatExtension());
-            processors.Add(new DispersionExtension());
-            processors.Add(new AnisotropyExtension());
-            processors.Add(new IridescenceExtension());            
-            processors.Add(new TransmissionExtension());
-            processors.Add(new DiffuseTransmissionExtension());
-            processors.Add(new EmissiveStrengthExtension());
-            processors.Add(new SpecularGlossinessExtension());
+            processors.AddRange(KhronosExtensions.GetExtensionsProcessors());
 
-            // cesium outlines
-            processors.Add(new CesiumPrimitiveOutlineExtension());
-
-            // lights
-            processors.Add(new LightsPunctualExtension());
-
-            // gpu mesh instancing
-            processors.Add(new MeshGpuInstancingExtension());
-
-            // textures
-            processors.Add(new TextureTransformExtension());
-            processors.Add(new TextureDDSExtension());
-            processors.Add(new TextureWebpExtension());
-            processors.Add(new TextureKtx2Extension());
-
-            processors.Add(new AgiArticulationsExtension());
-            processors.Add(new AgiStkMetadataExtension());
-
-            // other
-            processors.Add(new XmpJsonLdExtension());            
-
-            processors.Add(new ExtMeshFeaturesExtension());
-
-            processors.Add(new AnimationPointerExtension());
-
-            processors.Add(new ExtInstanceFeaturesExtension());
-
-            processors.Add(new ExtStructuralMetadataExtension());            
+            // ---------------------------------------------- Add third party extensions
 
+            processors.AddRange(AgiExtensions.GetExtensionsProcessors());
+            processors.AddRange(CesiumExtensions.GetExtensionsProcessors());
 
             // ----------------------------------------------  process all files
 

+ 10 - 8
build/SharpGLTF.CodeGen/SharpGLTF.CodeGen.csproj

@@ -6,14 +6,16 @@
     <RootNamespace>SharpGLTF</RootNamespace>
   </PropertyGroup>
 
-  <ItemGroup>
-    <PackageReference Include="LibGit2Sharp" />    
-    <PackageReference Include="NJsonSchema.CodeGeneration.CSharp" />
-    <PackageReference Include="NJsonSchema.NewtonsoftJson" />
-  </ItemGroup>
+  <PropertyGroup>
+    <Description>
+      Contains code generation utilities used to parse glTF schemas and transpile them into c# code.
+    </Description>
+  </PropertyGroup>
 
-  <ItemGroup>
-    <Folder Include="Schemas\" />
-	<None Update="Schemas\**\*" CopyToOutputDirectory="PreserveNewest" />
+  <ItemGroup>    
+    <ProjectReference Include="..\SharpGLTF.CodeGen.Core\SharpGLTF.CodeGen.Core.csproj" />    
+    <ProjectReference Include="..\SharpGLTF.CodeGen.Extensions.AGI\SharpGLTF.CodeGen.Extensions.AGI.csproj" />    
+    <ProjectReference Include="..\SharpGLTF.CodeGen.Extensions.Cesium\SharpGLTF.CodeGen.Extensions.Cesium.csproj" />    
+    <ProjectReference Include="..\SharpGLTF.codeGen.Extensions.Khronos\SharpGLTF.codeGen.Extensions.Khronos.csproj" />    
   </ItemGroup>
 </Project>

+ 24 - 24
build/SharpGLTF.CodeGen/Ext.EXT_MeshGpuInstancing.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.EXT_MeshGpuInstancing.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class MeshGpuInstancingExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.VendorExtensionPath("EXT_mesh_gpu_instancing", "glTF.EXT_mesh_gpu_instancing.schema.json");
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            yield return ("ext.MeshGpuInstancing.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName("EXT_mesh_gpu_instancing glTF extension", "MeshGpuInstancing");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class MeshGpuInstancingExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.VendorExtensionPath("EXT_mesh_gpu_instancing", "glTF.EXT_mesh_gpu_instancing.schema.json");
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            yield return ("ext.MeshGpuInstancing.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName("EXT_mesh_gpu_instancing glTF extension", "MeshGpuInstancing");
+        }
+    }
+}

+ 24 - 24
build/SharpGLTF.CodeGen/Ext.EXT_TextureWebp.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.EXT_TextureWebp.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class TextureWebpExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.VendorExtensionPath("EXT_texture_webp", "glTF.EXT_texture_webp.schema.json");
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);            
-
-            yield return ("ext.TextureWEBP.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName("EXT_texture_webp glTF extension", "TextureWEBP");
-        }        
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class TextureWebpExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.VendorExtensionPath("EXT_texture_webp", "glTF.EXT_texture_webp.schema.json");
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);            
+
+            yield return ("ext.TextureWEBP.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName("EXT_texture_webp glTF extension", "TextureWEBP");
+        }        
+    }
+}

+ 1 - 1
build/SharpGLTF.CodeGen/Ext.KHR_AnimPointer.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_AnimPointer.cs

@@ -10,7 +10,7 @@ namespace SharpGLTF
 {
     class AnimationPointerExtension : SchemaProcessor
     {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_animation_pointer", "animation.channel.target.KHR_animation_pointer.schema.json");
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_animation_pointer", "animation.channel.target.KHR_animation_pointer.schema.json");
 
         private const string ExtensionRootClassName = "KHR_animation_pointer glTF Animation Channel Target Extension";
 

+ 1 - 1
build/SharpGLTF.CodeGen/Ext.KHR_Anisotropy.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Anisotropy.cs

@@ -8,7 +8,7 @@ namespace SharpGLTF
 {
     class AnisotropyExtension : SchemaProcessor
     {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_anisotropy", "material.KHR_materials_anisotropy.schema.json");
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_anisotropy", "material.KHR_materials_anisotropy.schema.json");
 
         private const string ExtensionRootClassName = "KHR_materials_anisotropy glTF Material Extension";
 

+ 27 - 27
build/SharpGLTF.CodeGen/Ext.KHR_ClearCoat.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_ClearCoat.cs

@@ -1,27 +1,27 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class ClearCoatExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_clearcoat", "material.KHR_materials_clearcoat.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_clearcoat glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            yield return("ext.ClearCoat.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialClearCoat");
-        }        
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class ClearCoatExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_clearcoat", "material.KHR_materials_clearcoat.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_clearcoat glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            yield return("ext.ClearCoat.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialClearCoat");
+        }        
+    }
+}

+ 1 - 1
build/SharpGLTF.CodeGen/Ext.KHR_DiffuseTransmission.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_DiffuseTransmission.cs

@@ -12,7 +12,7 @@ namespace SharpGLTF
         // file naming issues and it's subject to change anytime.
         // https://github.com/KhronosGroup/glTF/issues/2482
 
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_diffuse_transmission", "glTF.KHR_materials_diffuse_transmission.schema.json");
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_diffuse_transmission", "glTF.KHR_materials_diffuse_transmission.schema.json");
 
         private const string ExtensionRootClassName = "KHR_materials_diffuse_transmission glTF extension"; // not correctly named?
 

+ 1 - 1
build/SharpGLTF.CodeGen/Ext.KHR_Dispersion.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Dispersion.cs

@@ -8,7 +8,7 @@ namespace SharpGLTF
 {
     class DispersionExtension : SchemaProcessor
     {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_dispersion", "material.KHR_materials_dispersion.schema.json");
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_dispersion", "material.KHR_materials_dispersion.schema.json");
 
         private const string ExtensionRootClassName = "KHR_materials_dispersion glTF Material Extension";
 

+ 30 - 30
build/SharpGLTF.CodeGen/Ext.KHR_EmissiveStrength.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_EmissiveStrength.cs

@@ -1,30 +1,30 @@
-using System;
-using System.Collections.Generic;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class EmissiveStrengthExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_emissive_strength", "material.KHR_materials_emissive_strength.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_emissive_strength glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            var cls = ctx.FindClass(ExtensionRootClassName);
-            
-            // straightforward extension, nothing to do
-
-            yield return ("ext.MaterialsEmissiveStrength.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialEmissiveStrength");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class EmissiveStrengthExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_emissive_strength", "material.KHR_materials_emissive_strength.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_emissive_strength glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            var cls = ctx.FindClass(ExtensionRootClassName);
+            
+            // straightforward extension, nothing to do
+
+            yield return ("ext.MaterialsEmissiveStrength.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialEmissiveStrength");
+        }
+    }
+}

+ 27 - 27
build/SharpGLTF.CodeGen/Ext.KHR_IOR.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_IOR.cs

@@ -1,27 +1,27 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class IorExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_ior", "material.KHR_materials_ior.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_ior glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            yield return ("ext.Ior.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialIOR");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class IorExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_ior", "material.KHR_materials_ior.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_ior glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            yield return ("ext.Ior.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialIOR");
+        }
+    }
+}

+ 29 - 29
build/SharpGLTF.CodeGen/Ext.KHR_Iridescence.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Iridescence.cs

@@ -1,29 +1,29 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class IridescenceExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_iridescence", "material.KHR_materials_iridescence.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_iridescence glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);    
-
-            yield return ("ext.Iridescence.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialIridescence");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class IridescenceExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_iridescence", "material.KHR_materials_iridescence.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_iridescence glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);    
+
+            yield return ("ext.Iridescence.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialIridescence");
+        }
+    }
+}

+ 53 - 53
build/SharpGLTF.CodeGen/Ext.KHR_LightsPunctual.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_LightsPunctual.cs

@@ -1,53 +1,53 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class LightsPunctualExtension : SchemaProcessor
-    {
-        private static string RootSchemaUri => Constants.KhronosExtensionPath("KHR_lights_punctual", "glTF.KHR_lights_punctual.schema.json");
-        private static string NodeSchemaUri => Constants.KhronosExtensionPath("KHR_lights_punctual", "node.KHR_lights_punctual.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_lights_punctual glTF Document Extension";
-        private const string ExtensionNodeClassName = "KHR_lights_punctual glTF Node Extension";
-        private const string ExtensionLightClassName = "KHR_lights_punctual Light Properties";
-        private const string ExtensionLightSpotClassName = "KHR_lights_punctual Light Spot Properties";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {            
-            yield return ("ext.ModelLightsPunctual.g", ProcessModel());
-            yield return ("ext.NodeLightsPunctual.g", ProcessNode());
-        }
-        private static SchemaType.Context ProcessModel()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(RootSchemaUri);
-
-            ctx.FindClass(ExtensionLightClassName)
-                .GetField("color")
-                .SetDataType(typeof(System.Numerics.Vector3), true)
-                .SetDefaultValue("Vector3.One")
-                .SetItemsRange(0);
-
-            return ctx;
-        }
-
-        private static SchemaType.Context ProcessNode()
-        {
-            var ctx = SchemaProcessing.LoadSchemaContext(NodeSchemaUri);
-            ctx.IgnoredByCodeEmitter("glTF Property");
-            ctx.IgnoredByCodeEmitter("glTF Child of Root Property");
-            return ctx;
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionLightClassName, "PunctualLight");
-            newEmitter.SetRuntimeName(ExtensionLightSpotClassName, "PunctualLightSpot");
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "_ModelPunctualLights");
-            newEmitter.SetRuntimeName(ExtensionNodeClassName, "_NodePunctualLight");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class LightsPunctualExtension : SchemaProcessor
+    {
+        private static string RootSchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_lights_punctual", "glTF.KHR_lights_punctual.schema.json");
+        private static string NodeSchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_lights_punctual", "node.KHR_lights_punctual.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_lights_punctual glTF Document Extension";
+        private const string ExtensionNodeClassName = "KHR_lights_punctual glTF Node Extension";
+        private const string ExtensionLightClassName = "KHR_lights_punctual Light Properties";
+        private const string ExtensionLightSpotClassName = "KHR_lights_punctual Light Spot Properties";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {            
+            yield return ("ext.ModelLightsPunctual.g", ProcessModel());
+            yield return ("ext.NodeLightsPunctual.g", ProcessNode());
+        }
+        private static SchemaType.Context ProcessModel()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(RootSchemaUri);
+
+            ctx.FindClass(ExtensionLightClassName)
+                .GetField("color")
+                .SetDataType(typeof(System.Numerics.Vector3), true)
+                .SetDefaultValue("Vector3.One")
+                .SetItemsRange(0);
+
+            return ctx;
+        }
+
+        private static SchemaType.Context ProcessNode()
+        {
+            var ctx = SchemaProcessing.LoadSchemaContext(NodeSchemaUri);
+            ctx.IgnoredByCodeEmitter("glTF Property");
+            ctx.IgnoredByCodeEmitter("glTF Child of Root Property");
+            return ctx;
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionLightClassName, "PunctualLight");
+            newEmitter.SetRuntimeName(ExtensionLightSpotClassName, "PunctualLightSpot");
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "_ModelPunctualLights");
+            newEmitter.SetRuntimeName(ExtensionNodeClassName, "_NodePunctualLight");
+        }
+    }
+}

+ 38 - 38
build/SharpGLTF.CodeGen/Ext.KHR_Sheen.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Sheen.cs

@@ -1,38 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class SheenExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_sheen", "material.KHR_materials_sheen.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_sheen glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            ctx.FindClass(ExtensionRootClassName)
-                .GetField("sheenColorFactor")
-                .SetDataType(typeof(System.Numerics.Vector3), true)
-                .SetDefaultValue("Vector3.Zero")
-                .SetItemsRange(0);
-
-            ctx.FindClass(ExtensionRootClassName)
-                .GetField("sheenRoughnessFactor")
-                .SetDataType(typeof(float), true)
-                .SetItemsRange(0);
-
-            yield return ("ext.Sheen.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialSheen");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class SheenExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_sheen", "material.KHR_materials_sheen.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_sheen glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            ctx.FindClass(ExtensionRootClassName)
+                .GetField("sheenColorFactor")
+                .SetDataType(typeof(System.Numerics.Vector3), true)
+                .SetDefaultValue("Vector3.Zero")
+                .SetItemsRange(0);
+
+            ctx.FindClass(ExtensionRootClassName)
+                .GetField("sheenRoughnessFactor")
+                .SetDataType(typeof(float), true)
+                .SetItemsRange(0);
+
+            yield return ("ext.Sheen.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialSheen");
+        }
+    }
+}

+ 33 - 33
build/SharpGLTF.CodeGen/Ext.KHR_Specular.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Specular.cs

@@ -1,33 +1,33 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class SpecularExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_specular", "material.KHR_materials_specular.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_specular glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            ctx.FindClass(ExtensionRootClassName)
-                .GetField("specularColorFactor")
-                .SetDataType(typeof(System.Numerics.Vector3), true)
-                .SetDefaultValue("Vector3.One")
-                .SetItemsRange(0);
-
-            yield return ("ext.pbrSpecular.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialSpecular");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class SpecularExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_specular", "material.KHR_materials_specular.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_specular glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            ctx.FindClass(ExtensionRootClassName)
+                .GetField("specularColorFactor")
+                .SetDataType(typeof(System.Numerics.Vector3), true)
+                .SetDefaultValue("Vector3.One")
+                .SetItemsRange(0);
+
+            yield return ("ext.pbrSpecular.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialSpecular");
+        }
+    }
+}

+ 36 - 36
build/SharpGLTF.CodeGen/Ext.KHR_SpecularGlossiness.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_SpecularGlossiness.cs

@@ -1,36 +1,36 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class SpecularGlossinessExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.ArchivedExtensionPath("KHR_materials_pbrSpecularGlossiness", "glTF.KHR_materials_pbrSpecularGlossiness.schema.json");
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            ctx.FindClass("KHR_materials_pbrSpecularGlossiness glTF extension")
-                .GetField("diffuseFactor")
-                .SetDataType(typeof(System.Numerics.Vector4), true)
-                .SetDefaultValue("Vector4.One")
-                .SetItemsRange(0);
-
-            ctx.FindClass("KHR_materials_pbrSpecularGlossiness glTF extension")
-                .GetField("specularFactor")
-                .SetDataType(typeof(System.Numerics.Vector3), true)
-                .SetDefaultValue("Vector3.One")
-                .SetItemsRange(0);
-
-            yield return ("ext.pbrSpecularGlossiness.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName("KHR_materials_pbrSpecularGlossiness glTF extension", "MaterialPBRSpecularGlossiness");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class SpecularGlossinessExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.ArchivedExtensionPath("KHR_materials_pbrSpecularGlossiness", "glTF.KHR_materials_pbrSpecularGlossiness.schema.json");
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            ctx.FindClass("KHR_materials_pbrSpecularGlossiness glTF extension")
+                .GetField("diffuseFactor")
+                .SetDataType(typeof(System.Numerics.Vector4), true)
+                .SetDefaultValue("Vector4.One")
+                .SetItemsRange(0);
+
+            ctx.FindClass("KHR_materials_pbrSpecularGlossiness glTF extension")
+                .GetField("specularFactor")
+                .SetDataType(typeof(System.Numerics.Vector3), true)
+                .SetDefaultValue("Vector3.One")
+                .SetItemsRange(0);
+
+            yield return ("ext.pbrSpecularGlossiness.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName("KHR_materials_pbrSpecularGlossiness glTF extension", "MaterialPBRSpecularGlossiness");
+        }
+    }
+}

+ 27 - 27
build/SharpGLTF.CodeGen/Ext.KHR_TextureBasisU.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_TextureBasisU.cs

@@ -1,27 +1,27 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class TextureKtx2Extension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_texture_basisu", "texture.KHR_texture_basisu.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_texture_basisu glTF Texture Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            yield return ("ext.TextureKTX2.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "TextureKTX2");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class TextureKtx2Extension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_texture_basisu", "texture.KHR_texture_basisu.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_texture_basisu glTF Texture Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            yield return ("ext.TextureKTX2.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "TextureKTX2");
+        }
+    }
+}

+ 39 - 39
build/SharpGLTF.CodeGen/Ext.KHR_TextureTransform.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_TextureTransform.cs

@@ -1,39 +1,39 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class TextureTransformExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_texture_transform", "textureInfo.KHR_texture_transform.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_texture_transform glTF TextureInfo Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            var tex = ctx.FindClass(ExtensionRootClassName);
-
-            tex.GetField("offset")
-                .SetDataType(typeof(System.Numerics.Vector2), true)
-                .SetDefaultValue("Vector2.Zero")
-                .SetItemsRange(0);
-
-            tex.GetField("scale")
-                .SetDataType(typeof(System.Numerics.Vector2), true)
-                .SetDefaultValue("Vector2.One")
-                .SetItemsRange(0);
-
-            yield return ("ext.TextureTransform.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "TextureTransform");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class TextureTransformExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_texture_transform", "textureInfo.KHR_texture_transform.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_texture_transform glTF TextureInfo Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            var tex = ctx.FindClass(ExtensionRootClassName);
+
+            tex.GetField("offset")
+                .SetDataType(typeof(System.Numerics.Vector2), true)
+                .SetDefaultValue("Vector2.Zero")
+                .SetItemsRange(0);
+
+            tex.GetField("scale")
+                .SetDataType(typeof(System.Numerics.Vector2), true)
+                .SetDefaultValue("Vector2.One")
+                .SetItemsRange(0);
+
+            yield return ("ext.TextureTransform.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "TextureTransform");
+        }
+    }
+}

+ 27 - 27
build/SharpGLTF.CodeGen/Ext.KHR_Transmission.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Transmission.cs

@@ -1,27 +1,27 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class TransmissionExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_transmission", "material.KHR_materials_transmission.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_transmission glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            yield return("ext.Transmission.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialTransmission");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class TransmissionExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_transmission", "material.KHR_materials_transmission.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_transmission glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            yield return("ext.Transmission.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialTransmission");
+        }
+    }
+}

+ 27 - 27
build/SharpGLTF.CodeGen/Ext.KHR_Unlit.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Unlit.cs

@@ -1,27 +1,27 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class UnlitExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_unlit", "material.KHR_materials_unlit.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_unlit glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            yield return("ext.Unlit.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialUnlit");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class UnlitExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_unlit", "material.KHR_materials_unlit.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_unlit glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            yield return("ext.Unlit.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialUnlit");
+        }
+    }
+}

+ 33 - 33
build/SharpGLTF.CodeGen/Ext.KHR_Volume.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_Volume.cs

@@ -1,33 +1,33 @@
-using System;
-using System.Collections.Generic;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class VolumeExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.KhronosExtensionPath("KHR_materials_volume", "material.KHR_materials_volume.schema.json");
-
-        private const string ExtensionRootClassName = "KHR_materials_volume glTF Material Extension";
-
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            var cls = ctx.FindClass(ExtensionRootClassName);
-
-            cls.GetField("attenuationColor")
-                .SetDataType(typeof(System.Numerics.Vector3), true)
-                .SetDefaultValue("Vector3.One")
-                .SetItemsRange(0);
-
-            yield return ("ext.MaterialsVolume.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialVolume");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class VolumeExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_materials_volume", "material.KHR_materials_volume.schema.json");
+
+        private const string ExtensionRootClassName = "KHR_materials_volume glTF Material Extension";
+
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            var cls = ctx.FindClass(ExtensionRootClassName);
+
+            cls.GetField("attenuationColor")
+                .SetDataType(typeof(System.Numerics.Vector3), true)
+                .SetDefaultValue("Vector3.One")
+                .SetItemsRange(0);
+
+            yield return ("ext.MaterialsVolume.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName(ExtensionRootClassName, "MaterialVolume");
+        }
+    }
+}

+ 2 - 2
build/SharpGLTF.CodeGen/Ext.KHR_XmpJsonLD.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.KHR_XmpJsonLD.cs

@@ -10,9 +10,9 @@ namespace SharpGLTF
 {
     class XmpJsonLdExtension : SchemaProcessor
     {
-        private static string RootSchemaUri => Constants.KhronosExtensionPath("KHR_xmp_json_ld", "glTF.KHR_xmp_json_ld.schema.json");
+        private static string RootSchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_xmp_json_ld", "glTF.KHR_xmp_json_ld.schema.json");
 
-        private static string PropSchemaUri => Constants.KhronosExtensionPath("KHR_xmp_json_ld", "KHR_xmp_json_ld.schema.json");
+        private static string PropSchemaUri => KhronosExtensions.KhronosExtensionPath("KHR_xmp_json_ld", "KHR_xmp_json_ld.schema.json");
 
         private const string ExtensionRootClassName = "KHR_xmp_json_ld glTF Document Extension";
         private const string ExtensionPropClassName = "KHR_xmp_json_ld glTF Extension";

+ 24 - 24
build/SharpGLTF.CodeGen/Ext.MSFT_TextureDDS.cs → build/SharpGLTF.codeGen.Extensions.Khronos/Ext.MSFT_TextureDDS.cs

@@ -1,24 +1,24 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-using SharpGLTF.SchemaReflection;
-
-namespace SharpGLTF
-{
-    class TextureDDSExtension : SchemaProcessor
-    {
-        private static string SchemaUri => Constants.VendorExtensionPath("MSFT_texture_dds", "glTF.MSFT_texture_dds.schema.json");
-        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
-        {
-            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
-
-            yield return ("ext.MSFT.TextureDDS.g", ctx);
-        }
-
-        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
-        {
-            newEmitter.SetRuntimeName("MSFT_texture_dds extension", "TextureDDS");
-        }
-    }
-}
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+using SharpGLTF.SchemaReflection;
+
+namespace SharpGLTF
+{
+    class TextureDDSExtension : SchemaProcessor
+    {
+        private static string SchemaUri => KhronosExtensions.VendorExtensionPath("MSFT_texture_dds", "glTF.MSFT_texture_dds.schema.json");
+        public override IEnumerable<(string, SchemaType.Context)> ReadSchema()
+        {
+            var ctx = SchemaProcessing.LoadExtensionSchemaContext(SchemaUri);
+
+            yield return ("ext.MSFT.TextureDDS.g", ctx);
+        }
+
+        public override void PrepareTypes(CodeGen.CSharpEmitter newEmitter, SchemaType.Context ctx)
+        {
+            newEmitter.SetRuntimeName("MSFT_texture_dds extension", "TextureDDS");
+        }
+    }
+}

+ 84 - 0
build/SharpGLTF.codeGen.Extensions.Khronos/KhronosExtensions.cs

@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace SharpGLTF
+{
+    public static class KhronosExtensions
+    {
+        #region API
+
+        public static IEnumerable<SchemaProcessor> GetExtensionsProcessors()
+        {
+            // material extensions       
+            yield return new UnlitExtension();
+            yield return new IorExtension();
+            yield return new SheenExtension();
+            yield return new VolumeExtension();
+            yield return new SpecularExtension();
+            yield return new ClearCoatExtension();
+            yield return new DispersionExtension();
+            yield return new AnisotropyExtension();
+            yield return new IridescenceExtension();
+            yield return new TransmissionExtension();
+            yield return new DiffuseTransmissionExtension();
+            yield return new EmissiveStrengthExtension();
+            yield return new SpecularGlossinessExtension();
+
+            // lights
+            yield return new LightsPunctualExtension();
+
+            // gpu mesh instancing
+            yield return new MeshGpuInstancingExtension();
+
+            // textures
+            yield return new TextureTransformExtension();
+            yield return new TextureDDSExtension();
+            yield return new TextureWebpExtension();
+            yield return new TextureKtx2Extension();
+
+            // other
+            yield return new XmpJsonLdExtension();
+
+            yield return new AnimationPointerExtension();
+        }
+
+        #endregion
+
+        #region root paths        
+
+        /// <summary>
+        /// Program directory
+        /// </summary>
+        public static string ProgramDirectory => System.IO.Path.GetDirectoryName(typeof(KhronosExtensions).Assembly.Location);
+
+        /// <summary>
+        /// Directory where the schema is downloaded and used as source
+        /// </summary>
+        public static string LocalRepoDirectory => System.IO.Path.Combine(ProgramDirectory, "glTF");
+
+        #endregion        
+
+        #region extension paths        
+        private static string ArchivedSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Archived");
+        private static string KhronosSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Khronos");
+        private static string VendorSchemaDir => System.IO.Path.Combine(LocalRepoDirectory, "extensions", "2.0", "Vendor");
+
+        internal static string ArchivedExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(ArchivedSchemaDir, ext, "schema", json);
+        }
+
+        internal static string KhronosExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(KhronosSchemaDir, ext, "schema", json);
+        }
+        
+        internal static string VendorExtensionPath(string ext, string json)
+        {
+            return System.IO.Path.Combine(VendorSchemaDir, ext, "schema", json);
+        }
+
+        #endregion        
+    }
+}

+ 12 - 0
build/SharpGLTF.codeGen.Extensions.Khronos/SharpGLTF.codeGen.Extensions.Khronos.csproj

@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <RootNamespace>SharpGLTF</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\SharpGLTF.CodeGen.Core\SharpGLTF.CodeGen.Core.csproj" />
+  </ItemGroup>  
+
+</Project>