This should come pretty close. You need to save this file as save_current_scene.py in your Blender scripts folder otherwise it won’t work. Also read the bpydoc This script could be a base for:
- exporting any scene, not just the active one
- splitting a blend drawing into separate scene drawings
- exporting just some (selected) objects, similar to wblock in AutoCAD. Is there any interest in that as well?
#!BPY
""" Registration info for Blender menus:
Name: 'Save Current Scene (.blend)...'
Blender: 248
Group: 'Export'
Tooltip: 'Save only current scene'
"""
# --------------------------------------------------------------------------
# ***** BEGIN GPL LICENSE BLOCK *****
#
# Copyright (C) 2009 Stani (SPE Python IDE)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ***** END GPL LICENCE BLOCK *****
# --------------------------------------------------------------------------
__author__ = "Stani (SPE Python IDE)"
__url__ = ["pythonide.stani.be", "blenderartists.org"]
__version__ = "0.2"
__bpydoc__ = """\
The filename of this script should be the value of SCRIPT_NAME in the
folder ~/.blender/scripts
The script tries to be as prudent as possible.
Probably some cleaning up can be skipped to gain more speed.
Known issues:
- Blender might display a Error Totblock because of action.removeChannel
(see clear_channels function) This is probably a memory leak, but
I don't know why.
- Blender will show several "Unable to open" warnings. It is safe to
ignore these messages.
"""
import os
import sys
import bpy
import Blender
from Blender import Armature, Curve, Draw, Ipo, Types, Window
SCRIPT_NAME = 'save_current_scene.py'
ACTIVE_SCENE = bpy.data.scenes.active
FILENAME_CURRENT = Blender.Get('filename')
SCRIPT = os.path.expanduser(os.path.join('~','.blender',
'scripts',SCRIPT_NAME))
def write(x):
"""Alternative for the print function. (python 3 compatible)"""
sys.stdout.write(x)
sys.stdout.flush()
def get_data(ob):
"""Returns data of an object and in case of a mesh,
returns Mesh instead of NMesh."""
data = ob.data
if type(data) is Types.NMeshType:
data = bpy.data.meshes[ob.data.name]
return data
def clear_action(x):
"""Clears an object from action, action strips and constraints."""
for strip in list(x.actionStrips):
x.actionStrips.remove(strip)
for constraint in list(x.constraints):
x.constraints.remove(constraint)
action = x.action
if action:
clear_channels(action)
x.action = None
def clear_channels(action):
"""Clears an action from its channels."""
for channel, ipo in action.getAllChannelIpos().items():
if ipo:
clear_curves(ipo)
# FIXME: this causes an Error Totblock
for channel in action.getChannelNames():
action.removeChannel(channel)
def clear_ipo(x):
"""Clears an object from its ipo."""
ipo = x.getIpo()
if ipo:
clear_curves(ipo)
x.ipo = None
def clear_curves(ipo):
"""Clear the curves from an Ipo."""
for curve in ipo.curveConsts.keys():
try:
ipo[getattr(Ipo,curve)] = None
except (KeyError,ValueError):
pass
def remove_texts():
"""Remove all unnecessary texts."""
texts = bpy.data.texts
for text in texts:
# keep pynodes, which have more than two users
if text.users < 2:
texts.unlink(text)
def save_scene(filename, scene=ACTIVE_SCENE):
"""Saves a scene only."""
write('
Exporting scene "%s" as "%s", please wait...
' %\
(scene.name,filename))
# save current file first
Blender.Save(filename,1)
Blender.Save(FILENAME_CURRENT,1)
# start a new Blender session to extract the scene to not
# interfere with the current one
command = '%s -b %s -P %s extract %s' %\
(Blender.sys.progname,filename,SCRIPT,scene.name)
os.system(command)
def extract_scene(filename, scene=ACTIVE_SCENE, texts=True):
"""Remove all content which does not belong to the scene."""
# objects
scene_objects = frozenset(scene.objects)
scenes = bpy.data.scenes
write('Clean up actions...
')
scene_actions = [ob.action for ob in scene_objects if ob.action]
for action in Armature.NLA.GetActions().values():
if not(action in scene_actions):
clear_channels(action)
write('Retrieve scene materials...
')
scene_materials = frozenset()
for object in scene_objects:
scene_materials = scene_materials.union(
frozenset(object.getMaterials()))
data = object.getData()
if hasattr(data,'materials'):
scene_materials = scene_materials.union(
frozenset(data.materials))
write('Clean up non scene materials...
')
for material in bpy.data.materials:
if not (material in scene_materials):
material.freeNodes()
clear_ipo(material)
material.clearScriptLinks()
for index, texture in enumerate(material.getTextures()):
if texture:
material.clearTexture(index)
write('Clean up datablocks...
')
scene_data = [get_data(ob) for ob in scene.objects] +\
[scene.world]
scene_text3d = [t for t in scene_data
if type(t) is Types.Text3dType]
for data_type in ['meshes','metaballs','lamps','worlds']:
for data in getattr(bpy.data,data_type):
if not(data in scene_data):
if hasattr(data, 'materials'):
data.materials = []
if hasattr(data, 'clearIpo'):
clear_ipo(data)
if hasattr(data,'clearScriptLinks'):
data.clearScriptLinks()
write('Clean up curves (incl. text3d)...
')
# Text3d needs to be treated as curve, otherwise its materials
# can't be cleared.
scene_curves = [c for c in scene_data
if type(c) is Types.CurveType] + \
[Curve.Get(t.name) for t in scene_text3d]
for curve in Curve.Get():
if not(curve in scene_curves):
curve.materials = []
write('Remove objects...
')
for s in scenes:
for o in s.objects:
if not(o in scene_objects):
clear_ipo(o)
o.clearScriptLinks()
o.clearTrack()
o.removeAllProperties()
o.clrParent()
clear_action(o)
s.objects.unlink(o)
write('Remove other scenes...
')
for s in scenes:
if s != scene:
s.update(1)
scenes.unlink(s)
write('Save only current scene...
')
save(filename,n=4)
def save(filename, n):
"""Iterate save/load sessions to get rid of unreferenced data."""
write('Remove texts...
')
if n == 1:
remove_texts()
Blender.Save(filename,1)
n -= 1
if n <= 0:
return
command = '%s -b %s -P %s save %d' %\
(Blender.sys.progname, filename, SCRIPT, n)
os.system(command)
if __name__=='__main__':
if not FILENAME_CURRENT:
menu = Draw.PupMenu('Please save the file first%t|OK')
elif 'extract' in sys.argv:
filename = sys.argv[2]
scene = bpy.data.scenes[sys.argv[6]]
extract_scene(filename, scene)
elif 'save' in sys.argv:
filename = sys.argv[2]
n = int(sys.argv[6])
save(filename, n)
else:
filename = Blender.sys.makename(ext='_%s.blend' %\
(ACTIVE_SCENE.name))
Window.FileSelector(
save_scene,
'Save current scene as',
filename)