Last active
September 8, 2024 19:35
-
-
Save zvodd/f65116412a3eaaf292fead54b1b952cd to your computer and use it in GitHub Desktop.
Blender 4 instance enumeration - Including unrealized Geometry Node generated instances.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
# https://docs.blender.org/api/current/bpy.types.Depsgraph.html | |
# https://docs.blender.org/api/current/bpy.types.DepsgraphObjectInstance.html | |
def report_instances(obj): | |
""" | |
Reports the instances under an object in the Blender scene. | |
Including unrealized Geometry Node generated instances. | |
Args: | |
obj (bpy.types.Object): The object whose Geometry Node instances are to be reported. | |
Returns: | |
list[tuple[index: int, object_name: str, world_matrix: mathutils.Matrix]]: | |
A list of tuples containing the index, object name, and world matrix of each instance. | |
Notes: | |
This function iterates over the object instances in the Blender scene, filters for instances that are children of the given object, | |
and caches their index, object name, and world matrix. The cached data is then returned. | |
The function uses the evaluated dependency graph to access the object instances. | |
""" | |
# Slightly tricky issue with `depsgraph.object_instances` is: | |
# The StructRNA<DepsgraphObjectInstance> yielded appear to live only during the iteration of `object_instances`. | |
# So we cache fields and indexes, if we want additional fields later, we must re-iterate `object_instances` generator. | |
# e.g. | |
# | |
# iter_instances = (o for o in depsgraph.object_instances if o.is_instance and o.parent and o.parent.name == obj.name) | |
# ## See that we are succsessfully accessing fields of the instances during iteration | |
# instlist = [o for o in iter_instances] | |
# print( len( instlist ) ) | |
# >>> (Displays correct length) | |
# print(instlist[0] | |
# >>> <bpy_struct, DepsgraphObjectInstance invalid> | |
# print(instlist[0].object) | |
# >>> ReferenceError: StructRNA of type DepsgraphObjectInstance has been removed | |
# ## Even though we cached the results of the iterator all of the instance are invalid. | |
depsgraph = bpy.context.evaluated_depsgraph_get() | |
instance_data_cache = [] | |
for i, inst in enumerate(depsgraph.object_instances): | |
#filter for instances that are children of obj | |
if not( inst.is_instance and inst.parent and inst.parent.name == obj.name): | |
continue | |
instance_data_cache.append( | |
(i, | |
inst.object.name, | |
inst.matrix_world.copy() # WE MUST deep copy instance data! It will be disposed of outside of current loop. | |
)) | |
return instance_data_cache | |
if __name__ == "__main__": | |
# Get the current object - which we assume has the Geometry Nodes modifier that produces _un-realized_ instances. | |
activeobj = bpy.context.active_object | |
instance_data_cache = report_instances(activeobj) | |
print(instance_data_cache) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment