diff --git a/CHANGELOG.md b/CHANGELOG.md index cf74bf3..fb9f6fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ changed functionality, fixed bugs). ## Version 1.6 (in development) - Support linked collections used as input in a Geometry Nodes modifier. +- Support collections, objects, images, and textures used as default values in nodes. ## Version 1.5.1 (2021-07-22) diff --git a/blender_asset_tracer/cdefs.py b/blender_asset_tracer/cdefs.py index bbc9bd1..a77eac0 100644 --- a/blender_asset_tracer/cdefs.py +++ b/blender_asset_tracer/cdefs.py @@ -72,6 +72,23 @@ IDP_DOUBLE = 8 IDP_IDPARRAY = 9 IDP_NUMTYPES = 10 +# DNA_node_types.h +SOCK_CUSTOM = -1 # socket has no integer type +SOCK_FLOAT = 0 +SOCK_VECTOR = 1 +SOCK_RGBA = 2 +SOCK_SHADER = 3 +SOCK_BOOLEAN = 4 +SOCK_MESH = 5 # deprecated +SOCK_INT = 6 +SOCK_STRING = 7 +SOCK_OBJECT = 8 +SOCK_IMAGE = 9 +SOCK_GEOMETRY = 10 +SOCK_COLLECTION = 11 +SOCK_TEXTURE = 12 +SOCK_MATERIAL = 13 + # BKE_pointcache.h PTCACHE_FILE_PTCACHE = 0 PTCACHE_FILE_OPENVDB = 1 diff --git a/blender_asset_tracer/trace/expanders.py b/blender_asset_tracer/trace/expanders.py index 6b8da42..5285585 100644 --- a/blender_asset_tracer/trace/expanders.py +++ b/blender_asset_tracer/trace/expanders.py @@ -93,15 +93,35 @@ def _expand_generic_nodetree(block: blendfile.BlendFileBlock): assert block.dna_type.dna_type_id == b"bNodeTree" nodes = block.get_pointer((b"nodes", b"first")) + + # See DNA_node_types.h + socket_types_with_value_pointer = { + cdefs.SOCK_OBJECT, # bNodeSocketValueObject + cdefs.SOCK_IMAGE, # bNodeSocketValueImage + cdefs.SOCK_COLLECTION, # bNodeSocketValueCollection + cdefs.SOCK_TEXTURE, # bNodeSocketValueTexture + cdefs.SOCK_MATERIAL, # bNodeSocketValueMaterial + } + for node in iterators.listbase(nodes): if node[b"type"] == cdefs.CMP_NODE_R_LAYERS: continue - yield node # The 'id' property points to whatever is used by the node # (like the image in an image texture node). yield node.get_pointer(b"id") + # Default values of inputs can also point to ID datablocks. + inputs = node.get_pointer((b"inputs", b"first")) + for input in iterators.listbase(inputs): + if input[b"type"] not in socket_types_with_value_pointer: + continue + value_container = input.get_pointer(b"default_value") + if not value_container: + continue + value = value_container.get_pointer(b"value") + yield value + def _expand_generic_idprops(block: blendfile.BlendFileBlock): """Yield ID datablocks and their libraries referenced from ID properties.""" diff --git a/tests/blendfiles/geometry-nodes-3/lib_trash.blend b/tests/blendfiles/geometry-nodes-3/lib_trash.blend new file mode 100644 index 0000000..c021619 Binary files /dev/null and b/tests/blendfiles/geometry-nodes-3/lib_trash.blend differ diff --git a/tests/blendfiles/geometry-nodes-3/set_file.blend b/tests/blendfiles/geometry-nodes-3/set_file.blend new file mode 100644 index 0000000..4eb237a Binary files /dev/null and b/tests/blendfiles/geometry-nodes-3/set_file.blend differ diff --git a/tests/blendfiles/geometry-nodes-3/shot_file.blend b/tests/blendfiles/geometry-nodes-3/shot_file.blend new file mode 100644 index 0000000..025d169 Binary files /dev/null and b/tests/blendfiles/geometry-nodes-3/shot_file.blend differ diff --git a/tests/test_tracer.py b/tests/test_tracer.py index caa744d..96c11e5 100644 --- a/tests/test_tracer.py +++ b/tests/test_tracer.py @@ -464,6 +464,34 @@ class DepsTest(AbstractTracerTest): }, ) + def test_geometry_nodes_node_input(self): + """Test linked collection as input to a geom node. + + Here a Geometry Nodes node references a collection that is not instanced + into the scene, which caused it to be missed. + """ + self.assert_deps( + "geometry-nodes-3/shot_file.blend", + { + b"LIset_file.blend": Expect( + type="Library", + full_field="name[1024]", + dirname_field=None, + basename_field=None, + asset_path=b"//set_file.blend", + is_sequence=False, + ), + b"LIlib_trash.blend": Expect( + type="Library", + full_field="name[1024]", + dirname_field=None, + basename_field=None, + asset_path=b"//lib_trash.blend", + is_sequence=False, + ), + }, + ) + def test_usage_abspath(self): deps = [ dep