1
$\begingroup$

am trying to copy the cache sequence modifiers from one mesh to another. The character with shaders and the character with the alembic sequence modifiers share parts of their names, example "BODY_GEO" and "AX_EP998_PUN02_ANIM_V010_ESC05_PL018_C01_ALUX_00_BODY_GEO". my goal is for this python script to select everything with a 'for' that doesnt contain "AX_" in the name, that select all meshes from the shader character, and then i select the matching pair with a nested 'for' like this:

bpy.ops.object.select_all(action='DESELECT')
for sel in bpy.context.visible_objects:
    if sel.type == 'MESH' and ('AX_' not in sel.name):
        for ob in bpy.context.visible_objects:
            if ob.type == 'MESH' and ('_'+sel.name in ob.name):
                print (sel, ob)
                sel.select_set(1)
                ob.select_set(1)
                bpy.ops.object.make_links_data(type='MODIFIERS')
            else:
                bpy.ops.object.select_all(action='DESELECT')

But that code seems to apply the same modifier to every mesh in the outliner.

if I do this:

bpy.data.objects['BODY_GEO'].select_set(1)
bpy.data.objects['AX_EP998_PUN02_ANIM_V010_ESC05_PL018_C01_ALUX_00_BODY_GEO'].select_set(1)
bpy.ops.object.make_links_data(type='MODIFIERS')

It works perfect, but the name of the mesh on the alembic will change with every shoot so it wont work that easy.

What em i doing wrong, i now that i may have to use a break to stop the second for once finds the pair but i get errors when i try.

Im very new to blender and i know that selecting things is terrible difficult, please help me with this.

$\endgroup$

2 Answers 2

1
$\begingroup$

Override the context

IMO At issue with code in question is not setting the active object, ie the one you want to copy modifiers from, to the others selected.

To set object ob as active

context.view_layer.objects.active = ob

which sets the active object, aka context.object and context.active_object to ob, but until selected it is not context.selected_objects[0] Wrote this re using "first selected" for active object. It causes confusion that relates to your issue here, you're only selecting, not "activating"

Anyhow, forget that, recommend overriding the context. Build a dictionary of the context members needed and pass it to the operator. No messy selecting and setting active object.

Simple test script. It happens I am working on a tree that has a number of modifiers. I will make the tree object active. Add a cube to scene and override it as selected object.

After some testing have determined that the operator needs to override, screen, scene, object and selected_editable_objects

To test replace "Tree" with name of object with modifiers (source) and "Cube" with the name of target mesh to copy to.

enter image description here Modifiers copied from tree to cube with neither selected and empty active

import bpy

context = bpy.context
scene = context.scene
cube = scene.objects.get("Cube")
tree = scene.objects.get("Tree")

override = {}
override["screen"] = context.screen
override["scene"] = context.scene
override["object"] = tree
override["selected_editable_objects"] = [tree, cube]

bpy.ops.object.make_links_data(override, type='MODIFIERS')

can see how this could be made into a little helper method, simply pass it context and the target and source object.

$\endgroup$
1
  • $\begingroup$ Thanks, am going to check this out right now. $\endgroup$ Jun 4, 2020 at 15:34
0
$\begingroup$

Thanks, that did it. the final code looks like this:

bpy.ops.object.select_all(action='DESELECT')
for sel in bpy.context.visible_objects:
    if sel.type == 'MESH' and ('AX_' not in sel.name):
        for ob in bpy.context.visible_objects:
            if ob.type == 'MESH' and ('_'+sel.name in ob.name):
                print (sel, ob)
                sel.select_set(1)
                ob.select_set(1)
                context = bpy.context
                scene = context.scene
                cube = sel
                tree = ob
                print (cube , tree)
                override = {}
                override["screen"] = context.screen
                override["scene"] = context.scene
                override["object"] = tree
                override["selected_editable_objects"] = [tree, cube]
                bpy.ops.object.make_links_data(override, type='MODIFIERS')

It instantly copied all modifiers from the alembic character to the shading character, just by adding your suggested code. Yes before is was copying the same modifier from the active to the rest.

Cheers, thank you very much.

Ps, if anyone is interested in using this code, it will work if the objects you want to copy modifiers share some letters or phrases. Just try to filter the receiving objects as "sel" and the donating objects as "ob". (it was named like that because i first selected the receiving but selecting didn't work) and it will go search your scene for matching names and copying the modifiers.

$\endgroup$
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .