2
$\begingroup$

I currently am writing python operator whith the task of appending the current scene into a new file and then linking it back into the original file. There is one problem: When loading a new file the bpy.context changes and I do not quite know how to reload it. This leads to the error "context is incorrect" when trying to append the original scene into the new file. Here is how my code looks so far:

class BPC_main_Outsource(bpy.types.Operator):
    bl_idname = "scene.outsource"
    bl_label = "Outsource"
    def execute(self, context):        
        compScene = bpy.context.scene #get scene
        bpy.ops.wm.save_mainfile() #save current file
        blendFile  = bpy.data.filepath #get path of current file
        apFilename = compScene.name #determine scene's name
        bpy.ops.wm.read_homefile() #load a new file
        oldScene = bpy.context.scene #get current scene in new file
        blendFile = blendFile.replace("\\", r"/")
        apPath = "//" + bpy.path.basename(blendFile) + "/Scene/" + apFilename #build append path
        apDirectory = blendFile + "/Scene/" #build append directory
        bpy.ops.wm.append(filepath=apPath, directory=apDirectory, filename=apFilename) #append scene from main file
        bpy.ops.scene.delete() #delete old scene in new file 
        #TODO: save file, open original file, link back
        return {"FINISHED"}

Any help on how to fix this would be greatly appreciated. Thanks in advance.

$\endgroup$
  • 1
    $\begingroup$ How about, save the file, remove all scenes but the context scene, save the file to the new "scene" location, then reopen original. $\endgroup$ – batFINGER Dec 13 '15 at 13:56
  • $\begingroup$ Could be problematic because have to import the scene back into the original file (and there I also have to open a file & link/append a scene into it). $\endgroup$ – Paul B. Dec 13 '15 at 14:23
  • $\begingroup$ Does this help: blender.stackexchange.com/questions/6101/… $\endgroup$ – p2or Dec 13 '15 at 16:04
  • $\begingroup$ Thanks. I had a look at it before. No, it does not really help, it just covers how to fix trying to execute a Operator in an invalid area. In my case the problem is that the whole bpy.context is not accessible through the script (at least it seems like it). $\endgroup$ – Paul B. Dec 13 '15 at 16:11
  • $\begingroup$ Yes, I did. Well that is what happens when not double checking after trying to shorten a code segment to put it in a question... Thanks, edited it. $\endgroup$ – Paul B. Dec 13 '15 at 17:00
2
$\begingroup$

Script saves the current file, removes all scenes but the context scene and saves that to a file in the current blends directory with name "SCENE_<context.scene.name>" eg SCENE_Scene.blend for the scene.name of "Scene".

After which it reopens the original file, links to the scene in the created file, and deletes the original.

import bpy

class BPC_main_Outsource(bpy.types.Operator):
    bl_idname = "scene.outsource"
    bl_label = "Outsource"

    @classmethod
    def poll(cls, context):
        return bpy.data.filepath != "" and context.scene.library is None

    def execute(self, context):
        from os import path

        compScene = context.scene #get scene
        blendFile  = bpy.data.filepath #get path of current file
        clean_name = bpy.path.clean_name(bpy.path.display_name(blendFile))
        apFilename = compScene.name 
        screen_name = context.screen.name
        scene_file_path = blendFile.replace(clean_name, "SCENE_%s" % apFilename)

        if path.isfile(scene_file_path):
            print("Scene file %s already exists" % scene_file_path)
            return {'CANCELLED'}

        bpy.ops.wm.save_mainfile()      

        # remove all but context scene
        for scene in bpy.data.scenes:
            if scene == compScene:
                continue
            bpy.data.scenes.remove(scene)


        # save with only compScene
        bpy.ops.wm.save_as_mainfile(filepath=scene_file_path)        
        # reopen original,link saved scene
        bpy.ops.wm.open_mainfile(filepath=blendFile)  
        scene = bpy.data.scenes.get(apFilename)     
        # link the scene back
        with bpy.data.libraries.load(scene_file_path, link=True, relative=True) as (data_from, data_to):
            data_to.scenes = [apFilename]
        # rename the original scene, remove crashes my blender    
        screen = bpy.data.screens.get(screen_name) 
        scn = screen.scene
        if scene and screen:

            scene.name = "%s_ORIGINAL" % scene.name
            scn = bpy.data.scenes.get(apFilename)
            #c = context.copy()
            print("CONTEXT", bpy.context.window, context.window)
            c = {"scene": scene,
                 "screen": screen,
                 "area": screen.areas[0],
                 "region": screen.areas[0].regions[0],
                 "edit_object": None,
                 "blend_data": bpy.data,
                 "window": bpy.data.window_managers[0].windows[0]
                 }
            bpy.ops.scene.delete(c)
            screen.scene = scn

        return {"FINISHED"}

bpy.utils.register_class(BPC_main_Outsource)

# test run
if bpy.ops.scene.outsource.poll():
    bpy.ops.scene.outsource()
else:
    print("Failed POLL is scene already linked?")
$\endgroup$
  • $\begingroup$ Yes, I did. I saw your script was completely fine about two seconds after I wrote the comment. My apologies. Your answer was much appreciated. $\endgroup$ – Paul B. Dec 15 '15 at 18:19
  • $\begingroup$ Any idea why trying to delete the original scene results in a crash? $\endgroup$ – Paul B. Dec 15 '15 at 18:30
  • $\begingroup$ My guess is context is lost while loading a new file, during the restricted context time , a print of context.scene, context.window all show None (using bpy.context also). To get around this creating a datapath from the data of the file before reload and then getting them from the data after reload appears to be the way to go. I've posted code that "works" but would suggest putting a lot of checks and balances in it and even a try except (which I try to avoid) after the file save, to reload if something goes wrong. Wondering if re-importing bpy as bpy_ may be useful here. $\endgroup$ – batFINGER Dec 16 '15 at 13:22
  • $\begingroup$ importlib.reload(bpy) may be woth a try but I do not really think it is going to help a lot... The context problem was sort of what my question was (and still is) all about. But thanks for pointing out the datapath method in your initial answer that one really was extremely helpful! $\endgroup$ – Paul B. Dec 16 '15 at 16:06
  • $\begingroup$ Did you try the new code?. Forgot to mention I updated it. It's working for me on most occasions. $\endgroup$ – batFINGER Dec 16 '15 at 16:15

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.