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$ – Mohamad Zeina Jun 1 '20 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 Jul 16 '20 at 6:14
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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.