14
$\begingroup$

I have code to make a copy of my scene.

bpy.ops.scene.new(type='FULL_COPY')
cloneScene = bpy.context.scene
cloneScene.name = 'clone'

I wish to adapt it so that if the .blend contain several scenes, it will make a copy of the scene named 'Scene', i.e. The default scene (in my use case, it is reasonable to suppose this exists).

First thought is to do:

bpy.context.scene = bpy.data.scenes[ 'Scene' ]

Doc on bpy.context here http://www.blender.org/documentation/blender_python_api_2_57_release/bpy.context.html says 'Note that all context values are readonly, but may be modified through the data api or by running operators'

So I assume I cannot do this.

I found a related thread: http://blenderartists.org/forum/archive/index.php/t-201501.html

which recommends:

bpy.data.screens['Default'].scene = bpy.data.scenes['Scene']
bpy.context.screen.scene=bpy.data.scenes['Scene']

But I don't understand what's going on here, so I'm hesitant to blindly copy the code across. Does each sub-window have an associated screen, so my 3-D view could be viewing one scene whereas the animation view could be looking at another?

$\endgroup$

4 Answers 4

10
$\begingroup$

The older answers here are invalid as of 2.80. The Python API has changed, and screen objects no longer have scene as a property. In addition, the window object owns the active view layer.

Now, you can:
bpy.context.window.scene = someScene bpy.context.window.view_layer = someVL

API doc for window object: https://docs.blender.org/api/current/bpy.types.Window.html#bpy.types.Window

$\endgroup$
2
  • 1
    $\begingroup$ Can we have a link to the API docs please? $\endgroup$
    – brockmann
    Commented May 20, 2020 at 17:06
  • $\begingroup$ I've edited my answer to include this :) $\endgroup$ Commented May 20, 2020 at 20:03
9
$\begingroup$

Yes, that answer is valid.

You only need one of these 2 lines, they're just a different way to access the Screen data block. A screen datablock defines the layout of editors (which is why there is a selection of "screens" for e.g. UV editing, animation, etc. and you can fully customized that).

Every window (the system window blender runs in) has a screen property. Every screen in turn has a scene property which defines the active editable scene. Both of these properties are selectable at the top of the window by default. The most convenient way to set the screen.scene property is probably via the context:

bpy.context.screen.scene = some_scene

$\endgroup$
1
  • 2
    $\begingroup$ This is no longer valid as of 2.80. If I can figure out how to do it in the new Python API, I will post an answer. $\endgroup$ Commented May 20, 2020 at 16:54
2
$\begingroup$

From talking with lukas_t on IRC, here is what I have gleaned:

EDIT: I've combined sambler's answer into this also, thanks sambler!

Blender has a number of 'Window' objects. At least one, anyway (where all the action happens -- the main Blender window).

bpy.context.window. 

If you open up a modal dialog, like saving a file, that's probably another.

(Question: how to enumerate these? Just for an exercise in understanding...)

Each window object has an associated 'Screen' component that determines what scene to show, and which areas to display and how to lay them out. (3D View, Outliner View, etc are technically termed areas). You may notice that when you save and reload a .blend, Blender remembers the layout of all these areas.

So the main (default) window's screen can be accessed via any of:

bpy.context.window.screen
bpy.data.screens['Default']
bpy.context.screen

This last one is preferable, seeing as it is hard to imagine needing to use any other screen (can anyone give an example where you might need a different screen?)

Now you need to tell the main screen what scene it should be displaying.

mainScreen = bpy.context.screen
mainScreen.scene = bpy.data.scenes['Scene']

(Note that you can also do it via the pulldown on the infobar!)

Please upvote lukas_t + sambler's answers if this is useful to you, as I'm just compacting information from them.

$\endgroup$
1
$\begingroup$

Just to throw a spanner in the works. (I'm not 100% certain of the best answer)

Yes each screen defines a layout within the window and links to the scene that it uses.

But above that is a window, blender can open multiple windows (that is top level system provided windows). Each window has a screen which must be unique between windows. You can't have two blender windows using the same screen.

So I'm thinking the way to activate a scene would be

bpy.context.window.screen.scene = bpy.data.scenes['Scene']

So when a script is run, bpy.context.window would be the active window as defined by the system - the one that receives clicks and keystrokes.

Thing is it would seem we can't actually alter the screen in a non-active window so this may be irrelevant.

$\endgroup$

You must log in to answer this question.

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