I thought a little about what @batFINGER mentioned in the comments, and it got me thinking:
class DuplicateScene2():
_file_stack = []
def __init__(self):
if not bpy.data.is_saved:
raise ValueError("Save .blend file before exporting")
# Push filepath onto stack
if len(DuplicateScene2._file_stack) == 0:
DuplicateScene2._file_stack.append(bpy.data.filepath)
bpy.ops.wm.save_mainfile(filepath = bpy.data.filepath,
check_existing = False)
else:
filepath, fileext = os.path.splitext(bpy.data.filepath)
DuplicateScene2._file_stack.append("%s.copy.%02i.blend" % (filepath, DuplicateScene2._unique_id))
DuplicateScene2._unique_id += 1
# Save file
filepath = DuplicateScene2._file_stack[-1]
bpy.ops.wm.save_as_mainfile(filepath = filepath,
check_existing = False,
copy = True)
def __enter__(self):
# Return new context override
context = bpy.context
window = context.window_manager.windows[0]
screen = window.screen
scene = context.scene
area_view3d = [area for area in screen.areas if area.type == 'VIEW_3D'][0]
space_view3d = [space for space in area_view3d.spaces if space.type == 'VIEW_3D'][0]
return {'window': window,
'screen': screen,
'area': area_view3d,
'space': space_view3d,
'context': context,
'scene': scene}
def __exit__(self, type, value, traceback):
filepath = DuplicateScene2._file_stack.pop()
bpy.ops.wm.open_mainfile(filepath = filepath,
load_ui = True,
use_scripts = False)
if len(DuplicateScene2._file_stack) > 0:
os.remove(filepath)
Using it like so:
try:
with DuplicateScene2 as override_context:
...
except ValueError as e:
self.report({'ERROR'}, "%s" % (e))
return {'CANCELLED'}
With this, checking if the file has been saved or not will warn the user about needing to save before exporting. Any exceptions thrown will still allow the file to be reverted.
If there are "cleaner" methods, or suggestions, please do post!
Edit: This doesn't work nested, which is what I realized that I also need.
Edit: Added supported with nesting.