From c6dca17b9c80cc317b8d8d2753faba46c31a1ddb Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Thu, 25 Dec 2025 21:47:41 -0800 Subject: [PATCH] Change skinned mesh warning to only consider transformed parent nodes --- CHANGELOG.md | 8 ++++++++ ISSUES.md | 3 ++- lib/src/base/gltf.dart | 16 ++++++++++++---- lib/src/errors.dart | 18 ++++++++++++------ .../ignored_parent_transform.gltf.report.json | 12 +++++++++--- 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76e25ede..6a4c2ef8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +### New Features + +* Added new `NODE_SKINNED_MESH_PARENT_TRANSFORMS` validation warning. + +### Changes + +* Changed `NODE_SKINNED_MESH_NON_ROOT` default severity to Information. + ## 2.0.0-dev.3.10 ### New Features diff --git a/ISSUES.md b/ISSUES.md index 5d17ed5b..b81e4772 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -66,7 +66,8 @@ |NODE_MATRIX_NON_TRS|Matrix must be decomposable to TRS.|Error| |NODE_MATRIX_TRS|A node can have either a matrix or any combination of translation/rotation/scale (TRS) properties.|Error| |NODE_SKINNED_MESH_LOCAL_TRANSFORMS|Local transforms will not affect a skinned mesh.|Warning| -|NODE_SKINNED_MESH_NON_ROOT|Node with a skinned mesh is not root. Parent transforms will not affect a skinned mesh.|Warning| +|NODE_SKINNED_MESH_NON_ROOT|Node with a skinned mesh is not root. Parent transforms will not affect a skinned mesh.|Information| +|NODE_SKINNED_MESH_PARENT_TRANSFORMS|Node with a skinned mesh has parent nodes with transforms. Parent transforms will not affect a skinned mesh.|Warning| |NODE_SKIN_NO_SCENE|A node with a skinned mesh is used in a scene that does not contain joint nodes.|Error| |NON_OBJECT_EXTRAS|Prefer JSON Objects for extras.|Information| |NON_RELATIVE_URI|Non-relative URI found: '`%1`'.|Warning| diff --git a/lib/src/base/gltf.dart b/lib/src/base/gltf.dart index 424cb63d..575c3e9b 100644 --- a/lib/src/base/gltf.dart +++ b/lib/src/base/gltf.dart @@ -308,14 +308,22 @@ class Gltf extends GltfProperty { // Node has a skinned mesh, check hierarchy and scenes if (node.skin != null) { - if (node.parent != null) { - context.addIssue(SemanticError.nodeSkinnedMeshNonRoot, index: i); - } - if (node.hasTransform) { context.addIssue(SemanticError.nodeSkinnedMeshLocalTransforms, index: i); } + if (node.parent != null) { + var parent = node.parent; + while (parent != null) { + if (parent.hasTransform) { + context.addIssue(SemanticError.nodeSkinnedMeshParentTransforms, + index: i); + break; + } + parent = parent.parent; + } + context.addIssue(SemanticError.nodeSkinnedMeshNonRoot, index: i); + } final topCommonRoot = node.skin.commonRoots .firstWhere((root) => root.parent == null, orElse: () => null); diff --git a/lib/src/errors.dart b/lib/src/errors.dart index b07e28f5..39e23132 100644 --- a/lib/src/errors.dart +++ b/lib/src/errors.dart @@ -441,17 +441,23 @@ class SemanticError extends IssueType { static final SemanticError nodeEmpty = SemanticError._( 'NODE_EMPTY', (args) => 'Empty node encountered.', Severity.Information); - static final SemanticError nodeSkinnedMeshNonRoot = SemanticError._( - 'NODE_SKINNED_MESH_NON_ROOT', - (args) => 'Node with a skinned mesh is not root. ' - 'Parent transforms will not affect a skinned mesh.', - Severity.Warning); - static final SemanticError nodeSkinnedMeshLocalTransforms = SemanticError._( 'NODE_SKINNED_MESH_LOCAL_TRANSFORMS', (args) => 'Local transforms will not affect a skinned mesh.', Severity.Warning); + static final SemanticError nodeSkinnedMeshParentTransforms = SemanticError._( + 'NODE_SKINNED_MESH_PARENT_TRANSFORMS', + (args) => 'Node with a skinned mesh has parent nodes with transforms. ' + 'Parent transforms will not affect a skinned mesh.', + Severity.Warning); + + static final SemanticError nodeSkinnedMeshNonRoot = SemanticError._( + 'NODE_SKINNED_MESH_NON_ROOT', + (args) => 'Node with a skinned mesh is not root. ' + 'Parent transforms will not affect a skinned mesh.', + Severity.Information); + static final SemanticError nodeSkinNoScene = SemanticError._( 'NODE_SKIN_NO_SCENE', (args) => 'A node with a skinned mesh is used in a scene that does not ' diff --git a/test/base/data/skin/ignored_parent_transform.gltf.report.json b/test/base/data/skin/ignored_parent_transform.gltf.report.json index 888ca5a5..e0b35fd9 100644 --- a/test/base/data/skin/ignored_parent_transform.gltf.report.json +++ b/test/base/data/skin/ignored_parent_transform.gltf.report.json @@ -5,13 +5,19 @@ "issues": { "numErrors": 0, "numWarnings": 1, - "numInfos": 1, + "numInfos": 2, "numHints": 0, "messages": [ + { + "code": "NODE_SKINNED_MESH_PARENT_TRANSFORMS", + "message": "Node with a skinned mesh has parent nodes with transforms. Parent transforms will not affect a skinned mesh.", + "severity": 1, + "pointer": "/nodes/2" + }, { "code": "NODE_SKINNED_MESH_NON_ROOT", "message": "Node with a skinned mesh is not root. Parent transforms will not affect a skinned mesh.", - "severity": 1, + "severity": 2, "pointer": "/nodes/2" }, { @@ -38,4 +44,4 @@ "maxInfluences": 4, "maxAttributes": 3 } -} \ No newline at end of file +}