From ff683b9a78e1711d6d19ca35d8265e01852933fc Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Sun, 22 Feb 2026 16:21:49 +0100 Subject: [PATCH 1/6] Throw exception when unsupported extension is required --- .../plugins/gltf/CustomContentManager.java | 173 +++++++++++++----- .../jme3/scene/plugins/gltf/GltfModelKey.java | 35 ++++ 2 files changed, 161 insertions(+), 47 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java index 8606667eb5..eff5f69eb4 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java @@ -31,17 +31,22 @@ */ package com.jme3.scene.plugins.gltf; -import com.jme3.plugins.json.JsonArray; -import com.jme3.plugins.json.JsonElement; -import com.jme3.asset.AssetLoadException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import com.jme3.asset.AssetLoadException; +import com.jme3.plugins.json.JsonArray; +import com.jme3.plugins.json.JsonElement; +import com.jme3.plugins.json.JsonObject; + /** * Created by Nehon on 20/08/2017. */ @@ -56,6 +61,10 @@ public class CustomContentManager { private GltfLoader gltfLoader; + /** + * The mapping from glTF extension names to the classes that + * represent the respective laoders. + */ static final Map> defaultExtensionLoaders = new ConcurrentHashMap<>(); static { defaultExtensionLoaders.put("KHR_materials_pbrSpecularGlossiness", PBRSpecGlossExtensionLoader.class); @@ -64,9 +73,13 @@ public class CustomContentManager { defaultExtensionLoaders.put("KHR_texture_transform", TextureTransformExtensionLoader.class); defaultExtensionLoaders.put("KHR_materials_emissive_strength", PBREmissiveStrengthExtensionLoader.class); defaultExtensionLoaders.put("KHR_draco_mesh_compression", DracoMeshCompressionExtensionLoader.class); - } + /** + * The mapping from glTF extension names to the actual loader instances + * that have been lazily created from the defaultExtensionLoaders, + * in {@link #findExtensionLoader(String)} + */ private final Map loadedExtensionLoaders = new HashMap<>(); public CustomContentManager() { @@ -104,30 +117,82 @@ void init(GltfLoader gltfLoader) { this.key = (GltfModelKey) gltfLoader.getInfo().getKey(); } - JsonArray extensionUsed = gltfLoader.getDocRoot().getAsJsonArray("extensionsUsed"); - if (extensionUsed != null) { - for (JsonElement extElem : extensionUsed) { - String ext = extElem.getAsString(); - if (ext != null) { - if (defaultExtensionLoaders.get(ext) == null && (this.key != null && this.key.getExtensionLoader(ext) == null)) { - logger.log(Level.WARNING, "Extension " + ext + " is not supported, please provide your own implementation in the GltfModelKey"); - } - } + // For extensions that are USED but not supported, print a warning + List extensionsUsed = getArrayAsStringList(gltfLoader.getDocRoot(), "extensionsUsed"); + for (String extensionName : extensionsUsed) { + if (!isExtensionSupported(extensionName)) { + logger.log(Level.WARNING, "Extension " + extensionName + + " is not supported, please provide your own implementation in the GltfModelKey"); } } - JsonArray extensionRequired = gltfLoader.getDocRoot().getAsJsonArray("extensionsRequired"); - if (extensionRequired != null) { - for (JsonElement extElem : extensionRequired) { - String ext = extElem.getAsString(); - if (ext != null) { - if (defaultExtensionLoaders.get(ext) == null && (this.key != null && this.key.getExtensionLoader(ext) == null)) { - logger.log(Level.SEVERE, "Extension " + ext + " is mandatory for this file, the loaded scene result will be unexpected."); - } + + // For extensions that are REQUIRED but not supported, + // throw an AssetLoadException by default + // If the GltfModelKey#isStrict returns false, then + // still print an error message, at least + List extensionsRequired = getArrayAsStringList(gltfLoader.getDocRoot(), "extensionsRequired"); + for (String extensionName : extensionsRequired) { + if (!isExtensionSupported(extensionName)) { + if (this.key != null && this.key.isStrict()) { + throw new AssetLoadException( + "Extension " + extensionName + " is required for this file."); + } else { + logger.log(Level.SEVERE, "Extension " + extensionName + + " is required for this file. The behavior of the loader is unspecified."); } } } } + /** + * Returns a (possibly unmodifiable) list of the string representations of the elements in the specified + * array, or an empty list if the specified array does not exist. + * + * @param jsonObject + * The JSON object + * @param property + * The property name of the array property + * @return The list + */ + private static List getArrayAsStringList(JsonObject jsonObject, String property) { + JsonArray jsonArray = jsonObject.getAsJsonArray(property); + if (jsonArray == null) { + return Collections.emptyList(); + } + List list = new ArrayList(); + for (JsonElement jsonElement : jsonArray) { + String string = jsonElement.getAsString(); + if (string != null) { + list.add(string); + } + } + return list; + } + + /** + * Returns whether the specified glTF extension is supported. + * + * The given string is the name of the extension, e.g. KHR_texture_transform. + * + * This will return whether there is a default extension loader for the given extension registered in the + * {@link #defaultExtensionLoaders}, or whether the GltfModelKey that was obtained from the + * GltfLoader contains a custom extension loader that was registered via + * {@link GltfModelKey#registerExtensionLoader(String, ExtensionLoader)}. + * + * @param ext + * The glTF extension name + * @return Whether the given extension is supported + */ + private boolean isExtensionSupported(String ext) { + if (defaultExtensionLoaders.containsKey(ext)) { + return true; + } + if (this.key != null && this.key.getExtensionLoader(ext) != null) { + return true; + } + return false; + } + public T readExtensionAndExtras(String name, JsonElement el, T input) throws AssetLoadException, IOException { T output = readExtension(name, el, input); output = readExtras(name, el, output); @@ -142,36 +207,11 @@ private T readExtension(String name, JsonElement el, T input) throws AssetLo } for (Map.Entry ext : extensions.getAsJsonObject().entrySet()) { - ExtensionLoader loader = null; - - if (key != null) { - loader = key.getExtensionLoader(ext.getKey()); - } - - if (loader == null) { - loader = loadedExtensionLoaders.get(ext.getKey()); - if (loader == null) { - try { - Class clz = defaultExtensionLoaders.get(ext.getKey()); - if (clz != null) { - loader = clz.getDeclaredConstructor().newInstance(); - } - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { - logger.log(Level.WARNING, "Could not instantiate loader", e); - } - - if (loader != null) { - loadedExtensionLoaders.put(ext.getKey(), loader); - } - } - } - - + ExtensionLoader loader = findExtensionLoader(ext.getKey()); if (loader == null) { logger.log(Level.WARNING, "Could not find loader for extension " + ext.getKey()); continue; } - try { return (T) loader.handleExtension(gltfLoader, name, el, ext.getValue(), input); } catch (ClassCastException e) { @@ -182,6 +222,45 @@ private T readExtension(String name, JsonElement el, T input) throws AssetLo return input; } + /** + * Returns the ExtensionLoader for the given glTF extension name. + * + * The extension name is a name like KHR_texture_transform. This method will first try to + * return the custom extension loader that was registered in the GltfModelKey. + * + * If it does not exist, it will return an instance of the default extension loader that was registered + * for the given extension, lazily creating the instance based on the registered defaultExtensionLoaders. + * + * @param extensionName + * The extension name + * @return The loader, or null if no loader could be found or instantiated + */ + private ExtensionLoader findExtensionLoader(String extensionName) { + if (key != null) { + ExtensionLoader loader = key.getExtensionLoader(extensionName); + if (loader != null) { + return loader; + } + } + + ExtensionLoader loader = loadedExtensionLoaders.get(extensionName); + if (loader != null) { + return loader; + } + try { + Class clz = defaultExtensionLoaders.get(extensionName); + if (clz != null) { + loader = clz.getDeclaredConstructor().newInstance(); + loadedExtensionLoaders.put(extensionName, loader); + } + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException | SecurityException e) { + logger.log(Level.WARNING, "Could not instantiate loader", e); + } + return loader; + + } + @SuppressWarnings("unchecked") private T readExtras(String name, JsonElement el, T input) throws AssetLoadException { ExtrasLoader loader = null; diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java index 26da82bb3f..c46767fc71 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java @@ -57,11 +57,46 @@ public class GltfModelKey extends ModelKey { private boolean keepSkeletonPose = false; private ExtrasLoader extrasLoader; + /** + * The flag indicating whether the loader should perform stricter consistency checks of the supported glTF + * extensions. + * + * When this is true, then the loader will cause an AssetLoadException when it + * encounters an asset that contains an extension in its extensionsRequired declaration that + * is not supported. + */ + private boolean strictExtensionCheck; + public GltfModelKey(String name) { super(name); + this.strictExtensionCheck = true; } public GltfModelKey() { + this.strictExtensionCheck = true; + } + + /** + * Set whether the loader should perform stricter consistency checks when loading a model. Details are not + * specified for now. + * + * The default value is true. + * + * @param strict + * The flag + */ + public void setStrict(boolean strict) { + this.strictExtensionCheck = strict; + } + + /** + * Returns whether the loader should perform stricter consistency checks when loading a model. Details are + * not specified for now. + * + * @return The flag + */ + public boolean isStrict() { + return strictExtensionCheck; } /** From 9bf1df45f3bb918e9d4466ec2418d9548ae9c17b Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Sun, 1 Mar 2026 14:49:23 +0100 Subject: [PATCH 2/6] Initialize variable in declaration --- .../gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java index c46767fc71..5034191f9f 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java @@ -65,15 +65,13 @@ public class GltfModelKey extends ModelKey { * encounters an asset that contains an extension in its extensionsRequired declaration that * is not supported. */ - private boolean strictExtensionCheck; + private boolean strictExtensionCheck = true; public GltfModelKey(String name) { super(name); - this.strictExtensionCheck = true; } public GltfModelKey() { - this.strictExtensionCheck = true; } /** From 1d54bc4580ce5babf85de1c3d945dfd820307731 Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Sun, 1 Mar 2026 14:53:31 +0100 Subject: [PATCH 3/6] Add unit test for extension handling --- .../scene/plugins/gltf/GltfLoaderTest.java | 72 ++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java index d9b873afa9..ebec4b4300 100644 --- a/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java +++ b/jme3-plugins/src/test/java/com/jme3/scene/plugins/gltf/GltfLoaderTest.java @@ -40,8 +40,10 @@ import com.jme3.material.plugin.TestMaterialWrite; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; +import com.jme3.scene.Mesh; import com.jme3.scene.Node; import com.jme3.scene.Spatial; +import com.jme3.scene.VertexBuffer; import com.jme3.system.JmeSystem; import org.junit.Assert; @@ -69,8 +71,8 @@ public void init() { public void testLoad() { Spatial scene = assetManager.loadModel("gltf/box/box.gltf"); dumpScene(scene, 0); -// scene = assetManager.loadModel("gltf/hornet/scene.gltf"); -// dumpScene(scene, 0); + // scene = assetManager.loadModel("gltf/hornet/scene.gltf"); + // dumpScene(scene, 0); } @Test @@ -95,6 +97,72 @@ public void testLightsPunctualExtension() { } } + + @Test + public void testRequiredExtensionHandling() { + + // By default, the unsupported extension that is listed in + // the 'extensionsRequired' will cause an AssetLoadException + Assert.assertThrows(AssetLoadException.class, () -> { + GltfModelKey gltfModelKey = new GltfModelKey("gltf/TriangleUnsupportedExtensionRequired.gltf"); + Spatial scene = assetManager.loadModel(gltfModelKey); + dumpScene(scene, 0); + }); + + // When setting the 'strict' flag to 'false', then the + // asset will be loaded despite the unsupported extension + try { + GltfModelKey gltfModelKey = new GltfModelKey("gltf/TriangleUnsupportedExtensionRequired.gltf"); + gltfModelKey.setStrict(false); + Spatial scene = assetManager.loadModel(gltfModelKey); + dumpScene(scene, 0); + } catch (AssetLoadException ex) { + ex.printStackTrace(); + Assert.fail("Failed to load TriangleUnsupportedExtensionRequired"); + } + + } + + @Test + public void testDracoExtension() { + try { + Spatial scene = assetManager.loadModel("gltf/unitSquare11x11_unsignedShortTexCoords-draco.glb"); + + Node node0 = (Node) scene; + Node node1 = (Node) node0.getChild(0); + Node node2 = (Node) node1.getChild(0); + Geometry geometry = (Geometry) node2.getChild(0); + Mesh mesh = geometry.getMesh(); + + // The geometry has 11x11 vertices arranged in a square, + // so there are 10 x 10 * 2 triangles + VertexBuffer indices = mesh.getBuffer(VertexBuffer.Type.Index); + Assert.assertEquals(10 * 10 * 2, indices.getNumElements()); + Assert.assertEquals(VertexBuffer.Format.UnsignedShort, indices.getFormat()); + + // All attributes of the 11 x 11 vertices are stored as Float + // attributes (even the texture coordinates, which originally + // had been normalized(!) unsigned shorts!) + VertexBuffer positions = mesh.getBuffer(VertexBuffer.Type.Position); + Assert.assertEquals(11 * 11, positions.getNumElements()); + Assert.assertEquals(VertexBuffer.Format.Float, positions.getFormat()); + + VertexBuffer normal = mesh.getBuffer(VertexBuffer.Type.Normal); + Assert.assertEquals(11 * 11, normal.getNumElements()); + Assert.assertEquals(VertexBuffer.Format.Float, normal.getFormat()); + + VertexBuffer texCoord = mesh.getBuffer(VertexBuffer.Type.TexCoord); + Assert.assertEquals(11 * 11, texCoord.getNumElements()); + Assert.assertEquals(VertexBuffer.Format.Float, texCoord.getFormat()); + + dumpScene(scene, 0); + + } catch (AssetLoadException ex) { + ex.printStackTrace(); + Assert.fail("Failed to import unitSquare11x11_unsignedShortTexCoords"); + } + } + private void dumpScene(Spatial s, int indent) { System.err.print(indentString.substring(0, indent) + s.getName() + " (" + s.getClass().getSimpleName() + ") / " + s.getLocalTransform().getTranslation().toString() + ", " + From 3f098b8b5b950f6040c76476330810bafbbca937 Mon Sep 17 00:00:00 2001 From: Marco Hutter Date: Sun, 1 Mar 2026 14:56:36 +0100 Subject: [PATCH 4/6] Add assets for extension handling unit tests --- .../src/test/resources/gltf/README.md | 13 +++ .../TriangleUnsupportedExtensionRequired.gltf | 78 ++++++++++++++++++ ...uare11x11_unsignedShortTexCoords-draco.glb | Bin 0 -> 2752 bytes 3 files changed, 91 insertions(+) create mode 100644 jme3-plugins/src/test/resources/gltf/README.md create mode 100644 jme3-plugins/src/test/resources/gltf/TriangleUnsupportedExtensionRequired.gltf create mode 100644 jme3-plugins/src/test/resources/gltf/unitSquare11x11_unsignedShortTexCoords-draco.glb diff --git a/jme3-plugins/src/test/resources/gltf/README.md b/jme3-plugins/src/test/resources/gltf/README.md new file mode 100644 index 0000000000..4072c90f66 --- /dev/null +++ b/jme3-plugins/src/test/resources/gltf/README.md @@ -0,0 +1,13 @@ +# Models for the glTF loader unit tests + +Used in `com.jme3.scene.plugins.gltf.GltfLoaderTest` + +- `TriangleUnsupportedExtensionRequired.gltf` is the embedded representation of + the `Triangle` sample asset, with additional declarations in `extensionsUsed` + and `extensionsRequired`, to test the behavior of the loader when encountering + unknown extensions +- `unitSquare11x11_unsignedShortTexCoords-draco.glb` is a simple unit square with + 11x11 vertices, and texture coordinates that are stored as (normalized) unsigned + short values. The asset is draco-compressed, to check the behavior of the Draco + extension handler. + diff --git a/jme3-plugins/src/test/resources/gltf/TriangleUnsupportedExtensionRequired.gltf b/jme3-plugins/src/test/resources/gltf/TriangleUnsupportedExtensionRequired.gltf new file mode 100644 index 0000000000..c7216a38f9 --- /dev/null +++ b/jme3-plugins/src/test/resources/gltf/TriangleUnsupportedExtensionRequired.gltf @@ -0,0 +1,78 @@ +{ + "extensionsUsed": [ + "KHR_texture_transform", + "EXAMPLE_unsupported_extension" + ], + "extensionsRequired": [ + "KHR_texture_transform", + "EXAMPLE_unsupported_extension" + ], + "scene" : 0, + "scenes" : [ + { + "nodes" : [ 0 ] + } + ], + + "nodes" : [ + { + "mesh" : 0 + } + ], + + "meshes" : [ + { + "primitives" : [ { + "attributes" : { + "POSITION" : 1 + }, + "indices" : 0 + } ] + } + ], + + "buffers" : [ + { + "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=", + "byteLength" : 44 + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 6, + "target" : 34963 + }, + { + "buffer" : 0, + "byteOffset" : 8, + "byteLength" : 36, + "target" : 34962 + } + ], + "accessors" : [ + { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 3, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 0 ] + }, + { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 3, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + } + ], + + "asset" : { + "version" : "2.0" + } +} diff --git a/jme3-plugins/src/test/resources/gltf/unitSquare11x11_unsignedShortTexCoords-draco.glb b/jme3-plugins/src/test/resources/gltf/unitSquare11x11_unsignedShortTexCoords-draco.glb new file mode 100644 index 0000000000000000000000000000000000000000..34421a09e1f3132a730646871eb25b4a26e891f4 GIT binary patch literal 2752 zcmcIkd011~6@Lk_EXvw;=BrYTZ^BZE7!qU&vPqBxfk49c0RduoKxVRF7Qm!|6y-x_ zY%LM1z~F$NsNjGDsGtODiuqlFg0EY%Z_9qV2vH%AL7pf;XJW0 zLo7l>vPk{HUKcV2b;?Bm(2Yb=5x-A~4h*2YHNoxs1Q)Uk5f*Z@0g?;Rg-GH6iw~&8 zlZfEq{OHa8GlBe8^fz?%=prBnSHM>wDKJ$gks~U=;gCEv6_G^qkt~A-1{$`4-Afhx`I!tvTySbtSejplMHso(4P(VCDlX8U_0&oa=xw9nP3^v${SY&Pqy=aCzb+Az+e(wmcBsa7#AM7wrx`?hjD{m2OZ1?Eak+ z8C0p_poNM6F@OlJ849$17E&I#wFd9TI=BiTTEFmLbfcu`8N|c?gEGi`QyvRBEayx9 ze~t=|Pxu)G?Pr8RC&I&m%+0ofHw)vozcCJa*OM-i$ig+_W6#IN#$bk~$kujzl3)z{EXf}) zPO0uN7X-YeVot+#uZ2fbY-Y2z>l4-a;-0SWwrQ0Yw-8ExQ2=3ns;B(#IC>>(bXWd` z#>Rnn=vSbX+WLC(qwI=J%kxwFO~N}C0@V9(*$M@@p`qc@&71v2XU~?dtSBh%?rC4I z%CfR9H!jS~)X5d*{U=&meUuZ;^FAC7CuwP@zyD9Y&M}B&OLk>JhTRk zKd(fSvC~l1v9iUnZ=0LFl;H^u)m2pw_WAmHZCVVwkjTNNKegPJL-q2?4TWy>>TXq5 z+Fffs^MdVH8^5@`+~iHafB*jE>gsU+Ow=dawr+jVH<2b3cF!{%mM16eRmQP#aVx!6 zV{vx=f&evR3~(OH?9IkraQPIs4{c{L2gvw}>u0akeEZ4V&;nrNOGaIQQ!r3r%>SxcMiF=GZJUvajNBYRV1qB5azHQrWZ3&lJ>fZIc^N~{o zPobbrVT3~Ajm{hMLqnyZB`Pmio{z<3zGcp!CZ%5b{{;i_L zWbxG1t4^iPH9}ePs$(7d^~-zTMBaLp_~i0Ib;4=-^T&y}<<5zT%I-4u^%rKEqQ;$k+1YuJx?5_E*f4AdOX(QU z8-nnQPJMgZcEyKJY)a<(M-?#$httK+aj{8Bjh$zxbEiJ#WPdd?J6p|(X&V|j!`mUZ zVbl%9ld-hoeTBl=qW0hcQ~8C2n`i6IoTLt1o4L&2L2Vg!cKYWFAS(OCWgOe_|I0lp(07;Fc| z6mnnqe3o4^%kHb5Wk=PZe|^>HKbY$WVChHHHcU`Y^)4O8T8AA+6aER8}bzux?wHOA<;rTJGreNGRf&*d~Z)~zy2bUK|SinJn literal 0 HcmV?d00001 From 5e26893add017a95d254768d5daca9f18f683cb0 Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Sun, 1 Mar 2026 20:08:50 +0100 Subject: [PATCH 5/6] strict by default Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../com/jme3/scene/plugins/gltf/CustomContentManager.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java index eff5f69eb4..e4e504e1ef 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/CustomContentManager.java @@ -133,12 +133,12 @@ void init(GltfLoader gltfLoader) { List extensionsRequired = getArrayAsStringList(gltfLoader.getDocRoot(), "extensionsRequired"); for (String extensionName : extensionsRequired) { if (!isExtensionSupported(extensionName)) { - if (this.key != null && this.key.isStrict()) { - throw new AssetLoadException( - "Extension " + extensionName + " is required for this file."); - } else { + if (this.key != null && !this.key.isStrict()) { logger.log(Level.SEVERE, "Extension " + extensionName + " is required for this file. The behavior of the loader is unspecified."); + } else { + throw new AssetLoadException( + "Extension " + extensionName + " is required for this file."); } } } From 06db0fb853d0f099af5929ea1e60e474467e2c4b Mon Sep 17 00:00:00 2001 From: Riccardo Balbo Date: Sun, 1 Mar 2026 20:12:02 +0100 Subject: [PATCH 6/6] improve javadoc Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../com/jme3/scene/plugins/gltf/GltfModelKey.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java index 5034191f9f..2490243a00 100644 --- a/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java +++ b/jme3-plugins/src/gltf/java/com/jme3/scene/plugins/gltf/GltfModelKey.java @@ -75,10 +75,11 @@ public GltfModelKey() { } /** - * Set whether the loader should perform stricter consistency checks when loading a model. Details are not - * specified for now. + * Set whether the loader should perform stricter consistency checks of the supported glTF extensions. * - * The default value is true. + * When this is true (the default), the loader will cause an AssetLoadException when it + * encounters an asset that contains an extension in its extensionsRequired declaration that + * is not supported. When false, it will only log a SEVERE message. * * @param strict * The flag @@ -88,8 +89,11 @@ public void setStrict(boolean strict) { } /** - * Returns whether the loader should perform stricter consistency checks when loading a model. Details are - * not specified for now. + * Returns whether the loader should perform stricter consistency checks of the supported glTF extensions. + * + * When this is true (the default), the loader will cause an AssetLoadException when it + * encounters an asset that contains an extension in its extensionsRequired declaration that + * is not supported. When false, it will only log a SEVERE message. * * @return The flag */