I'm building a model completely in python. This means that I start with an empty scene, and all I want to do is run a python command that creates all meshes and objects. I'm building this python script in vi, just because blender is amazing 3D software, but lousy at making a decent text editor.
Off topic: The main reason for building my model this way, is that I want to have complete control over what I build, complete reproducibility, and I get to store my model in github, having proper version control and clear change sets. I would certainly be interested in hearing some off-topic reactions on how I could do this better/differently.
While developing this script, I constantly want to reload, from scratch, change a line in my script, reload, etc. I was wondering what the best way to achieve this is. My requirements:
- It has to be simple, a couple of keystrokes, since I'm doing this multiple times per minute.
- I don't want to restart blender every time, just because it takes a couple of seconds to start blender, and because the blender window doesn't appear in the right spot by default (this latter is possibly fixable).
- Preferably I start from a new state (as in: File -> new) or in a known saved state (File --> open). Between reruns I do things in the interface and I may accidentally alter some property without knowing it. Ideally this would be reset on the next run.
- Preferably the execution is triggered by the Python Console, so that errors appear there (and not in the bash console used to start blender).
Things I've tried so far:
Loop over all objects and delete them
I can manually try to delete all objects (using the method described here): http://blenderscripting.blogspot.nl/2012/03/deleting-objects-from-scene.html This doesn't quite work (it crashes if there are hidden objects), but this is probably solvable. However it doesn't satisfy my 3rd requirement. It does allow my to make 1 oneliner that loops over all objects, delete them, and then runs my script again.
bpy.ops.wm.read_homefile() to get to the new state
Using this command I can get to the new state, however this also resets the python console, meaning that any subsequent command gets ignored and I can't up-arrow anymore to get it back.
bpy.ops.wm.open_mainfile() to get to a known saved state
This suffers from the same problem as the previous
bpy.ops.wm.read_homefile, however it allows me to save some history in the python console, so I can up-arrow to it. It works, sort of, but not ideal.
In all of the above settings, I used
exec(compile(open(filename).read(), filename, "exec"))
to execute the script.
My latest plan is to use modules (however I think it would work just as well with the above
exec command), and the undo history. Calling operators from a script doesn't add them to the undo history, so if after the running of the script I push onto the undo stack, I can then cmd-Z my way to the previous state. I could probably. When I start, I run once (single is my module name):
import sys; import importlib; sys.path.append("/path/with/my/module"); import single;
Now I use the oneliner
importlib.reload(single); single.build_single((20,25,0)); bpy.ops.ed.undo_push()
whenever I want to see how my program runs. When I'm ready to do a new run, I cmd-Z until I'm back at the beginning (most of the time once, sometimes I did some manual operations and need to press it more often).
Somehow I feel however that there must be a better way to do this, to reset the scene to some saved or new state, while the python script keeps running....
I still haven't found a good solution to this problem. However since all I really needed was to make relatively simple 3D objects for printing on my 3D printer and sending of to Shapeways, I found OpenSCAD more suitable, and 100% text based, which allows me easy checkins into git and changesets. Don't get me wrong, I think Blender is the tool for amazing 3D rendered images and animations, for my use however it was overkill.