Skip to content

Instantly share code, notes, and snippets.

@zvodd
Last active September 8, 2024 19:35
Show Gist options
  • Save zvodd/f65116412a3eaaf292fead54b1b952cd to your computer and use it in GitHub Desktop.
Save zvodd/f65116412a3eaaf292fead54b1b952cd to your computer and use it in GitHub Desktop.
Blender 4 instance enumeration - Including unrealized Geometry Node generated instances.
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