7
$\begingroup$

I have a Blender file wih many scenes and I want to copy the node tree of one of them to the other scenes. From Blender interface it is a very simple task, in python I have tried using

bpy.ops.node.clipboard_copy() and bpy.ops.node.clipboard_paste()

with no success.

Is there any other method I can use?

Here is my code:

import sys
import bpy

def deleteNodeTree(scene, override):
    scene.node_tree.nodes.clear()


def copyNodeTree(scene, override):
    bpy.ops.node.select_all(override, action = 'DESELECT')
    bpy.ops.node.select_all(override, action = 'SELECT')    
    bpy.ops.node.clipboard_copy(override)

def pasteNodeTree(scene, override):
    bpy.ops.node.select_all(override, action = 'DESELECT')
    bpy.ops.node.select_all(override, action = 'SELECT')
    bpy.ops.node.clipboard_paste(override)

def getOverride(type, regionType):
    Override = False
    for window in bpy.context.window_manager.windows:
        for area in window.screen.areas:
            if(area.type == type):
                Override = {"window": window, "screen": window.screen, "area": area, "scene" : bpy.context.scene}
                break
    if(not Override):
        bpy.context.window_manager.windows[0].screen.areas[0].type = type
        Override = {"window": bpy.context.window_manager.windows[0], "screen": bpy.context.window_manager.windows[0].screen, "area": bpy.context.window_manager.windows[0].screen.areas[0], "scene" : bpy.context.scene, "region" : bpy.context.region}
    if(regionType):
        for region in Override["area"].regions:
            if(region.type == regionType):
            Override["region"] = region
    return Override

if len(sys.argv) < 6:
    raise Exception("Usage:  blender -b blend_file --python script.py 
target_scene_name")

blend_file        = sys.argv[2]
target_scene_name = sys.argv[5]

bpy.ops.wm.open_mainfile( filepath = blend_file )

#Copia su tutte le scene le impostazioni dei nodi di output prese dalla scena selezionata (target_scene_name)

bpy.context.screen.scene = bpy.data.scenes[target_scene_name]
override = getOverride('NODE_EDITOR', False)
copyNodeTree( bpy.context.screen.scene, override)

for scene in bpy.data.scenes:
    if scene.name != target_scene_name:     
        bpy.context.screen.scene = bpy.data.scenes[scene.name]
        scene = bpy.context.screen.scene
        print("Deleting output options from scene: " + 
bpy.context.screen.scene.name)
        deleteNodeTree(scene, override)
        print("Pasting output options to scene: " + 
bpy.context.screen.scene.name)
        pasteNodeTree(scene, override)

bpy.ops.wm.save_as_mainfile(filepath = blend_file, compress=False)
$\endgroup$
2
  • $\begingroup$ Did you ever find a solution to this? Trying to do something very similar $\endgroup$ Commented Jun 1, 2020 at 6:03
  • $\begingroup$ I don't have scripting knowledge, so sorry if it is too naive, but since you can we or place nodetree via node group, wouldn't be this a way? $\endgroup$
    – vklidu
    Commented Jul 16, 2020 at 6:14

1 Answer 1

1
$\begingroup$

I have managed to do it via the bpy.ops.wm.redraw_timer(type='DRAW_WIN', iterations=1) hack.

enter image description here

import bpy

class TEST_OT_poll():
    @classmethod
    def poll(cls, context):
        if context.space_data.type == 'NODE_EDITOR' and context.space_data.tree_type == 'CompositorNodeTree':
            return True
        else:
            return False

class COPY_SCENE_NODE_TREE_OT_copy_to_others(bpy.types.Operator, TEST_OT_poll):
    bl_idname = "node.csnt_test_temp"
    bl_label = "TEMPT TEST"
    bl_description = ""
    bl_options = {'REGISTER', 'UNDO'}
    

    def execute(self, context):
        
        initial_scene = bpy.context.scene
        
        scenes = bpy.data.scenes.values()
        scenes.remove(initial_scene)
        
        bpy.ops.node.select_all(action='SELECT')
        bpy.ops.node.clipboard_copy()
        
        for scene in scenes:
            print(scene)
            bpy.context.window.scene = scene
            bpy.ops.wm.redraw_timer(type='DRAW_WIN', iterations=1)
            bpy.context.scene.node_tree.nodes.clear()
            bpy.ops.node.clipboard_paste()
            bpy.ops.node.select_all(action='DESELECT')
        
        bpy.context.window.scene = initial_scene
        bpy.ops.wm.redraw_timer(type='DRAW_WIN', iterations=1)
        bpy.ops.node.select_all(action='DESELECT')
        
        return {'FINISHED'}
  
    
    
class COPY_SCENE_NODE_TREE_PT_panel(bpy.types.Panel):
    bl_idname = "COPY_SCENE_NODE_PT_panel"
    bl_label = "Copy scene node tree"
    bl_space_type = 'NODE_EDITOR'
    bl_region_type = "UI"
    bl_category = "Tool"

    @classmethod
    def poll(cls, context):
        if context.space_data.tree_type == 'CompositorNodeTree':
            return True
        else:
            return False

    def draw(self, context):
        
        layout = self.layout
        column = layout.column()
        column.operator("node.csnt_test_temp", text = "Copy And Paste")
    

classes = (
    COPY_SCENE_NODE_TREE_PT_panel,
    COPY_SCENE_NODE_TREE_OT_copy_to_others,
)

def register():
    for c in classes:
        bpy.utils.register_class(c)

def unregister():
    for c in classes:
        bpy.utils.unregister_class(c)
        
        
if __name__ == "__main__":
    register()
$\endgroup$

You must log in to answer this question.

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