Apply scale to linked duplicates

Is there a version of script from this yt video for Blender 2.80?

If there is none, could one of you coders translate it please?
Now when i try to use it i have

line 25, in <module>
AttributeError: bpy_prop_collection: attribute "active" not found

Here is a quick fix. Not tested, if it still does everything.

change log:

  • bpy.context.scene.objects.active = objects[0] removed
  • bpy.context.scene.objects.active = latticeparent replaced with bpy.context.view_layer.objects.active = latticeparent
  • .select = False replaced with .select_set(False)
  • .select = True replaced with .select_set(True)
  • var2 renamed to scale_length for better readabiltiy
  • linkedoblist = [] and linkedmeshlist = [] replaced by linkedoblist = {}
  • bpy.ops.object.transform_apply(scale=True) replaced by bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

Info for linked duplicates: Does only work properly, if all linked duplicates have the same scale value and are all selected!

#   Scale Master Flex

#   How to use this script:
#     1 - To use this script in your own files, just copy and paste this text into the text editor window
#     2 - Select your objects
#     3 - If desired change overall dimensions by using the "unit scale" value in the scene properties
#     4 - Hover over this script and press alt+p to run it

#   Tutorial on how the script works:
#     - https://youtu.be/X_dJYAMCGYw

#   What this script does:
#     -Resizes selected objects based on the "unit scale" value in the scene properties in order to correct their dimensions.
#     -Applies scale to selected objects
#     -Applies scale to linked duplicates while keeping them linked
# INFO: Does only work properly, if all linked duplicates have the same scale value and are all selected!
#     -Applies scale to lattice deformed objects without messing them up
#     -Adjusts modifier values when applying scale so they don't visually change

#   by Chris Plush | cgmasters.net

import bpy

scale_length = bpy.context.scene.unit_settings.scale_length
objects = bpy.context.selected_objects
linkedoblist = {}
latticelist = []
latticedata = []
latticechildren = []

# Runs through modifiers to change values based on object scaling and scene scaling


def modifierfun(var):
    if mod.name == 'Bevel':
        mod.width *= var
    elif mod.name == 'Solidify':
        mod.thickness *= var
    elif mod.name == 'Array':
        mod.constant_offset_displace[0] *= var
        mod.constant_offset_displace[1] *= var
        mod.constant_offset_displace[2] *= var
        mod.merge_threshold *= var
    elif mod.name == 'Boolean':
        mod.double_threshold *= var
    elif mod.name == 'Mirror':
        mod.merge_threshold *= var
    elif mod.name == 'Screw':
        mod.screw_offset *= var
    elif mod.name == 'Wireframe':
        mod.thickness *= var
    elif mod.name == 'Cast':
        mod.radius *= var
    elif mod.name == 'Hook':
        mod.falloff_radius *= var
    elif mod.name == 'Shrinkwrap':
        mod.offset *= var
    elif mod.name == 'Warp':
        mod.falloff_radius *= var
    elif mod.name == 'Wave':
        mod.start_position_x *= var
        mod.start_position_y *= var
        mod.falloff_radius *= var
        mod.height *= var
        mod.width *= var
        mod.narrowness *= var


# Append lattices to a list. Append their children to another list.
for ob in objects:
    if ob.type == 'LATTICE' and ob.children:
        latticelist.append(ob)
        latticedata.append(ob.data)
        latticechildren.append(ob.children[0])
    if ob.type not in ['EMPTY', 'SPEAKER'] and ob.data.users > 1 and ob.type != 'LATTICE':
        linkedoblist[ob] = ob.data

# First pass. Change modifier values to compensate for any object scaling. Make any linked lattice children single users.
for ob in objects:
    var1 = min(ob.scale, key=lambda x: abs(1 - x))
    if latticechildren.count(ob) > 0:
        bpy.ops.object.make_single_user(object=True, obdata=True)
    if ob.modifiers:
        for mod in ob.modifiers:
            modifierfun(var1)

# Clear parenting of lattice children but keep lattice modifier active
for ob in latticechildren:
    bpy.ops.object.parent_clear(type='CLEAR_KEEP_TRANSFORM')

# Resize all selected objects based on the scene's unit scale
bpy.ops.transform.resize(value=(1.0 * scale_length, 1.0 * scale_length, 1.0 * scale_length))

# Deselect objects we don't want to apply scaling to
for ob in objects:
    if ob.type in ['CAMERA', 'LAMP', 'EMPTY', 'SPEAKER', 'LATTICE']:
        ob.select_set(False)

# Make objects single users and apply scale
bpy.ops.object.make_single_user(object=True, obdata=True)
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

# Relink duplicate meshes
for ob, data in linkedoblist.items():
    ob.data = data

# Second modifier pass. Change modifier values to be proportional to scene's unit scale.
for ob in objects:
    if ob.modifiers:
        for mod in ob.modifiers:
            modifierfun(scale_length)

# Re-parent children to lattices
for child in latticechildren:
    bpy.ops.object.select_all(action='DESELECT')
    latticeparent = latticelist[latticechildren.index(child)]
    child.select_set(True)
    latticeparent.select_set(True)
    bpy.context.view_layer.objects.active = latticeparent
    bpy.ops.object.parent_set(type='LATTICE')

# Re-link duplicate lattices
for ob in latticelist:
    ob.data = latticedata[latticelist.index(ob)]

# Reset the scene's unit scale back to 1
bpy.context.scene.unit_settings.scale_length = 1

# Reselect original selection
for ob in objects:
    ob.select_set(True)

Big thanks for Your time. Now when i run the script from tex editor in terminal i have this:

**Traceback (most recent call last):
  File "H:\Documents\Blender\Jepp\jepp_225.blend\Text", line 90, in <module>
  File "H:\Blender\Blender2.81\2.81\scripts\modules\bpy\ops.py", line 201, in __call__
    ret = op_call(self.idname_py(), None, kw)
RuntimeError: Operator bpy.ops.object.parent_clear.poll() failed, context is incorrect
Error: Python script failed, check the message in the system console**

Looks like it isn’t that easy. :slight_smile:

Under what circumstances does this occur?
I couldn’t reproduce the error, but found an other one.

I use this scene from the YT video. But with Your version of the script in text editor.

scale_master_flex.blend (433.8 KB)

When i select all objects and run script i have:

Traceback (most recent call last):
  File "F:\---[_download_]---\scale_master_flex.blend\scale_master_flex.py", line 120, in <module>
AttributeError: bpy_struct: Context property "active_object" is read-only
Error: Python script failed, check the message in the system console

and all link duplicated wheels (objects) are in the same place as orginal wheel mesh.

That’s the error I found. I already fixed it in the post above. (forgot to mention)

I can look up the liked duplicates error the next days.

Yes now the error in terminal is gone but still all the link duplicated objects are in the same plac as orginal mesh after run the script. Thank You very much!

I found the errors with linked duplicates. I updated the entry in the post above: https://blenderartists.org/t/apply-scale-to-linked-duplicates/1182294/2

It works, THANK YOU!

The only problems I had were with the lattices, but fixed them manually very easy afterwards