Browse Source

improving extensions infrastructure.

Vicente Penades 6 years ago
parent
commit
7596f4f635

+ 5 - 0
src/SharpGLTF/Schema2/gltf.Animations.cs

@@ -36,6 +36,11 @@ namespace SharpGLTF.Schema2
 
         #region API
 
+        protected override IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            return base.GetLogicalChildren().Concat(_samplers).Concat(_channels);
+        }
+
         private AnimationSampler _CreateSampler(AnimationInterpolationMode interpolation)
         {
             var sampler = new AnimationSampler(interpolation);

+ 19 - 22
src/SharpGLTF/Schema2/gltf.ExtensionsFactory.cs

@@ -80,37 +80,34 @@ namespace SharpGLTF.Schema2
 
     partial class ModelRoot
     {
-        private IEnumerable<glTFProperty> _GetAllExtensionContainers()
+        internal void UpdateExtensionsSupport()
         {
-            IEnumerable<glTFProperty> containers = new glTFProperty[] { this, this.Asset };
-
-            containers = containers.Concat(this.LogicalAccessors);
-            containers = containers.Concat(this.LogicalAnimations);
-            containers = containers.Concat(this.LogicalBuffers);
-            containers = containers.Concat(this.LogicalBufferViews);
-            containers = containers.Concat(this.LogicalCameras);
-            containers = containers.Concat(this.LogicalImages);
-            containers = containers.Concat(this.LogicalMaterials);
-            containers = containers.Concat(this.LogicalMeshes);
-            containers = containers.Concat(this.LogicalNodes);
-            containers = containers.Concat(this.LogicalPunctualLights);
-            containers = containers.Concat(this.LogicalSamplers);
-            containers = containers.Concat(this.LogicalScenes);
-            containers = containers.Concat(this.LogicalSkins);
-            containers = containers.Concat(this.LogicalTextures);
-            return containers;
+            var used = RetrieveUsedExtensions();
+
+            // update the used list
+            this._extensionsUsed.Clear();
+            this._extensionsUsed.AddRange(used);
         }
 
-        internal void UpdateExtensionsSupport()
+        internal IEnumerable<string> RetrieveUsedExtensions()
         {
-            var usedExtensions = new HashSet<string>();
+            // retrieve ALL the property based objects of the whole model.
 
-            foreach (var c in _GetAllExtensionContainers())
+            var allObjects = GetLogicalChildren()
+                .SelectMany(item => glTFProperty.Flatten(item)
+                .ToList());
+
+            // check all the extensions used by each object
+            var used = new HashSet<string>();
+
+            foreach (var c in allObjects)
             {
                 var ids = c.Extensions.Select(item => ExtensionsFactory.Identify(c.GetType(), item.GetType()));
 
-                foreach (var id in ids) usedExtensions.Add(id);
+                foreach (var id in ids) used.Add(id);
             }
+
+            return used;
         }
 
         internal void UsingExtension(Type parentType, Type extensionType)

+ 8 - 1
src/SharpGLTF/Schema2/gltf.Materials.cs

@@ -63,6 +63,11 @@ namespace SharpGLTF.Schema2
 
         #region API
 
+        protected override IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            return base.GetLogicalChildren().Concat(_normalTexture, _emissiveTexture, _occlusionTexture, _pbrMetallicRoughness);
+        }
+
         /// <summary>
         /// Finds an instance of <see cref="MaterialChannelView"/>
         /// </summary>
@@ -128,7 +133,7 @@ namespace SharpGLTF.Schema2
 
         public Texture Texture => _TextureInfoGetter?.Invoke(false) == null ? null : _Material.LogicalParent.LogicalTextures[_TextureInfoGetter(false)._LogicalTextureIndex];
 
-        public int Set => _TextureInfoGetter?.Invoke(false) == null ? 0 : _TextureInfoGetter(false).TextureSet;
+        public int Set => _TextureInfoGetter?.Invoke(false)?.TextureSet ?? 0;
 
         public Image Image => Texture?.Source;
 
@@ -136,6 +141,8 @@ namespace SharpGLTF.Schema2
 
         public Vector4 Factor => _FactorGetter();
 
+        public TextureTransform Transform => _TextureInfoGetter?.Invoke(false)?.Transform;
+
         #endregion
 
         #region fluent API

+ 10 - 0
src/SharpGLTF/Schema2/gltf.MaterialsFactory.cs

@@ -137,6 +137,11 @@ namespace SharpGLTF.Schema2
 
     internal sealed partial class MaterialPBRMetallicRoughness
     {
+        protected override IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            return base.GetLogicalChildren().Concat(_baseColorTexture, _metallicRoughnessTexture);
+        }
+
         private TextureInfo _GetBaseTexture(bool create)
         {
             if (create && _baseColorTexture == null) _baseColorTexture = new TextureInfo();
@@ -184,6 +189,11 @@ namespace SharpGLTF.Schema2
     {
         internal MaterialPBRSpecularGlossiness(Material material) { }
 
+        protected override IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            return base.GetLogicalChildren().Concat(_diffuseTexture, _specularGlossinessTexture);
+        }
+
         private TextureInfo _GetDiffuseTexture(bool create)
         {
             if (create && _diffuseTexture == null) _diffuseTexture = new TextureInfo();

+ 5 - 0
src/SharpGLTF/Schema2/gltf.Mesh.cs

@@ -40,6 +40,11 @@ namespace SharpGLTF.Schema2
 
         #region API
 
+        protected override IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            return base.GetLogicalChildren().Concat(_primitives);
+        }
+
         /// <summary>
         /// Creates a new <see cref="MeshPrimitive"/> instance
         /// and adds it to the current <see cref="Mesh"/>.

+ 17 - 0
src/SharpGLTF/Schema2/gltf.Property.cs

@@ -71,6 +71,23 @@ namespace SharpGLTF.Schema2
             _extensions.RemoveAll(item => item.GetType() == typeof(T));
         }
 
+        protected virtual IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            return _extensions.OfType<glTFProperty>();
+        }
+
+        protected static IEnumerable<glTFProperty> Flatten(glTFProperty container)
+        {
+            yield return container;
+
+            foreach (var c in container.GetLogicalChildren())
+            {
+                var cc = Flatten(c);
+
+                foreach (var ccc in cc) yield return ccc;
+            }
+        }
+
         #endregion
 
         #region serialization API

+ 22 - 0
src/SharpGLTF/Schema2/gltf.Root.cs

@@ -90,6 +90,28 @@ namespace SharpGLTF.Schema2
         public IReadOnlyList<Scene>         LogicalScenes       => _scenes;
         public IReadOnlyList<Animation>     LogicalAnimations   => _animations;
 
+        protected override IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            var containers = base.GetLogicalChildren();
+
+            containers = containers.Concat(this.Asset);
+            containers = containers.Concat(this.LogicalAccessors);
+            containers = containers.Concat(this.LogicalAnimations);
+            containers = containers.Concat(this.LogicalBuffers);
+            containers = containers.Concat(this.LogicalBufferViews);
+            containers = containers.Concat(this.LogicalCameras);
+            containers = containers.Concat(this.LogicalImages);
+            containers = containers.Concat(this.LogicalMaterials);
+            containers = containers.Concat(this.LogicalMeshes);
+            containers = containers.Concat(this.LogicalNodes);
+            containers = containers.Concat(this.LogicalSamplers);
+            containers = containers.Concat(this.LogicalScenes);
+            containers = containers.Concat(this.LogicalSkins);
+            containers = containers.Concat(this.LogicalTextures);
+
+            return containers;
+        }
+
         #endregion
 
         #region Visual Tree

+ 36 - 1
src/SharpGLTF/Schema2/gltf.Textures.cs

@@ -23,6 +23,17 @@ namespace SharpGLTF.Schema2
             set => _texCoord = value.AsNullable(_texCoordDefault, _texCoordMinimum, int.MaxValue);
         }
 
+        public TextureTransform Transform
+        {
+            get => this.GetExtension<TextureTransform>();
+            set
+            {
+                if (value == null) { this.RemoveExtensions<TextureTransform>(); return; }
+
+                this.SetExtension(value);
+            }
+        }
+
         #endregion
     }
 
@@ -128,9 +139,33 @@ namespace SharpGLTF.Schema2
         #endregion
     }
 
-    partial class TextureTransform
+    public partial class TextureTransform
     {
         internal TextureTransform(TextureInfo parent) { }
+
+        public Vector2 Offset
+        {
+            get => _offset.AsValue(_offsetDefault);
+            set => _offset = value.AsNullable(_offsetDefault);
+        }
+
+        public Vector2 Scale
+        {
+            get => _scale.AsValue(_scaleDefault);
+            set => _scale = value.AsNullable(_scaleDefault);
+        }
+
+        public float Rotation
+        {
+            get => (float)_rotation.AsValue(_rotationDefault);
+            set => _rotation = ((double)value).AsNullable(_rotationDefault);
+        }
+
+        public int TextureCoordinate
+        {
+            get => _texCoord.AsValue(_texCoordMinimum);
+            set => _texCoord = value.AsNullable(_texCoordMinimum);
+        }
     }
 
     public partial class ModelRoot

+ 6 - 0
src/SharpGLTF/Schema2/khr.lights.cs

@@ -6,6 +6,7 @@ using System.Numerics;
 namespace SharpGLTF.Schema2
 {
     using Collections;
+    using System.Linq;
 
     partial class KHR_lights_punctualglTFextension
     {
@@ -14,6 +15,11 @@ namespace SharpGLTF.Schema2
             _lights = new ChildrenCollection<PunctualLight, ModelRoot>(root);
         }
 
+        protected override IEnumerable<glTFProperty> GetLogicalChildren()
+        {
+            return base.GetLogicalChildren().Concat(_lights);
+        }
+
         public IReadOnlyList<PunctualLight> Lights => _lights;
 
         public PunctualLight CreateLight(string name = null)

+ 6 - 0
src/SharpGLTF/_Extensions.cs

@@ -6,6 +6,7 @@ using System.Numerics;
 namespace SharpGLTF
 {
     using Schema2;
+    using System.Linq;
 
     /// <summary>
     /// Extensions used internally.
@@ -265,6 +266,11 @@ namespace SharpGLTF
             }
         }
 
+        internal static IEnumerable<T> Concat<T>(this IEnumerable<T> collection, params T[] instances)
+        {
+            return collection.Concat(instances.Where(item => item != null));
+        }
+
         #endregion
 
         #region vertex & index accessors

+ 10 - 1
tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadModelTests.cs

@@ -87,6 +87,12 @@ namespace SharpGLTF.Schema2.LoadAndSave
             {
                 if (!f.Contains(section)) continue;
 
+                if (section.Contains("glTF-pbrSpecularGlossiness"))
+                {
+                    // these ones are included in the pbrSpecularGlossiness but don't actually contain any extension
+                    if (f.EndsWith("BoxInterleaved.gltf")) continue;
+                }
+
                 var model = GltfUtils.LoadModel(f);
                 Assert.NotNull(model);
 
@@ -96,8 +102,11 @@ namespace SharpGLTF.Schema2.LoadAndSave
                 
                 // do a model roundtrip
                 var bytes = model.WriteGLB();
-
                 var modelBis = ModelRoot.ParseGLB(bytes);
+
+                // check extensions used
+                var detectedExtensions = model.RetrieveUsedExtensions().ToArray();
+                CollectionAssert.AreEquivalent(model.ExtensionsUsed, detectedExtensions);
             }
         }