Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### New Features

* Added support for the `KHR_node_visibility` extension.

* Added new `NODE_SKINNED_MESH_PARENT_TRANSFORMS` validation warning.

### Changes
Expand Down
34 changes: 34 additions & 0 deletions lib/src/ext/KHR_node_visibility/khr_node_visibility.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
library gltf.extensions.khr_node_visibility;

import 'package:gltf/src/base/gltf_property.dart';
import 'package:gltf/src/ext/extensions.dart';

const String KHR_NODE_VISIBILITY = 'KHR_node_visibility';
const String VISIBLE = 'visible';

const List<String> KHR_NODE_VISIBILITY_MEMBERS = <String>[
VISIBLE,
];

class KhrNodeVisibility extends GltfProperty {
final bool visible;

KhrNodeVisibility._(
this.visible, Map<String, Object> extensions, Object extras)
: super(extensions, extras);

static KhrNodeVisibility fromMap(Map<String, Object> map, Context context) {
if (context.validate) {
checkMembers(map, KHR_NODE_VISIBILITY_MEMBERS, context);
}
return KhrNodeVisibility._(
getBool(map, VISIBLE, context, def: true),
getExtensions(map, KhrNodeVisibility, context),
getExtras(map, context));
}
}

const Extension khrNodeVisibilityExtension =
Extension(KHR_NODE_VISIBILITY, <Type, ExtensionDescriptor>{
Node: ExtensionDescriptor(KhrNodeVisibility.fromMap),
});
3 changes: 3 additions & 0 deletions lib/src/ext/extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import 'package:gltf/src/ext/KHR_materials_unlit/khr_materials_unlit.dart';
import 'package:gltf/src/ext/KHR_materials_variants/KHR_materials_variants.dart';
import 'package:gltf/src/ext/KHR_materials_volume/khr_materials_volume.dart';
import 'package:gltf/src/ext/KHR_mesh_quantization/khr_mesh_quantization.dart';
import 'package:gltf/src/ext/KHR_node_visibility/khr_node_visibility.dart';
import 'package:gltf/src/ext/KHR_texture_transform/khr_texture_transform.dart';
import 'package:gltf/src/hash.dart';
import 'package:meta/meta.dart';
Expand All @@ -56,6 +57,7 @@ export 'package:gltf/src/ext/KHR_materials_unlit/khr_materials_unlit.dart';
export 'package:gltf/src/ext/KHR_materials_variants/KHR_materials_variants.dart';
export 'package:gltf/src/ext/KHR_materials_volume/khr_materials_volume.dart';
export 'package:gltf/src/ext/KHR_mesh_quantization/khr_mesh_quantization.dart';
export 'package:gltf/src/ext/KHR_node_visibility/khr_node_visibility.dart';
export 'package:gltf/src/ext/KHR_texture_transform/khr_texture_transform.dart';

class Extension {
Expand Down Expand Up @@ -120,5 +122,6 @@ const List<Extension> kDefaultExtensions = <Extension>[
khrMaterialsVariantsExtension,
khrMaterialsVolumeExtension,
khrMeshQuantizationExtension,
khrNodeVisibilityExtension,
khrTextureTransformExtension
];
11 changes: 8 additions & 3 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,22 @@ int getIndex(Map<String, Object> map, String name, Context context,
return -1;
}

bool getBool(Map<String, Object> map, String name, Context context) {
bool getBool(Map<String, Object> map, String name, Context context,
{bool req = false, bool def = false}) {
final value = _getGuarded(map, name, _kBoolean, context);
if (value == null) {
return false;
if (!req) {
return def;
}
context.addIssue(SchemaError.undefinedProperty, args: [name]);
return def;
}
if (value is bool) {
return value;
}
context
.addIssue(SchemaError.typeMismatch, name: name, args: [value, _kBoolean]);
return false;
return def;
}

int getUint(Map<String, Object> map, String name, Context context,
Expand Down
10 changes: 10 additions & 0 deletions test/ext/KHR_node_visibility/assets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"node": {
"name": "node.KHR_node_visibility",
"tests": {
"custom_property.gltf": "Custom property",
"unexpected_extension.gltf": "Unexpected extension object location",
"valid.gltf": "Valid"
}
}
}
13 changes: 13 additions & 0 deletions test/ext/KHR_node_visibility/data/node/custom_property.gltf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"asset": { "version": "2.0" },
"extensionsUsed": ["KHR_node_visibility"],
"nodes": [
{
"extensions": {
"KHR_node_visibility": {
"customProperty": true
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"uri": "test/ext/KHR_node_visibility/data/node/custom_property.gltf",
"mimeType": "model/gltf+json",
"issues": {
"numErrors": 0,
"numWarnings": 1,
"numInfos": 1,
"numHints": 0,
"messages": [
{
"code": "UNEXPECTED_PROPERTY",
"message": "Unexpected property.",
"severity": 1,
"pointer": "/nodes/0/extensions/KHR_node_visibility/customProperty"
},
{
"code": "UNUSED_OBJECT",
"message": "This object may be unused.",
"severity": 2,
"pointer": "/nodes/0"
}
],
"truncated": false
},
"info": {
"version": "2.0",
"extensionsUsed": ["KHR_node_visibility"],
"animationCount": 0,
"materialCount": 0,
"hasMorphTargets": false,
"hasSkins": false,
"hasTextures": false,
"hasDefaultScene": false,
"drawCallCount": 0,
"totalVertexCount": 0,
"totalTriangleCount": 0,
"maxUVs": 0,
"maxInfluences": 0,
"maxAttributes": 0
}
}
13 changes: 13 additions & 0 deletions test/ext/KHR_node_visibility/data/node/unexpected_extension.gltf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"asset": { "version": "2.0" },
"extensionsUsed": ["KHR_node_visibility"],
"materials": [
{
"extensions": {
"KHR_node_visibility": {
"visible": true
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"uri": "test/ext/KHR_node_visibility/data/node/unexpected_extension.gltf",
"mimeType": "model/gltf+json",
"issues": {
"numErrors": 1,
"numWarnings": 0,
"numInfos": 1,
"numHints": 0,
"messages": [
{
"code": "UNEXPECTED_EXTENSION_OBJECT",
"message": "Unexpected location for this extension.",
"severity": 0,
"pointer": "/materials/0/extensions/KHR_node_visibility"
},
{
"code": "UNUSED_OBJECT",
"message": "This object may be unused.",
"severity": 2,
"pointer": "/materials/0"
}
],
"truncated": false
},
"info": {
"version": "2.0",
"extensionsUsed": ["KHR_node_visibility"],
"animationCount": 0,
"materialCount": 1,
"hasMorphTargets": false,
"hasSkins": false,
"hasTextures": false,
"hasDefaultScene": false,
"drawCallCount": 0,
"totalVertexCount": 0,
"totalTriangleCount": 0,
"maxUVs": 0,
"maxInfluences": 0,
"maxAttributes": 0
}
}
9 changes: 9 additions & 0 deletions test/ext/KHR_node_visibility/data/node/valid.gltf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"asset": { "version": "2.0" },
"extensionsUsed": ["KHR_node_visibility"],
"nodes": [
{ "extensions": { "KHR_node_visibility": { "visible": false } }, "name": "InvisibleCube" },
{ "extensions": { "KHR_node_visibility": { "visible": true } }, "name": "VisibleCube" },
{ "extensions": { "KHR_node_visibility": {} }, "name": "EmptyExtensionObject" }
]
}
47 changes: 47 additions & 0 deletions test/ext/KHR_node_visibility/data/node/valid.gltf.report.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"uri": "test/ext/KHR_node_visibility/data/node/valid.gltf",
"mimeType": "model/gltf+json",
"issues": {
"numErrors": 0,
"numWarnings": 0,
"numInfos": 3,
"numHints": 0,
"messages": [
{
"code": "UNUSED_OBJECT",
"message": "This object may be unused.",
"severity": 2,
"pointer": "/nodes/0"
},
{
"code": "UNUSED_OBJECT",
"message": "This object may be unused.",
"severity": 2,
"pointer": "/nodes/1"
},
{
"code": "UNUSED_OBJECT",
"message": "This object may be unused.",
"severity": 2,
"pointer": "/nodes/2"
}
],
"truncated": false
},
"info": {
"version": "2.0",
"extensionsUsed": ["KHR_node_visibility"],
"animationCount": 0,
"materialCount": 0,
"hasMorphTargets": false,
"hasSkins": false,
"hasTextures": false,
"hasDefaultScene": false,
"drawCallCount": 0,
"totalVertexCount": 0,
"totalTriangleCount": 0,
"maxUVs": 0,
"maxInfluences": 0,
"maxAttributes": 0
}
}
46 changes: 46 additions & 0 deletions test/ext/KHR_node_visibility/khr_node_visibility_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* # Copyright (c) 2016-2026 The Khronos Group Inc.
* #
* # Licensed under the Apache License, Version 2.0 (the "License");
* # you may not use this file except in compliance with the License.
* # You may obtain a copy of the License at
* #
* # http://www.apache.org/licenses/LICENSE-2.0
* #
* # Unless required by applicable law or agreed to in writing, software
* # distributed under the License is distributed on an "AS IS" BASIS,
* # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* # See the License for the specific language governing permissions and
* # limitations under the License.
*/

import 'dart:async';

import 'package:gltf/gltf.dart';
import 'package:test/test.dart';

import '../../utils.dart';

Future main() async {
await compareReports('test/ext/KHR_node_visibility');

group('Evaluate valid objects', () {
test('node.KHR_node_visibility', () async {
final gltf = (await read('ext/KHR_node_visibility/data/node/valid.gltf',
ignoreUnused: true))
.gltf;

final invisibleNodeVisibility =
gltf.nodes[0].extensions['KHR_node_visibility'] as KhrNodeVisibility;
expect(invisibleNodeVisibility.visible, isFalse);

final visibleNodeVisibility =
gltf.nodes[1].extensions['KHR_node_visibility'] as KhrNodeVisibility;
expect(visibleNodeVisibility.visible, isTrue);

final emptyExtensionObject =
gltf.nodes[2].extensions['KHR_node_visibility'] as KhrNodeVisibility;
expect(emptyExtensionObject.visible, isTrue);
});
});
}