diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-10-11 13:28:06 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-10-11 13:35:38 +0300 |
commit | a82c9e1e405c84b9ab8b5c1f31d7e135ab41c101 (patch) | |
tree | 1fc3cbbb26058def040218b66d3c31bfef3209af /release/scripts/modules/bpy_extras | |
parent | 0ceded7bc97852564c4d26951b41853e8289925e (diff) |
Fix T91169: bpy_extras.io_utils.create_derived_objects -> duplis error
This function now takes a depsgraph and a list of objects to avoid
inefficient O(n^2) iteration when extracting instances from all objects
in the scene. Returning an object -> instance map.
Note that keeping compatibility with the existing API wasn't practical
in this case since instances can no longer be generated from the scene
and it's objects.
Diffstat (limited to 'release/scripts/modules/bpy_extras')
-rw-r--r-- | release/scripts/modules/bpy_extras/io_utils.py | 50 |
1 files changed, 34 insertions, 16 deletions
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 9e3c5bb64e0..a3b39853b3a 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -25,7 +25,6 @@ __all__ = ( "axis_conversion", "axis_conversion_ensure", "create_derived_objects", - "free_derived_objects", "unpack_list", "unpack_face_list", "path_reference", @@ -348,21 +347,40 @@ def axis_conversion_ensure(operator, forward_attr, up_attr): return False -# return a tuple (free, object list), free is True if memory should be freed -# later with free_derived_objects() -def create_derived_objects(scene, ob): - if ob.parent and ob.parent.instance_type in {'VERTS', 'FACES'}: - return False, None - - if ob.instance_type != 'NONE': - ob.dupli_list_create(scene) - return True, [(dob.object, dob.matrix) for dob in ob.dupli_list] - else: - return False, [(ob, ob.matrix_world)] - - -def free_derived_objects(ob): - ob.dupli_list_clear() +def create_derived_objects(depsgraph, objects): + """ + This function takes a sequence of objects, returning their instances. + + :arg depsgraph: The evaluated depsgraph. + :type depsgraph: :class:`bpy.types.Depsgraph` + :arg objects: A sequencer of objects. + :type objects: sequence of :class:`bpy.types.Object` + :return: A dictionary where each key is an object from `objects`, + values are lists of (:class:`bpy.types.Object`, :class:`mathutils.Matrix`) tuples representing instances. + :rtype: dict + """ + result = {} + has_instancer = False + for ob in objects: + ob_parent = ob.parent + if ob_parent and ob_parent.instance_type in {'VERTS', 'FACES'}: + continue + result[ob] = [] if ob.is_instancer else [(ob, ob.matrix_world.copy())] + + if result: + for dup in depsgraph.object_instances: + dup_parent = dup.parent + if dup_parent is None: + continue + dup_parent_original = dup_parent.original + if not dup_parent_original.is_instancer: + # The instance has already been added (on assignment). + continue + instance_list = result.get(dup_parent_original) + if instance_list is None: + continue + instance_list.append((dup.instance_object.original, dup.matrix_world.copy())) + return result def unpack_list(list_of_tuples): |