Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWillian Padovani Germano <wpgermano@gmail.com>2005-04-16 09:25:42 +0400
committerWillian Padovani Germano <wpgermano@gmail.com>2005-04-16 09:25:42 +0400
commitd65fc84a6815673b9c4085bd4b3e4830167f59fb (patch)
treed8b083c5306ea01492f37fb92828fe4a0b42e1b4 /source/blender/python
parent8b664b924b40aeddc8bc9ac72451a0702af75afe (diff)
Note: this commit includes new functionality to save and restore scripts configure options. This is ongoing work, scripts still have to be updated to use this feature and more tests are needed, though many have been performed. The new Scripts Config Editor script is the main part of this. If anyone wants to check it, only the AC3D importer and exporter have already been updated to use it: simply open them (you can then cancel with ESC) to have the data created, then try the config editor.
Scripts: - Thanks Jean-Michel Soler (jms) for updated versions of dispaint, fixfromarmature and unweld (also renamed to remove version part). - Thanks Bart for the upgraded VRML exporter (great doc webpage!). It is available as VRML 97 and the original VRML 2 is for now still there, to help users testing the new version. For the next release the old one should be removed, of course. - New script: Scripts Config Editor (Scripts win -> Scripts -> System). Scripts with config options (simple data that is to be set according to user needs or preferences) can use this facility instead of providing a gui and writing config files to disk themselves. - Added new menu: System, available in the Scripts win. - Updated sys_info.py, help_browse.py and the AC3D importer and exporter. - Removed use of the Scrollbar and added arrow keys and mouse wheel support instead in Daniel Dunbar's old doc_browser.py. The scrollbar events handling doesn't exist, Ton suggested removing the scrollbar from the API months ago. For now its ref doc is gone and no bundled script uses it, until we get time to implement it properly. - Added module BPyRegistry.py with functions to handle reading / writing config files automatically to the scripts/bpydata/config dir. - Removing dir release/bpydata and its contents (moved earlier to release/scripts/bpydata/) - Bug #2379: made small changes to bevel_center's ui to fix a problem reported by Alexander Ewering (intrr): http://projects.blender.org/tracker/?func=detail&atid=125&aid=2379&group_id=9 BPython: - Thanks Campbell Barton for new functionality: Blender.Get() now can also return all the paths from the user prefs -> file paths win and there is a new function: Blender.sys.expandpath() to transform Blender paths (those starting with '//' and ending with '#') to absolute paths. - Added function Blender.ShowHelp(), to open the Scripts Help Browser with a given help page -- just a time saver for scripts. - Improved function Blender.Run() to also work with gui and file select scripts. - Found a (new?) crash related to NMesh.PutRaw when creating a new object while in edit mode. Leaving / entering edit mode fixes the problem, so a check for obj created, edit mode and leaving / re-entering it were added to the code for now (gdb didn't help much, no backtrace) - doc updates, including splitting intro page in two, with bpython related stuff (registering / documenting / configuring scripts and command line mode (thanks Chris Want for "use system variables to pass parameters to scripts" idea). - Registry: functions have been updated to support writing to / reading from disk, for the config editor -- only simple config data supported, for large amounts coders should write to a file themselves. This is done with a new parameter: Registry.GetKey(keyname, True) will also search for the key on the config dir, if not already loaded; equiv. for Registry.SetKey(keyname, dict, True). Data is only written to / read from disk when needed and only scripts already used (assuming they support this functionality) will have config data saved.
Diffstat (limited to 'source/blender/python')
-rw-r--r--source/blender/python/BPY_menus.c5
-rw-r--r--source/blender/python/BPY_menus.h3
-rw-r--r--source/blender/python/api2_2x/Blender.c188
-rw-r--r--source/blender/python/api2_2x/EXPP_interface.c31
-rw-r--r--source/blender/python/api2_2x/NMesh.c7
-rw-r--r--source/blender/python/api2_2x/Registry.c85
-rw-r--r--source/blender/python/api2_2x/Sys.c31
-rw-r--r--source/blender/python/api2_2x/doc/API_intro.py195
-rw-r--r--source/blender/python/api2_2x/doc/API_related.py377
-rw-r--r--source/blender/python/api2_2x/doc/Blender.py52
-rw-r--r--source/blender/python/api2_2x/doc/Draw.py78
-rw-r--r--source/blender/python/api2_2x/doc/Object.py44
-rw-r--r--source/blender/python/api2_2x/doc/Registry.py49
-rw-r--r--source/blender/python/api2_2x/doc/Render.py4
-rw-r--r--source/blender/python/api2_2x/doc/Sys.py21
15 files changed, 882 insertions, 288 deletions
diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
index 40dd8543762..e71d06b4141 100644
--- a/source/blender/python/BPY_menus.c
+++ b/source/blender/python/BPY_menus.c
@@ -94,6 +94,8 @@ static int bpymenu_group_atoi( char *str )
return PYMENU_HELPSYSTEM;
else if( !strcmp( str, "Render" ) )
return PYMENU_RENDER;
+ else if( !strcmp( str, "System" ) )
+ return PYMENU_SYSTEM;
else if( !strcmp( str, "Object" ) )
return PYMENU_OBJECT;
else if( !strcmp( str, "Mesh" ) )
@@ -141,6 +143,9 @@ char *BPyMenu_group_itoa( short menugroup )
case PYMENU_RENDER:
return "Render";
break;
+ case PYMENU_SYSTEM:
+ return "System";
+ break;
case PYMENU_OBJECT:
return "Object";
break;
diff --git a/source/blender/python/BPY_menus.h b/source/blender/python/BPY_menus.h
index 52ab5e85e4a..8ef94b1ce79 100644
--- a/source/blender/python/BPY_menus.h
+++ b/source/blender/python/BPY_menus.h
@@ -25,7 +25,7 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Willian P. Germano
+ * Contributor(s): Willian P. Germano, Matt Ebb
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -87,6 +87,7 @@ typedef enum {
PYMENU_MISC,
PYMENU_OBJECT,
PYMENU_RENDER,/* exporters to external renderers */
+ PYMENU_SYSTEM,
PYMENU_THEMES,
PYMENU_UV,/* UV editing tools, to go in UV/Image editor space, 'UV' menu */
PYMENU_WIZARDS,/* complex 'app' scripts */
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index 988e9ac67bd..e2f68a9a6f9 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -24,7 +24,8 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Michel Selten, Willian P. Germano, Joseph Gilbert
+ * Contributor(s): Michel Selten, Willian P. Germano, Joseph Gilbert,
+ * Campbell Barton
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -66,6 +67,8 @@
#include "../BPY_extern.h" /* BPY_txt_do_python_Text */
#include "../BPY_menus.h" /* to update menus */
+extern PyObject *bpy_registryDict; /* defined in ../BPY_interface.c */
+
/**********************************************************/
/* Python API function prototypes for the Blender module. */
/**********************************************************/
@@ -76,6 +79,7 @@ static PyObject *Blender_Quit( PyObject * self );
static PyObject *Blender_Load( PyObject * self, PyObject * args );
static PyObject *Blender_Save( PyObject * self, PyObject * args );
static PyObject *Blender_Run( PyObject * self, PyObject * args );
+static PyObject *Blender_ShowHelp( PyObject * self, PyObject * args );
static PyObject *Blender_UpdateMenus( PyObject * self);
extern PyObject *Text3d_Init( void ); /* missing in some include */
@@ -137,6 +141,15 @@ static char Blender_Run_doc[] =
"(script) - Run the given Python script.\n\
(script) - the path to a file or the name of an available Blender Text.";
+static char Blender_ShowHelp_doc[] =
+"(script) - Show help for the given Python script.\n\
+ This will try to open the 'Scripts Help Browser' script, so to have\n\
+any help displayed the passed 'script' must be properly documented\n\
+with the expected strings (check API ref docs or any bundled script\n\
+for examples).\n\n\
+(script) - the filename of a script in the default or user defined\n\
+ scripts dir (no need to supply the full path name).";
+
static char Blender_UpdateMenus_doc[] =
"() - Update the menus where scripts are registered. Only needed for\n\
scripts that save other new scripts in the default or user defined folders.";
@@ -152,6 +165,7 @@ static struct PyMethodDef Blender_methods[] = {
{"Load", Blender_Load, METH_VARARGS, Blender_Load_doc},
{"Save", Blender_Save, METH_VARARGS, Blender_Save_doc},
{"Run", Blender_Run, METH_VARARGS, Blender_Run_doc},
+ {"ShowHelp", Blender_ShowHelp, METH_VARARGS, Blender_ShowHelp_doc},
{"UpdateMenus", ( PyCFunction ) Blender_UpdateMenus, METH_NOARGS,
Blender_UpdateMenus_doc},
{NULL, NULL, 0, NULL}
@@ -272,6 +286,110 @@ static PyObject *Blender_Get( PyObject * self, PyObject * args )
}
if (!ret) ret = EXPP_incr_ret(Py_None);
}
+ /* USER PREFS: */
+ else if( StringEqual( str, "yfexportdir" ) ) {
+ if (U.yfexportdir[0] != '\0') {
+ char yfexportdir[FILE_MAXDIR];
+
+ BLI_strncpy(yfexportdir, U.yfexportdir, FILE_MAXDIR);
+ BLI_convertstringcode(yfexportdir, G.sce, 0);
+
+ if( BLI_exists( yfexportdir ) )
+ ret = PyString_FromString( yfexportdir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
+ /* fontsdir */
+ else if( StringEqual( str, "fontsdir" ) ) {
+ if (U.fontdir[0] != '\0') {
+ char fontdir[FILE_MAXDIR];
+
+ BLI_strncpy(fontdir, U.fontdir, FILE_MAXDIR);
+ BLI_convertstringcode(fontdir, G.sce, 0);
+
+ if( BLI_exists( fontdir ) )
+ ret = PyString_FromString( fontdir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
+ /* texturesdir */
+ else if( StringEqual( str, "texturesdir" ) ) {
+ if (U.textudir[0] != '\0') {
+ char textudir[FILE_MAXDIR];
+
+ BLI_strncpy(textudir, U.textudir, FILE_MAXDIR);
+ BLI_convertstringcode(textudir, G.sce, 0);
+
+ if( BLI_exists( textudir ) )
+ ret = PyString_FromString( textudir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
+ /* texpluginsdir */
+ else if( StringEqual( str, "texpluginsdir" ) ) {
+ if (U.plugtexdir[0] != '\0') {
+ char plugtexdir[FILE_MAXDIR];
+
+ BLI_strncpy(plugtexdir, U.plugtexdir, FILE_MAXDIR);
+ BLI_convertstringcode(plugtexdir, G.sce, 0);
+
+ if( BLI_exists( plugtexdir ) )
+ ret = PyString_FromString( plugtexdir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
+ /* seqpluginsdir */
+ else if( StringEqual( str, "seqpluginsdir" ) ) {
+ if (U.plugseqdir[0] != '\0') {
+ char plugseqdir[FILE_MAXDIR];
+
+ BLI_strncpy(plugseqdir, U.plugseqdir, FILE_MAXDIR);
+ BLI_convertstringcode(plugseqdir, G.sce, 0);
+
+ if( BLI_exists( plugseqdir ) )
+ ret = PyString_FromString( plugseqdir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
+ /* renderdir */
+ else if( StringEqual( str, "renderdir" ) ) {
+ if (U.renderdir[0] != '\0') {
+ char renderdir[FILE_MAXDIR];
+
+ BLI_strncpy(renderdir, U.renderdir, FILE_MAXDIR);
+ BLI_convertstringcode(renderdir, G.sce, 0);
+
+ if( BLI_exists( renderdir ) )
+ ret = PyString_FromString( renderdir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
+ /* soundsdir */
+ else if( StringEqual( str, "soundsdir" ) ) {
+ if (U.sounddir[0] != '\0') {
+ char sounddir[FILE_MAXDIR];
+
+ BLI_strncpy(sounddir, U.sounddir, FILE_MAXDIR);
+ BLI_convertstringcode(sounddir, G.sce, 0);
+
+ if( BLI_exists( sounddir ) )
+ ret = PyString_FromString( sounddir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
+ /* tempdir */
+ else if( StringEqual( str, "tempdir" ) ) {
+ if (U.tempdir[0] != '\0') {
+ char tempdir[FILE_MAXDIR];
+
+ BLI_strncpy(tempdir, U.tempdir, FILE_MAXDIR);
+ BLI_convertstringcode(tempdir, G.sce, 0);
+
+ if( BLI_exists( tempdir ) )
+ ret = PyString_FromString( tempdir );
+ }
+ if (!ret) ret = EXPP_incr_ret(Py_None);
+ }
/* According to the old file (opy_blender.c), the following if
statement is a quick hack and needs some clean up. */
else if( StringEqual( str, "vrmloptions" ) ) {
@@ -493,11 +611,56 @@ static PyObject *Blender_Save( PyObject * self, PyObject * args )
return Py_None;
}
+static PyObject *Blender_ShowHelp(PyObject *self, PyObject *args)
+{
+ PyObject *script = NULL;
+ char hspath[FILE_MAXDIR + FILE_MAXFILE]; /* path to help_browser.py */
+ char *sdir = bpy_gethome(1);
+ PyObject *rkeyd = NULL, *arglist = NULL;
+
+ if (!PyArg_ParseTuple(args, "O!", &PyString_Type, &script))
+ return EXPP_ReturnPyObjError(PyExc_TypeError,
+ "expected a script filename as argument");
+
+ /* first we try to find the help_browser script */
+
+ if (sdir) BLI_make_file_string("/", hspath, sdir, "help_browser.py");
+
+ if (!sdir || (!BLI_exists(hspath) && (U.pythondir[0] != '\0'))) {
+ char upydir[FILE_MAXDIR];
+
+ BLI_strncpy(upydir, U.pythondir, FILE_MAXDIR);
+ BLI_convertstringcode(upydir, G.sce, 0);
+ BLI_make_file_string("/", hspath, upydir, "help_browser.py");
+
+ if (!BLI_exists(hspath))
+ return EXPP_ReturnPyObjError(PyExc_RuntimeError,
+ "can't find script help_browser.py");
+ }
+
+ /* now we store the passed script in the registry dict and call the
+ * help_browser to show help info for it */
+ rkeyd = PyDict_New();
+ if (!rkeyd)
+ return EXPP_ReturnPyObjError(PyExc_MemoryError,
+ "can't create py dictionary!");
+
+ PyDict_SetItemString(rkeyd, "script", script);
+ PyDict_SetItemString(bpy_registryDict, "__help_browser", rkeyd);
+
+ arglist = Py_BuildValue("(s)", hspath);
+ Blender_Run(self, arglist);
+ Py_DECREF(arglist);
+
+ return EXPP_incr_ret(Py_None);
+}
+
static PyObject *Blender_Run(PyObject *self, PyObject *args)
{
char *fname = NULL;
Text *text = NULL;
int is_blender_text = 0;
+ Script *script = NULL;
if (!PyArg_ParseTuple(args, "s", &fname))
return EXPP_ReturnPyObjError(PyExc_TypeError,
@@ -527,7 +690,28 @@ static PyObject *Blender_Run(PyObject *self, PyObject *args)
}
}
- BPY_txt_do_python_Text(text);
+ /* (this is messy, check Draw.c's Method_Register and Window.c's file
+ * selector for more info)
+ * - caller script is the one that called this Blender_Run function;
+ * - called script is the argument to this function: fname;
+ * To mark scripts whose global dicts can't be freed right after
+ * the script execution (or better, 'first pass', since these scripts
+ * leave callbacks for gui or file/image selectors) we flag them. But to
+ * get a pointer to them we need to check which one is currently
+ * running (if none we're already at a spacescript). To make sure only
+ * the called script will have the SCRIPT_RUNNING flag on, we unset it
+ * for the caller script here: */
+ script = G.main->script.first;
+ while (script) {
+ if (script->flags & SCRIPT_RUNNING) break;
+ script = script->id.next;
+ }
+
+ if (script) script->flags &= ~SCRIPT_RUNNING; /* unset */
+
+ BPY_txt_do_python_Text(text); /* call new script */
+
+ if (script) script->flags |= SCRIPT_RUNNING; /* set */
if (!is_blender_text) free_libblock(&G.main->text, text);
diff --git a/source/blender/python/api2_2x/EXPP_interface.c b/source/blender/python/api2_2x/EXPP_interface.c
index 4be155db944..62d1f4e799f 100644
--- a/source/blender/python/api2_2x/EXPP_interface.c
+++ b/source/blender/python/api2_2x/EXPP_interface.c
@@ -65,6 +65,7 @@ char *bpy_gethome(int append_scriptsdir)
{
static char homedir[FILE_MAXDIR];
static char scriptsdir[FILE_MAXDIR];
+ char tmpdir[FILE_MAXDIR];
char bprogdir[FILE_MAXDIR];
char *s;
int i;
@@ -91,20 +92,37 @@ char *bpy_gethome(int append_scriptsdir)
}
else return homedir;
}
+ else homedir[0] = '\0';
- /* otherwise, use argv[0] (bprogname) to get .blender/ in
+ /* if either:
+ * no homedir was found or
+ * append_scriptsdir = 1 but there's no scripts/ inside homedir,
+ * use argv[0] (bprogname) to get .blender/ in
* Blender's installation dir */
s = BLI_last_slash( bprogname );
i = s - bprogname + 1;
- PyOS_snprintf( bprogdir, i, bprogname );
- BLI_make_file_string( "/", homedir, bprogdir, ".blender" );
+ PyOS_snprintf( bprogdir, i, "%s", bprogname );
- if (BLI_exists(homedir)) {
+ /* using tmpdir to preserve homedir (if) found above:
+ * the ideal is to have a home dir with scripts dir inside
+ * it, but if that isn't available, it's possible to
+ * have a 'broken' home dir somewhere and a scripts dir in the
+ * cvs sources */
+ BLI_make_file_string( "/", tmpdir, bprogdir, ".blender" );
+
+ if (BLI_exists(tmpdir)) {
if (append_scriptsdir) {
- BLI_make_file_string("/", scriptsdir, homedir, "scripts");
- if (BLI_exists(scriptsdir)) return scriptsdir;
+ BLI_make_file_string("/", scriptsdir, tmpdir, "scripts");
+ if (BLI_exists(scriptsdir)) {
+ PyOS_snprintf(homedir, FILE_MAXDIR, "%s", tmpdir);
+ return scriptsdir;
+ }
+ else {
+ homedir[0] = '\0';
+ scriptsdir[0] = '\0';
+ }
}
else return homedir;
}
@@ -113,6 +131,7 @@ char *bpy_gethome(int append_scriptsdir)
if (append_scriptsdir) {
BLI_make_file_string("/", scriptsdir, bprogdir, "release/scripts");
if (BLI_exists(scriptsdir)) return scriptsdir;
+ else scriptsdir[0] = '\0';
}
return NULL;
diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c
index f2bf3aa31e4..2e6f2ca2601 100644
--- a/source/blender/python/api2_2x/NMesh.c
+++ b/source/blender/python/api2_2x/NMesh.c
@@ -2796,7 +2796,7 @@ static PyObject *M_NMesh_PutRaw( PyObject * self, PyObject * args )
ob = add_object( OB_MESH );
if( !ob ) {
PyErr_SetString( PyExc_RuntimeError,
- "Fatal: could not create mesh object" );
+ "Fatal: could not create mesh object" );
return 0;
}
@@ -2824,6 +2824,11 @@ static PyObject *M_NMesh_PutRaw( PyObject * self, PyObject * args )
if( !during_script( ) )
EXPP_allqueue( REDRAWVIEW3D, 0 );
+ if (ob && G.obedit) { /* prevents a crash when a new object is created */
+ exit_editmode(1);
+ enter_editmode();
+ }
+
// @OK...this requires some explanation:
// Materials can be assigned two ways:
// a) to the object data (in this case, the mesh)
diff --git a/source/blender/python/api2_2x/Registry.c b/source/blender/python/api2_2x/Registry.c
index e0ba81b1029..bf839630aa2 100644
--- a/source/blender/python/api2_2x/Registry.c
+++ b/source/blender/python/api2_2x/Registry.c
@@ -33,11 +33,11 @@
#include "Registry.h"
#include <stdio.h>
+#include <BKE_global.h> /* G.f & G_DEBUG */
#include "gen_utils.h"
-
/* the Registry dictionary */
PyObject *bpy_registryDict = NULL;
@@ -64,17 +64,23 @@ char M_Registry_Keys_doc[] =
Each key references another dict with saved data from a specific script.\n";
char M_Registry_GetKey_doc[] =
- "(name) - Get a specific entry (dict) from the Registry dictionary\n\
- (name) - a string that references a specific script.\n";
+ "(name, disk = False) - Get an entry (a dict) from the Registry dictionary\n\
+ (name) - a string that references a specific script;\n\
+ (disk = False) - search on the user (if available) or default scripts config\n\
+data dir.\n";
char M_Registry_SetKey_doc[] =
- "(key, dict) - Store an entry in the Registry dictionary.\n\
+ "(key, dict, disk = False) - Store an entry in the Registry dictionary.\n\
If an entry with the same 'key' already exists, it is substituted.\n\
(key) - the string to use as a key for the dict being saved.\n\
- (dict) - a dictionary with the data to be stored.\n";
+ (dict) - a dictionary with the data to be stored.\n\
+ (disk = False) - also write data as a config file inside the user (if\n\
+available) or default scripts config data dir.\n";
char M_Registry_RemoveKey_doc[] =
- "(key) - Remove the dict with key 'key' from the Registry.\n";
+ "(key, disk = False) - Remove the dict with key 'key' from the Registry.\n\
+ (key) - the name of the key to delete;\n\
+ (disk = False) - if True the respective config file is also deleted.\n";
/*****************************************************************************/
/* Python method structure definition for Blender.Registry module: */
@@ -118,25 +124,35 @@ static PyObject *M_Registry_GetKey( PyObject * self, PyObject * args )
{
PyObject *pyentry = NULL;
PyObject *pydict = NULL;
+ int disk = 0;
if( !bpy_registryDict )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
- "No Registry dictionary found!" );
+ "No Registry dictionary found!" );
- if( !PyArg_ParseTuple( args, "O!", &PyString_Type, &pyentry ) )
+ if( !PyArg_ParseTuple( args, "O!|i", &PyString_Type, &pyentry, &disk ) )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
- "expected a string" );
+ "expected a string and optionally a bool" );
pydict = PyDict_GetItem( bpy_registryDict, pyentry ); /* borrowed ... */
- if( !pydict )
-/* return EXPP_ReturnPyObjError (PyExc_KeyError,
- "no such key in the Registry"); */
- pydict = Py_None; /* better to return None than an error */
-
- Py_INCREF( pydict ); /* ... so we incref it */
- /* should we copy the dict instead? */
- return pydict;
+ if (!pydict) {
+ if (disk > 0) {
+ /* try to get data from disk */
+ char buf[256];
+ PyOS_snprintf(buf, sizeof(buf),
+ "import Blender, BPyRegistry; BPyRegistry.LoadConfigData('%s')",
+ PyString_AsString(pyentry));
+ if (!PyRun_SimpleString(buf))
+ pydict = PyDict_GetItem(bpy_registryDict, pyentry);
+ else PyErr_Clear();
+ }
+
+ if (!pydict) /* no need to return a KeyError, since without doubt */
+ pydict = Py_None; /* Py_None means no key (all valid keys are dicts) */
+ }
+
+ return EXPP_incr_ret (pydict); /* ... so we incref it */
}
/*****************************************************************************/
@@ -147,14 +163,15 @@ static PyObject *M_Registry_SetKey( PyObject * self, PyObject * args )
{
PyObject *pystr = NULL;
PyObject *pydict = NULL;
+ int disk = 0;
if( !bpy_registryDict )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
"No Registry dictionary found!" );
- if( !PyArg_ParseTuple( args, "O!O!",
+ if( !PyArg_ParseTuple( args, "O!O!|i",
&PyString_Type, &pystr, &PyDict_Type,
- &pydict ) )
+ &pydict, &disk ) )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
"expected a string and a dictionary" );
@@ -162,6 +179,19 @@ static PyObject *M_Registry_SetKey( PyObject * self, PyObject * args )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
"Registry_SetKey: couldn't update the Registry dict" );
+ if (disk) {
+ /* try to save data to disk */
+ char buf[256];
+ PyOS_snprintf(buf, sizeof(buf),
+ "import Blender, BPyRegistry; BPyRegistry.SaveConfigData('%s')",
+ PyString_AsString(pystr));
+ if (PyRun_SimpleString(buf) != 0) {
+ PyErr_Clear();
+ if (G.f & G_DEBUG)
+ fprintf(stderr, "\nCan't save script configuration data!\n");
+ }
+ }
+
Py_INCREF( Py_None );
return Py_None;
}
@@ -173,18 +203,31 @@ static PyObject *M_Registry_SetKey( PyObject * self, PyObject * args )
static PyObject *M_Registry_RemoveKey( PyObject * self, PyObject * args )
{
PyObject *pystr = NULL;
+ int disk = 0;
if( !bpy_registryDict )
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
"No Registry dictionary found!" );
- if( !PyArg_ParseTuple( args, "O!", &PyString_Type, &pystr ) )
+ if( !PyArg_ParseTuple( args, "O!|i", &PyString_Type, &pystr, &disk ) )
return EXPP_ReturnPyObjError( PyExc_AttributeError,
- "expected a string" );
+ "expected a string and optionally a bool" );
if( PyDict_DelItem( bpy_registryDict, pystr ) ) /* returns 0 on success */
return EXPP_ReturnPyObjError( PyExc_KeyError,
"no such key in the Registry" );
+ else if (disk) {
+ /* try to delete from disk too */
+ char buf[256];
+ PyOS_snprintf(buf, sizeof(buf),
+ "import Blender, BPyRegistry; BPyRegistry.RemoveConfigData('%s')",
+ PyString_AsString(pystr));
+ if (PyRun_SimpleString(buf) != 0) {
+ PyErr_Clear();
+ if (G.f & G_DEBUG)
+ fprintf(stderr, "\nCan't remove script configuration data file!\n");
+ }
+ }
Py_INCREF( Py_None );
return Py_None;
diff --git a/source/blender/python/api2_2x/Sys.c b/source/blender/python/api2_2x/Sys.c
index 5af539ac881..64bdc49bf79 100644
--- a/source/blender/python/api2_2x/Sys.c
+++ b/source/blender/python/api2_2x/Sys.c
@@ -25,13 +25,14 @@
*
* This is a new part of Blender.
*
- * Contributor(s): Willian P. Germano
+ * Contributor(s): Willian P. Germano, Campbell Barton
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include <BKE_utildefines.h>
#include <BLI_blenlib.h>
+#include <DNA_scene_types.h> /* G.scene->r.cfra */
#include <PIL_time.h>
#include <Python.h>
#include <sys/stat.h>
@@ -47,10 +48,11 @@ static PyObject *M_sys_dirname( PyObject * self, PyObject * args );
static PyObject *M_sys_join( PyObject * self, PyObject * args );
static PyObject *M_sys_splitext( PyObject * self, PyObject * args );
static PyObject *M_sys_makename( PyObject * self, PyObject * args,
- PyObject * kw );
+ PyObject * kw );
static PyObject *M_sys_exists( PyObject * self, PyObject * args );
static PyObject *M_sys_time( PyObject * self );
static PyObject *M_sys_sleep( PyObject * self, PyObject * args );
+static PyObject *M_sys_expandpath( PyObject *self, PyObject *args);
/*****************************************************************************/
/* The following string definitions are used for documentation strings. */
@@ -108,6 +110,15 @@ The return value is as follows:\n\
\t 2: path is an existing dirname;\n\
\t-1: path exists but is neither a regular file nor a dir.";
+static char M_sys_expandpath_doc[] =
+"(path) - Expand this Blender internal path to a proper file system path.\n\
+(path) - the string path to convert.\n\n\
+Note: internally Blender paths can contain two special character sequences:\n\
+- '//' (at start) for base path directory (the current .blend's dir path);\n\
+- '#' (at ending) for current frame number.\n\n\
+This function expands these to their actual content, returning a valid path.\n\
+If the special chars are not found in the given path, it is simply returned.";
+
/*****************************************************************************/
/* Python method structure definition for Blender.sys module: */
/*****************************************************************************/
@@ -122,6 +133,7 @@ struct PyMethodDef M_sys_methods[] = {
{"exists", M_sys_exists, METH_VARARGS, M_sys_exists_doc},
{"sleep", M_sys_sleep, METH_VARARGS, M_sys_sleep_doc},
{"time", ( PyCFunction ) M_sys_time, METH_NOARGS, M_sys_time_doc},
+ {"expandpath", M_sys_expandpath, METH_VARARGS, M_sys_expandpath_doc},
{NULL, NULL, 0, NULL}
};
@@ -395,3 +407,18 @@ static PyObject *M_sys_exists( PyObject * self, PyObject * args )
return Py_BuildValue( "i", i );
}
+
+static PyObject *M_sys_expandpath( PyObject * self, PyObject * args )
+{
+ char *path = NULL;
+ char expanded[FILE_MAXDIR + FILE_MAXFILE];
+
+ if (!PyArg_ParseTuple( args, "s", &path))
+ return EXPP_ReturnPyObjError( PyExc_TypeError,
+ "expected string argument" );
+
+ BLI_strncpy(expanded, path, FILE_MAXDIR + FILE_MAXFILE);
+ BLI_convertstringcode(expanded, G.sce, G.scene->r.cfra);
+
+ return PyString_FromString(expanded);
+}
diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py
index 8f4031756f2..ce2b7d8fc93 100644
--- a/source/blender/python/api2_2x/doc/API_intro.py
+++ b/source/blender/python/api2_2x/doc/API_intro.py
@@ -40,9 +40,16 @@ The Blender Python API Reference
- L{Texture}
- L{Types}
- L{Window}
- - L{Theme} (new)
+ - L{Theme}
- L{World}
- - L{sys<Sys>}
+ - L{sys<Sys>} (*)
+
+ Additional information:
+ -----------------------
+
+ - L{Misc facilities<API_related>}:
+ - scripts: registering in menus, documenting, configuring (new);
+ - command line examples (new).
(*) - marks updated.
@@ -91,57 +98,6 @@ These are the basic ways to execute scripts in Blender:
6. A script can call another script (that will run in its own context, with
its own global dictionary) with the L{Blender.Run} module function.
-Registering scripts:
---------------------
- To be registered a script needs two things:
- - be either in the default scripts dir or in the user defined scripts path
- (see Info window, paths tab);
- - have a proper header.
-
- Try 'blender -d' to know where your default dir for scripts is, it will
- inform either the dir or the file with that info already parsed, which is
- in the same dir of the scripts folder.
-
- The header should be like this one (all double and single apostrophes below
- are required)::
- #!BPY
-
- # \"\"\"
- # Name: 'Script Name'
- # Blender: 233
- # Group: 'Export'
- # Submenu: 'All' all
- # Submenu: 'Selected' sel
- # Submenu: 'Configure (gui)' gui
- # Tooltip: 'Export to some format.'
- # \"\"\"
-
- where:
- - B{Name} is the string that will appear in the menu;
- - B{Blender} is the minimum program version required to run the script;
- - B{Group} defines where the script will be put, see all groups in the
- Scripts Window's header, menu "Scripts";
- - B{Submenu} adds optional submenus for further control;
- - B{Tooltip} is the (short) tooltip string for the menu entry.
-
- note:
- - all double and single apostrophes above are required;
- - B{*NEW*}: you can "comment out" the header above, by starting lines with
- '#', like we did. This is not required (except for the first line, #!BPY,
- of course), but this way the header won't conflict with Python tools that
- you can use to generate documentation for your script code. Just
- remember to keep this header above any other line with triple
- double-quotes (\"\"\") in your script.
-
- Submenu lines are not required, use them if you want to provide extra
- options. To see which submenu the user chose, check the "__script__"
- dictionary in your code: __script__['arg'] has the defined keyword (the word
- after the submenu string name: all, sel or gui in the example above) of the
- chosen submenu. For example, if the user clicked on submenu 'Selected' above,
- __script__['arg'] will be "sel".
-
- If your script requires extra data or configuration files, there is a special
- folder where they can be saved: see 'datadir' in L{Blender.Get}.
Interaction with users:
-----------------------
@@ -171,53 +127,22 @@ Command line mode:
run scripts from the program itself: you can't import the Blender module
into an external Python interpreter.
- But with "OnLoad" script links, the "-b" background mode and additions like
- the "-P" command line switch, L{Blender.Save}, L{Blender.Load},
- L{Blender.Quit} and the L{Library} module, for many tasks it's possible to
- control Blender via some automated process using scripts. Note that command
- line scripts are run before Blender initializes its windows (and in '-b' mode
- no window will be initialized), so many functions that get or set window
- related attributes (like most in L{Window}) don't work here. If you need
- those, use an ONLOAD script link (see L{Scene.Scene.addScriptLink}) instead --
- it's also possible to use a command line script to write or set an ONLOAD
- script link. Check the L{Blender.mode} module var to know if Blender is being
- executed in "background" or "interactive" mode.
-
- Background mode examples::
-
- # Open Blender in background mode with file 'myfile.blend'
- # and run the script 'script.py':
-
- blender -b myfile.blend -P script.py
-
- # Note: a .blend file is always required. 'script.py' can be a file
- # in the file system or a Blender Text stored in 'myfile.blend'.
+ On the other hand, for many tasks it's possible to control Blender via
+ some automated process using scripts. Interested readers should learn about
+ features like "OnLoad" script links, the "-b <blendfile>" (background mode)
+ and "-P <script>" (run script) command line options and API calls like
+ L{Blender.Save}, L{Blender.Load}, L{Blender.Quit} and the L{Library} and
+ L{Render} modules.
- # Let's assume 'script.py' has code to render the current frame;
- # this line will set the [s]tart and [e]nd (and so the current) frame to
- # frame 44 and call the script:
+ Note that command line scripts are run before Blender initializes its windows
+ (and in '-b' mode no window will be initialized), so many functions that get
+ or set window related attributes (like most in L{Window}) don't work here. If
+ you need those, use an ONLOAD script link (see L{Scene.Scene.addScriptLink})
+ instead -- it's also possible to use a command line script to write or set an
+ ONLOAD script link. Check the L{Blender.mode} module var to know if Blender
+ is being executed in "background" or "interactive" mode.
- blender -b myfile.blend -s 44 -e 44 -P script.py
-
- # Using now a script written to render animations, we set different
- # start and end frames and then execute this line:
-
- blender -b myfile.blend -s 1 -e 10 -P script.py
-
- # Note: we can also set frames and define if we want a single image or
- # an animation in the script body itself, naturally.
-
- The rendered pictures will be written to the default render folder, that can
- also be set via bpython (take a look at L{Render.RenderData}). Their
- names will be the equivalent frame number followed by the extension of the
- chosen image type: 0001.png, for example. To rename them to something else,
- coders can use the C{rename} function in the standard 'os' Python module.
-
- Reminder: if you just need to render, it's not necessary to have a script.
- Blender can create stills and animations with its own command line arguments.
- Example:
- - a single image at frame 44: blender -b myfile.blend -f 44
- - an animation from frame 1 to 10: blender -b myfile.blend -s 1 -e 10 -a
+ L{Click here for command line and background mode examples<API_related>}.
Demo mode:
@@ -246,7 +171,7 @@ Blender Data Structures:
Programs manipulate data structures. Blender python scripts are no exception.
Blender uses an Object Oriented architecture. The bpython interface tries to
present Blender objects and their attributes in the same way you see them
- through the User Interface ( the GUI ). One key to bpython programming is
+ through the User Interface (the GUI). One key to bpython programming is
understanding the information presented in Blender's OOPS window where Blender
objects and their relationships are displayed.
@@ -268,74 +193,6 @@ Blender Data Structures:
Blender works the way it does, see the U{Blender Architecture document
<http://www.blender3d.org/cms/Blender_Architecture.336.0.html>}.
-Documenting scripts:
---------------------
-
- The "Scripts Help Browser" script in the Help menu can parse special variables
- from registered scripts and display help information for users. For that,
- authors only need to add proper information to their scripts, after the
- registration header.
-
- The expected variables:
-
- - __bpydoc__ (or __doc__) (type: string):
- - The main help text. Write a first short paragraph explaining what the
- script does, then add the rest of the help text, leaving a blank line
- between each new paragraph. To force line breaks you can use <br> tags.
-
- - __author__ (type: string or list of strings):
- - Author name(s).
-
- - __version__ (type: string):
- - Script version.
-
- - __url__ (type: string or list of strings):
- - Internet links that are shown as buttons in the help screen. Clicking
- them opens the user's default browser at the specified location. The
- expected format for each url entry is e.g.
- "Author's site, http://www.somewhere.com". The first part, before the
- comma (','), is used as the button's tooltip. There are two preset
- options: "blender" and "elysiun", which link to the Python forums at
- blender.org and elysiun.com, respectively.
-
- - __email__ (optional, type: string or list of strings):
- - Equivalent to __url__, but opens the user's default email client. You
- can write the email as someone:somewhere*com and the help script will
- substitute accordingly: someone@somewhere.com. This is only a minor help
- to hide emails from spammers, since your script may be available at some
- site. "scripts" is the available preset, with the email address of the
- mailing list devoted to scripting in Blender, bf-scripts-dev@blender.org.
- You should only use this one if you are subscribed to the list:
- http://projects.blender.org/mailman/listinfo/bf-scripts-dev for more
- information.
-
- Example::
- __author__ = 'Mr. Author'
- __version__ = '1.0 2005/06/06'
- __url__ = ["Author's site, http://somewhere.com",
- "Support forum, http://somewhere.com/forum/", "blender", "elysiun"]
- __email__ = ["Mr. Author, mrauthor:somewhere*com", "scripts"]
- __bpydoc__ = \"\"\"\\
- This script does this and that.
-
- Explaining better, this script helps you create ...
-
- You can write as many paragraphs as needed.
-
- Shortcuts:<br>
- Esc or Q: quit.<br>
- etc.
-
- Supported:<br>
- Meshes, metaballs.
-
- Known issues:<br>
- This is just an example, there's no actual script.
-
- Notes:<br>
- You can check scripts bundled with Blender to see more examples of how to
- add documentation to your own works.
- \"\"\"
A note to newbie script writers:
--------------------------------
@@ -348,8 +205,8 @@ A note to newbie script writers:
to get an idea of what can be done, you may be surprised.
@author: The Blender Python Team
-@requires: Blender 2.35 or newer.
-@version: 2.35 - 2.36
+@requires: Blender 2.36 cvs or newer.
+@version: 2.36 cvs
@see: U{www.blender3d.org<http://www.blender3d.org>}: main site
@see: U{www.blender.org<http://www.blender.org>}: documentation and forum
@see: U{www.elysiun.com<http://www.elysiun.com>}: user forum
diff --git a/source/blender/python/api2_2x/doc/API_related.py b/source/blender/python/api2_2x/doc/API_related.py
new file mode 100644
index 00000000000..103a6c3d0a2
--- /dev/null
+++ b/source/blender/python/api2_2x/doc/API_related.py
@@ -0,0 +1,377 @@
+# This is not a real module, it's simply an introductory text.
+
+"""
+Blender Python related features
+===============================
+
+ L{Back to Main Page<API_intro>}
+
+
+Introduction:
+=============
+
+ This page describes special features available to BPython scripts:
+
+ - Command line mode is accessible with the '-P' and '-b' Blender options.
+ - Registration allows scripts to become available from some pre-defined menus
+ in Blender, like Import, Export, Wizards and so on.
+ - Proper documentation data is used by the 'Scripts Help Browser' script to
+ show help information for any registered script. Your own GUI can use
+ this facility with the L{Blender.ShowHelp} function.
+ - Configuration is for data in your script that can be tweaked according to
+ user taste or needs. Like documentation, this is another helper
+ functionality -- you don't need to provide a GUI yourself to edit config
+ data.
+
+
+ Command line usage:
+ -------------------
+
+ B{Specifying scripts}:
+
+ The '-P' option followed either by:
+ - a script filename (full pathname if not in the same folder where you run
+ the command);
+ - the name of a Text in a .blend file (that must also be specified)
+ will open Blender and immediately run the given script.
+
+ Example::
+
+ # open Blender and execute the given script:
+ blender -P script.py
+
+ B{Passing parameters}:
+
+ To pass parameters to the script you can:
+ - write them to a file before running Blender, then make your script parse that file;
+ - set environment variables and access them with the 'os' module:
+
+ Examples with parameters being passed to the script via command line::
+
+ # execute a command like:
+
+ myvar=value blender -P script.py
+
+ # and in script.py access myvar with os.getenv
+ # (os.environ and os.setenv are also useful):
+
+ # script.py:
+ import os
+ val = os.getenv('myvar')
+
+ # To pass multiple parameters, simply write them in sequence,
+ # separated by spaces:
+
+ myvar1=value1 myvar2=value2 mystr="some string data" blender -P script.py
+
+ B{Background mode}:
+
+ In '-b' mode no windows will be opened: the program will run as a command
+ line tool able to render stills and animations and execute any working Python
+ script with complete access to loaded .blend's file contents. Once the task
+ is completed, the program will exit.
+
+ Background mode examples::
+
+ # Open Blender in background mode with file 'myfile.blend'
+ # and run the script 'script.py':
+
+ blender -b myfile.blend -P script.py
+
+ # Note: a .blend file is always required. 'script.py' can be a file
+ # in the file system or a Blender Text stored in 'myfile.blend'.
+
+ # Let's assume 'script.py' has code to render the current frame;
+ # this line will set the [s]tart and [e]nd (and so the current) frame to
+ # frame 44 and call the script:
+
+ blender -b myfile.blend -s 44 -e 44 -P script.py
+
+ # Using now a script written to render animations, we set different
+ # start and end frames and then execute this line:
+
+ blender -b myfile.blend -s 1 -e 10 -P script.py
+
+ # Note: we can also set frames and define if we want a single image or
+ # an animation in the script body itself, naturally.
+
+ The rendered pictures will be written to the default render folder, that can
+ also be set via bpython (take a look at L{Render.RenderData}). Their
+ names will be the equivalent frame number followed by the extension of the
+ chosen image type: 0001.png, for example. To rename them to something else,
+ coders can use the C{rename} function in the standard 'os' Python module.
+
+ Reminder: if you just need to render, it's not necessary to have a script.
+ Blender can create stills and animations with its own command line arguments.
+ Example:
+ - a single image at frame 44: blender -b myfile.blend -f 44
+ - an animation from frame 1 to 10: blender -b myfile.blend -s 1 -e 10 -a
+
+
+ Registering scripts:
+ --------------------
+
+ To be registered a script needs two things:
+ - to be either in the default scripts dir or in the user defined scripts
+ path (see User Preferences window -> File Paths tab -> Python path);
+ - to have a proper header.
+
+ Try 'blender -d' to know where your default dir for scripts is, it will
+ inform either the dir or the file with that info already parsed, which is
+ in the same dir of the scripts folder.
+
+ The header should be like this one (all double and single apostrophes below
+ are required)::
+ #!BPY
+
+ # \"\"\"
+ # Name: 'Script Name'
+ # Blender: 233
+ # Group: 'Export'
+ # Submenu: 'All' all
+ # Submenu: 'Selected' sel
+ # Submenu: 'Configure (gui)' gui
+ # Tooltip: 'Export to some format.'
+ # \"\"\"
+
+ where:
+ - B{Name} is the string that will appear in the menu;
+ - B{Blender} is the minimum program version required to run the script;
+ - B{Group} defines where the script will be put, see all groups in the
+ Scripts Window's header, menu "Scripts";
+ - B{Submenu} adds optional submenus for further control;
+ - B{Tooltip} is the (short) tooltip string for the menu entry.
+
+ note:
+ - all double and single apostrophes above are required;
+ - you can "comment out" the header above, by starting lines with
+ '#', like we did. This is not required (except for the first line, #!BPY,
+ of course), but this way the header won't conflict with Python tools that
+ you can use to generate documentation for your script code. Just
+ remember to keep this header above any other line with triple
+ double-quotes (\"\"\") in your script.
+
+ Submenu lines are not required, use them if you want to provide extra
+ options. To see which submenu the user chose, check the "__script__"
+ dictionary in your code: __script__['arg'] has the defined keyword (the word
+ after the submenu string name: all, sel or gui in the example above) of the
+ chosen submenu. For example, if the user clicked on submenu 'Selected' above,
+ __script__['arg'] will be "sel".
+
+ If your script requires extra data or configuration files, there is a special
+ folder where they can be saved: see 'datadir' in L{Blender.Get}.
+
+
+ Documenting scripts:
+ --------------------
+
+ The "Scripts Help Browser" script in the Help menu can parse special variables
+ from registered scripts and display help information for users. For that,
+ authors only need to add proper information to their scripts, after the
+ registration header.
+
+ The expected variables:
+
+ - __bpydoc__ (or __doc__) (type: string):
+ - The main help text. Write a first short paragraph explaining what the
+ script does, then add the rest of the help text, leaving a blank line
+ between each new paragraph. To force line breaks you can use <br> tags.
+
+ - __author__ (type: string or list of strings):
+ - Author name(s).
+
+ - __version__ (type: string):
+ - Script version. A good recommendation is using a version number followed
+ by the date in the format YYYY/MM/DD: "1.0 2005/12/31".
+
+ - __url__ (type: string or list of strings):
+ - Internet links that are shown as buttons in the help screen. Clicking
+ them opens the user's default browser at the specified location. The
+ expected format for each url entry is e.g.
+ "Author's site, http://www.somewhere.com". The first part, before the
+ comma (','), is used as the button's tooltip. There are two preset
+ options: "blender" and "elysiun", which link to the Python forums at
+ blender.org and elysiun.com, respectively.
+
+ - __email__ (optional, type: string or list of strings):
+ - Equivalent to __url__, but opens the user's default email client. You
+ can write the email as someone:somewhere*com and the help script will
+ substitute accordingly: someone@somewhere.com. This is only a minor help
+ to hide emails from spammers, since your script may be available at some
+ site. "scripts" is the available preset, with the email address of the
+ mailing list devoted to scripting in Blender, bf-scripts-dev@blender.org.
+ You should only use this one if you are subscribed to the list:
+ http://projects.blender.org/mailman/listinfo/bf-scripts-dev for more
+ information.
+
+ Example::
+ __author__ = 'Mr. Author'
+ __version__ = '1.0 2005/01/01'
+ __url__ = ["Author's site, http://somewhere.com",
+ "Support forum, http://somewhere.com/forum/", "blender", "elysiun"]
+ __email__ = ["Mr. Author, mrauthor:somewhere*com", "scripts"]
+ __bpydoc__ = \"\"\"\\
+ This script does this and that.
+
+ Explaining better, this script helps you create ...
+
+ You can write as many paragraphs as needed.
+
+ Shortcuts:<br>
+ Esc or Q: quit.<br>
+ etc.
+
+ Supported:<br>
+ Meshes, metaballs.
+
+ Known issues:<br>
+ This is just an example, there's no actual script.
+
+ Notes:<br>
+ You can check scripts bundled with Blender to see more examples of how to
+ add documentation to your own works.
+ \"\"\"
+
+ B{Note}: your own GUI or menu code can display documentation by calling the
+ help browser with the L{Blender.ShowHelp} function.
+
+ Configuring scripts:
+ --------------------
+
+ Configuration data is simple data used by your script (bools, ints, floats,
+ strings) to define default behaviors.
+
+ For example, an exporter might have:
+ - EXPORT_LIGHTS = False: a bool variable (True / False) to determine if it
+ should also export lights setup information;
+ - VERSION = 2.0: an int to define an specific version of the export format;
+ - TEX_DIR = "/path/to/textures": a default texture dir to prepend to all
+ exported texture filenames instead of their actual paths.
+
+ To properly handle this, script writers had to keep this information in a
+ separate config file (at L{Blender.Get}('udatadir') or, if not available,
+ L{Blender.Get}('datadir')), provide a GUI to edit it and update the file
+ whenever needed.
+
+ There are facilities in BPython now to take care of this in a simplified (and
+ much recommended) way.
+
+ The L{Registry} module functions L{GetKey<Registry.GetKey>} and
+ L{SetKey<Registry.SetKey>} take care of both keeping the data in Blender
+ and (new) storing it in config files at the proper dir. And the 'Scripts
+ Configuration Editor' script provides a GUI for users to view and edit
+ configuration data.
+
+ Here's how it works::
+
+ # sample_exporter.py
+ import Blender
+ from Blender import Registry
+
+ # First define all config variables with their default values:
+ EXPORT_LIGHTS = True
+ VERBOSE = True
+ EXPORT_DIR = ''
+
+ # Then define a function to update the Registry:
+ def registry_update():
+ # populate a dict with current config values:
+ d = {
+ 'EXPORT_LIGHTS': EXPORT_LIGHTS,
+ 'VERBOSE': VERBOSE,
+ 'EXPORT_DIR': EXPORT_DIR
+ }
+ # store the key (optional 3rd arg tells if
+ # the data should also be written to a file):
+ Registry.SetKey('sample_exporter', d, True)
+
+ # (A good convention is to use the script name as Registry key)
+
+ # Now we check if our key is available in the Registry or file system:
+ regdict = Registry.GetKey('sample_exporter', True)
+
+ # If this key already exists, update config variables with its values:
+ if regdict:
+ EXPORT_LIGHTS = regdict['EXPORT_LIGHTS']
+ VERBOSE = regdict['VERBOSE']
+ EXPORT_DIR = regdict['EXPORT_DIR']
+ else: # if the key doesn't exist yet, use our function to create it:
+ update_registry()
+
+ # ...
+
+ Hint: nicer code than the simplistic example above can be written by keeping
+ config var names in a list of strings and using the exec function.
+
+ B{Note}: if you have a gui and the user uses it to change config vars,
+ call the registry_update() function to save the changes.
+ On the other hand, you don't need to handle configuration
+ in your own gui, it can be left for the 'Scripts Config Editor',
+ which should have access to your script's config key as soon as the
+ above code is executed once.
+
+ As written above, config vars can be bools, ints, floats or strings. This is
+ what the Config Editor supports, with sensible but generous limits for the
+ number of vars and the size of each string. Restrictions were suggested or
+ imposed to these facilities related to the Registry module because it's meant
+ for configuration info, not for large volumes of data. For that you can
+ trivially store it in a file or Blender Text yourself -- and tell the user
+ about it, specially if your script keeps megabytes of data in the Registry
+ memory.
+
+ B{Scripts Configuration Editor}:
+
+ This script should be available from the Help menu and provides a GUI to
+ view and edit saved configuration data, both from the Registry dictionary in
+ memory and the scripts config data dir.
+
+ The example above already gives a good idea of how the information can be
+ prepared to be accessible from this editor, but there is more worth knowing:
+
+ 1. String vars that end with '_dir' or '_file' (can be upper case, too) are
+ recognized as input boxes for dirs or files and a 'browse' button is added to
+ their right side, to call the file selector.
+
+ 2. Both key names and configuration variables names starting with an
+ underscore ('_') are ignored by the editor. Programmers can use this feature
+ for any key or config var that is not meant to be configured by this editor.
+
+ 3. The following information refers to extra config variables that may be
+ added specifically to aid the configuration editor script. To clarify, in the
+ example code above these variables (the string 'script' and the dictionaries
+ 'tooltips' and 'limits') would appear along with EXPORT_LIGHTS, VERBOSE and
+ EXPORT_DIR, wherever they are written.
+
+ Minor note: these names are case insensitive: tooltips, TOOLTIPS, etc. are all
+ recognized.
+
+ 3.1 The config editor will try to display a 'help' button for a key, to show
+ documentation for the script that owns it. To find this "owner script", it
+ will first look for a config variable called 'script', a string containing
+ the name of the owner Python file (with or without '.py' extension)::
+
+ script = 'sample_exporter.py'
+
+ If there is no such variable, the editor will check if the file formed by the
+ key name and the '.py' extension exists. If both alternatives fail, no help
+ button will be displayed.
+
+ 3.2 You can define tooltips for the buttons that the editor creates for your
+ config data (string input, toggle, number sliders). Simply create a dict
+ called 'tooltips', where config var names are keys and their tooltips,
+ values::
+
+ tooltips = {
+ 'EXPORT_DIR': 'default folder where exported files should be saved',
+ 'VERBOSE': 'print info and warning messages to the console',
+ 'EXPORT_LIGHTS': 'export scene lighting setup'
+ }
+
+ 3.3 Int and float button sliders need min and max limits. This can be passed
+ to the editor via a dict called 'limits' (ivar1, ivar2 and fvar are meant as
+ extra config vars that might have been in the example code above)::
+
+ limits = {'ivar1': [-10, 10], 'ivar2': [0, 100], 'fvar1': [-12.3, 15.4]}
+
+ L{Back to Main Page<API_intro>}
+"""
diff --git a/source/blender/python/api2_2x/doc/Blender.py b/source/blender/python/api2_2x/doc/Blender.py
index d22536c24a8..1aa7f81c703 100644
--- a/source/blender/python/api2_2x/doc/Blender.py
+++ b/source/blender/python/api2_2x/doc/Blender.py
@@ -10,7 +10,7 @@
"""
The main Blender module.
-B{New}: L{Run}, L{UpdateMenus}, new options to L{Get}.
+B{New}: L{Run}, L{UpdateMenus}, new options to L{Get}, L{ShowHelp}.
Blender
=======
@@ -61,13 +61,23 @@ def Get (request):
available (is None if not found), but users that define uscriptsdir
have a place for their own scripts and script data that won't be
erased when a new version of Blender is installed.
- - 'scriptsdir': the path to the main dir where scripts are stored
- (can be None, if not found).
- - 'uscriptsdir': the path to the user defined dir for scripts, see
- the paths tab in the User Preferences window in Blender
- (can be None, if not found).
+ - 'scriptsdir': the path to the main dir where scripts are stored.
+ - 'uscriptsdir': the path to the user defined dir for scripts. (*)
+ - 'yfexportdir': the path to the user defined dir for yafray export. (*)
+ - 'fontsdir': the path to the user defined dir for fonts. (*)
+ - 'texturesdir': the path to the user defined dir for textures. (*)
+ - 'texpluginsdir': the path to the user defined dir for texture plugins. (*)
+ - 'seqpluginsdir': the path to the user defined dir for sequence plugins. (*)
+ - 'renderdir': the path to the user defined dir for render output. (*)
+ - 'soundsdir': the path to the user defined dir for sound files. (*)
+ - 'tempdir': the path to the user defined dir for storage of Blender
+ temporary files. (*)
- 'version' : the Blender version number.
- @return: The requested data.
+ @note: (*) these can be set in Blender at the User Preferences window -> File
+ Paths tab.
+ @warn: this function returns None for requested dir paths that have not been
+ set or do not exist in the user's file system.
+ @return: The requested data or None if not found.
"""
def Redraw ():
@@ -122,8 +132,8 @@ def Save (filename, overwrite = 0):
of the supported extensions or an error will be returned.
@type overwrite: int (bool)
@param overwrite: if non-zero, file 'filename' will be overwritten if it
- already exists. By default existing files are not overwritten (an error
- is returned).
+ already exists (can be checked with L{Blender.sys.exists<Sys.exists>}.
+ By default existing files are not overwritten (an error is returned).
@note: The substring ".B.blend" is not accepted inside 'filename'.
@note: DXF, STL and Videoscape export only B{selected} meshes.
@@ -136,8 +146,28 @@ def Run (script):
@param script: the name of an available Blender Text (use L{Text.Get}() to
get a complete list) or the full pathname to a Python script file in the
system.
- @note: the script is executed in its own context (with its own global
- dictionary), as if you had called it with ALT+P or chosen from a menu.
+ @note: the script is executed in its own context -- with its own global
+ dictionary -- as if it had been executed from the Text Editor or chosen
+ from a menu.
+ """
+
+def ShowHelp (script):
+ """
+ Show help for the given script. This is a time-saver ("code-saver") for
+ scripts that need to feature a 'help' button in their GUI's or a 'help'
+ submenu option. With proper documentation strings, calling this function is
+ enough to present a screen with help information plus link and email buttons.
+ @type script: string
+ @param script: the filename of a registered Python script.
+ @note: this function uses L{Run} and the "Scripts Help Browser" script. This
+ means that it expects proper doc strings in the script to be able to show
+ help for it (otherwise it offers to load the script source code as text).
+ The necessary information about doc strings is in the
+ L{Intro page<API_intro>} of this API Reference documentation you're
+ reading.
+ @note: 'script' doesn't need to be a full path name: "filename.py" is enough.
+ Note, though, that this function only works for properly registered
+ scripts (those that appear in menus).
"""
def UpdateMenus ():
diff --git a/source/blender/python/api2_2x/doc/Draw.py b/source/blender/python/api2_2x/doc/Draw.py
index 67d9203b5f5..a3c42c7cdc2 100644
--- a/source/blender/python/api2_2x/doc/Draw.py
+++ b/source/blender/python/api2_2x/doc/Draw.py
@@ -192,7 +192,23 @@ All available events:
- ZEROKEY
- ZKEY
-@note: function Button has a new alias: L{PushButton}.
+@note: function Button has an alias: L{PushButton}.
+
+@warn: B{very important}: if using your script causes "Error totblock"
+messages when Blender exits (meaning that memory has been leaked), this may
+have been caused by an ignored return value from one of the button types. To
+avoid this, assign created buttons return values to B{global} variables,
+instead of ignoring them. Examples::
+
+ # avoid this, it can cause memory leaks:
+ Draw.Toggle(...)
+ Draw.Number(...)
+ Draw.String(...)
+ # this is correct -- assuming the variables are globals:
+ my_toggle_button = Draw.Toggle(...)
+ my_int_button = Draw.Number(...)
+ my_str_button = Draw.String(...)
+
@warn: Inside the windowing loop (after Draw.Register() has been executed and
before Draw.Exit() is called), don't use the redraw functions from other
@@ -484,36 +500,36 @@ def Slider(name, event, x, y, width, height, initial, min, max, realtime = 1,
@return: The Button created.
"""
-def Scrollbar(event, x, y, width, height, initial, min, max, realtime = 1,
- tooltip = None):
- """
- Create a new Scrollbar Button object.
- @type event: int
- @param event: The event number to pass to the button event function when
- activated.
- @type x: int
- @type y: int
- @param x: The lower left x (horizontal) coordinate of the button.
- @param y: The lower left y (vertical) coordinate of the button.
- @type width: int
- @type height: int
- @param width: The button width.
- @param height: The button height.
- @type initial: int or float
- @type min: int or float
- @type max: int or float
- @param initial: The initial value.
- @param min: The minimum value.
- @param max: The maximum value.
- @type realtime: int
- @param realtime: If non-zero (the default), the slider will emit events as
- it is edited.
- @type tooltip: string
- @param tooltip: The button's tooltip (the string that appears when the mouse
- is kept over the button).
- @rtype: Blender Button
- @return: The Button created.
- """
+#def Scrollbar(event, x, y, width, height, initial, min, max, realtime = 1,
+# tooltip = None):
+# """
+# Create a new Scrollbar Button object.
+# @type event: int
+# @param event: The event number to pass to the button event function when
+# activated.
+# @type x: int
+# @type y: int
+# @param x: The lower left x (horizontal) coordinate of the button.
+# @param y: The lower left y (vertical) coordinate of the button.
+# @type width: int
+# @type height: int
+# @param width: The button width.
+# @param height: The button height.
+# @type initial: int or float
+# @type min: int or float
+# @type max: int or float
+# @param initial: The initial value.
+# @param min: The minimum value.
+# @param max: The maximum value.
+# @type realtime: int
+# @param realtime: If non-zero (the default), the slider will emit events as
+# it is edited.
+# @type tooltip: string
+# @param tooltip: The button's tooltip (the string that appears when the mouse
+# is kept over the button).
+# @rtype: Blender Button
+# @return: The Button created.
+# """
def Number(name, event, x, y, width, height, initial, min, max, tooltip = None):
"""
diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py
index cdb5beb1f19..1dc8ee4413e 100644
--- a/source/blender/python/api2_2x/doc/Object.py
+++ b/source/blender/python/api2_2x/doc/Object.py
@@ -804,11 +804,11 @@ class Property:
"""
Set the the Object's Particle Interaction type.
Use Module Constants
- NONE
- WIND
- FORCE
- VORTEX
- MAGNET
+ - NONE
+ - WIND
+ - FORCE
+ - VORTEX
+ - MAGNET
@rtype: PyNone
@type type: int
@param type: the Object's Particle Interaction Type.
@@ -902,7 +902,7 @@ class Property:
Values between 0 to 50.0
@rtype: PyNone
@type mass: float
- @param damp: the Object's SB New mass.
+ @param mass: the Object's SB New mass.
"""
def getSBGravity():
@@ -917,7 +917,7 @@ class Property:
Values between 0 to 10.0
@rtype: PyNone
@type grav: float
- @param damp: the Object's SB New Gravity.
+ @param grav: the Object's SB New Gravity.
"""
def getSBFriction():
@@ -932,7 +932,7 @@ class Property:
Values between 0 to 10.0
@rtype: PyNone
@type frict: float
- @param damp: the Object's SB New Friction.
+ @param frict: the Object's SB New Friction.
"""
def getSBErrorLimit():
@@ -947,7 +947,7 @@ class Property:
Values between 0 to 1.0
@rtype: PyNone
@type err: float
- @param damp: the Object's SB New ErrorLimit.
+ @param err: the Object's SB New ErrorLimit.
"""
def getSBGoalSpring():
@@ -962,7 +962,7 @@ class Property:
Values between 0 to 0.999
@rtype: PyNone
@type gs: float
- @param damp: the Object's SB New GoalSpring.
+ @param gs: the Object's SB New GoalSpring.
"""
def getSBGoalFriction():
@@ -977,7 +977,7 @@ class Property:
Values between 0 to 10.0
@rtype: PyNone
@type gf: float
- @param damp: the Object's SB New GoalFriction.
+ @param gf: the Object's SB New GoalFriction.
"""
def getSBMinGoal():
@@ -992,7 +992,7 @@ class Property:
Values between 0 to 1.0
@rtype: PyNone
@type mg: float
- @param damp: the Object's SB New MinGoal.
+ @param mg: the Object's SB New MinGoal.
"""
def getSBMaxGoal():
@@ -1007,7 +1007,7 @@ class Property:
Values between 0 to 1.0
@rtype: PyNone
@type mg: float
- @param damp: the Object's SB New MaxGoal.
+ @param mg: the Object's SB New MaxGoal.
"""
def getSBInnerSpring():
@@ -1021,8 +1021,8 @@ class Property:
Set the the Object's SB InnerSpring.
Values between 0 to 0.999
@rtype: PyNone
- @type spr: float
- @param damp: the Object's SB New InnerSpring.
+ @type sprr: float
+ @param sprr: the Object's SB New InnerSpring.
"""
def getSBInnerSpringFriction():
@@ -1037,7 +1037,7 @@ class Property:
Values between 0 to 10.0
@rtype: PyNone
@type sprf: float
- @param damp: the Object's SB New InnerSpringFriction.
+ @param sprf: the Object's SB New InnerSpringFriction.
"""
def getSBDefaultGoal():
@@ -1052,7 +1052,7 @@ class Property:
Values between 0 to 1.0
@rtype: PyNone
@type goal: float
- @param damp: the Object's SB New DefaultGoal.
+ @param goal: the Object's SB New DefaultGoal.
"""
def getSBEnable():
@@ -1068,7 +1068,7 @@ class Property:
0: off
@rtype: PyNone
@type switch: int
- @param damp: the Object's SB New Enable Value.
+ @param switch: the Object's SB New Enable Value.
"""
def getSBPostDef():
@@ -1084,7 +1084,7 @@ class Property:
0: off
@rtype: PyNone
@type switch: int
- @param damp: the Object's SB New PostDef Value.
+ @param switch: the Object's SB New PostDef Value.
"""
def getSBUseGoal():
@@ -1100,7 +1100,7 @@ class Property:
0: off
@rtype: PyNone
@type switch: int
- @param damp: the Object's SB New UseGoal Value.
+ @param switch: the Object's SB New UseGoal Value.
"""
def getSBUseEdges():
"""
@@ -1115,7 +1115,7 @@ class Property:
0: off
@rtype: PyNone
@type switch: int
- @param damp: the Object's SB New UseEdges Value.
+ @param switch: the Object's SB New UseEdges Value.
"""
def getSBStiffQuads():
@@ -1131,5 +1131,5 @@ class Property:
0: off
@rtype: PyNone
@type switch: int
- @param damp: the Object's SB New StiffQuads Value.
+ @param switch: the Object's SB New StiffQuads Value.
"""
diff --git a/source/blender/python/api2_2x/doc/Registry.py b/source/blender/python/api2_2x/doc/Registry.py
index 390669eb37d..5913505f4e4 100644
--- a/source/blender/python/api2_2x/doc/Registry.py
+++ b/source/blender/python/api2_2x/doc/Registry.py
@@ -3,6 +3,8 @@
"""
The Blender.Registry submodule.
+B{New}: L{GetKey} and L{SetKey} can respectively load and save data to disk now.
+
Registry
========
@@ -17,19 +19,19 @@ give script authors a way around this limitation.
In Python terms, the Registry holds a dictionary of dictionaries.
You should use it to save Python objects only, not BPython (Blender Python)
objects -- but you can save BPython object names, since those are strings.
-Also, if you need to save a considerable amount of data, please save to a
-file instead. There's no need to keep huge blocks of memory around when they
-can simply be read from a file.
+Also, if you need to save a considerable amount of data, we recommend saving
+it to a file instead. There's no need to keep huge blocks of memory around when
+they can simply be read from a file.
+
+Examples of what this module can be used for:
-Two uses for this module:
+a) Saving data from a script that another script will need to access later.
-a) To save data from a script that another script will need to access later.
+b) Saving configuration data for a script. Users can view and edit this data
+using the "Scripts Configuration Editor" script, then.
-b) To save configuration data from your script's gui (button values) so that the
-next time the user runs your script, the changes will still be there. Later we
-can make Blender save the Registry so that its data won't be lost after users
-quit the program. And also add an option to save as a Text that can be kept in
-a .blend file, letting users keep script data there.
+c) Saving configuration data from your script's gui (button values) so that the
+next time the user runs your script, the changes will still be there.
Example::
@@ -42,12 +44,12 @@ Example::
mystr = "hello"
# then check if they are already at the Registry (saved on a
- # previous execution of this script):
- dict = Registry.GetKey('MyScript')
- if dict: # if found, get the values saved there
- myvar1 = dict['myvar1']
- myvar2 = dict['myvar2']
- mystr = dict['mystr']
+ # previous execution of this script) or on disk:
+ rdict = Registry.GetKey('MyScript', True)
+ if rdict: # if found, get the values saved there
+ myvar1 = rdict['myvar1']
+ myvar2 = rdict['myvar2']
+ mystr = rdict['mystr']
# let's create a function to update the Registry when we need to:
def update_Registry():
@@ -55,7 +57,8 @@ Example::
d['myvar1'] = myvar1
d['myvar2'] = myvar2
d['mystr'] = mystr
- Blender.Registry.SetKey('MyScript', d)
+ # cache = True: data is also saved to a file
+ Blender.Registry.SetKey('MyScript', d, True)
# ...
# here goes the main part of the script ...
@@ -72,21 +75,29 @@ def Keys ():
Get all keys currently in the Registry's dictionary.
"""
-def GetKey (key):
+def GetKey (key, cached = False):
"""
Get key 'key' from the Registry.
@type key: string
@param key: a key from the Registry dictionary.
+ @type cached: bool
+ @param cached: if True and the requested key isn't already loaded in the
+ Registry, it will also be searched on the user or default scripts config
+ data dir (config subdir in L{Blender.Get}('datadir')).
@return: the dictionary called 'key'.
"""
-def SetKey (key, dict):
+def SetKey (key, dict, cache = False):
"""
Store a new entry in the Registry.
@type key: string
@param key: the name of the new entry, tipically your script's name.
@type dict: dictionary
@param dict: a dict with all data you want to save in the Registry.
+ @type cache: bool
+ @param cache: if True the given key data will also be saved as a file
+ in the config subdir of the scripts user or default data dir (see
+ L{Blender.Get}.
"""
def RemoveKey (key):
diff --git a/source/blender/python/api2_2x/doc/Render.py b/source/blender/python/api2_2x/doc/Render.py
index 61454cfab53..fc1d2e53266 100644
--- a/source/blender/python/api2_2x/doc/Render.py
+++ b/source/blender/python/api2_2x/doc/Render.py
@@ -3,8 +3,8 @@
"""
The Blender.Scene.Render submodule.
-Scene
-=====
+Scene.Render
+============
This module provides access to B{Scene Rendering Contexts} in Blender.
diff --git a/source/blender/python/api2_2x/doc/Sys.py b/source/blender/python/api2_2x/doc/Sys.py
index 7536296d0ff..8d9ecf0eb46 100644
--- a/source/blender/python/api2_2x/doc/Sys.py
+++ b/source/blender/python/api2_2x/doc/Sys.py
@@ -6,7 +6,7 @@ The Blender.sys submodule.
sys
===
-B{New}: L{exists}, L{makename}, L{join}, L{sleep}.
+B{New}: L{expandpath}.
This module provides a minimal set of helper functions and data. Its purpose
is to avoid the need for the standard Python module 'os', in special 'os.path',
@@ -137,3 +137,22 @@ def sleep (millisecs = 10):
@param millisecs: the amount of time in milliseconds to sleep. The default
is 10 which is 0.1 seconds.
"""
+
+def expandpath (path):
+ """
+ Expand the given Blender 'path' into an absolute and valid path.
+ Internally, Blender recognizes two special character sequences in paths:
+ - '//' (used at the beginning): means base path -- the current .blend file's
+ dir;
+ - '#' (used at the end): means current frame number.
+ The expanded string can be passed to generic python functions that don't
+ understand Blender's internal relative paths.
+ @note: this function is also useful for obtaining the name of the image
+ that will be saved when rendered.
+ @note: if the passed string doesn't contain the special characters it is
+ returned unchanged.
+ @type path: string
+ @param path: a path name.
+ @rtype: string
+ @return: the expanded (if necessary) path.
+ """