BPython bug fixes:
- #2781, reported by Ed Blake: crash on undo when there were active space handlers. Space Handler script links belong to screen areas, which do not get saved on undo. Thanks Ton for pointing out the function that restores ui pointers gone bad. - Applied patch #2822 by Ken Hughes for bug #2647 ("Setting a Face UV"), reported by Campbell Barton. - #3022, reported by Timothy Wakeham: "Blender.BGL.glDrawPixels crashes when drawing more pixels then buffer size". Made glDrawPixels check buffer dimensions. - #2882, reported by Campbell: crash in nmesh.getMaterials(arg == 0 or 1) when nmesh came from GetRawFromMesh(). Raw nmeshes are not linked to Blender meshes, so the method doesn't support these options (getting mat info from the actual mesh) for it. - #2817, reported by Tod Koeckeritz: Dir_Depth var was not being decremented in BPY_Menus.c, causing dir depth limits to be reached prematurely. - #2954, reported by Daniel Holtz: "Python scripts crash hard with valid windows paths". Blender.Load() was not meant for background mode, now it's been update to support it, using BKE_read_file instead of BIF_read_file in this case. Also found another issue with command line scripts using Blender.Load() that could crash Blender: trying to free the Text when it wasn't available anymore (loading a new .blend already removed it). There are still issues with one case, though, causing a crash on start or "Memoryblock winopen: double free" at end, when running a script that is already a Blender Text (only if the script calls Blender.Load, of course). Will investigate. - #2897: reported by Timothy Wakeham: object.setMaterials was asking the length of a Python list w/o confirming first if the passed obj was really a list. Thanks all for the help and for being patient (long delay, again).
This commit is contained in:
@@ -2855,6 +2855,16 @@ void lib_link_screen_restore(Main *newmain, Scene *curscene)
|
|||||||
while(sa) {
|
while(sa) {
|
||||||
SpaceLink *sl;
|
SpaceLink *sl;
|
||||||
|
|
||||||
|
if (sa->scriptlink.totscript) {
|
||||||
|
/* restore screen area script links */
|
||||||
|
ScriptLink *slink = &sa->scriptlink;
|
||||||
|
int script_idx;
|
||||||
|
for (script_idx = 0; script_idx < slink->totscript; script_idx++) {
|
||||||
|
slink->scripts[script_idx] = restore_pointer_by_name(newmain,
|
||||||
|
(ID *)slink->scripts[script_idx], 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (sl= sa->spacedata.first; sl; sl= sl->next) {
|
for (sl= sa->spacedata.first; sl; sl= sl->next) {
|
||||||
if(sl->spacetype==SPACE_VIEW3D) {
|
if(sl->spacetype==SPACE_VIEW3D) {
|
||||||
View3D *v3d= (View3D*) sl;
|
View3D *v3d= (View3D*) sl;
|
||||||
|
|||||||
@@ -566,7 +566,8 @@ int BPY_txt_do_python_Text( struct Text *text )
|
|||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Description: Called from command line to run a Python script
|
* Description: Called from command line to run a Python script
|
||||||
* automatically.
|
* automatically. The script can be a file or a Blender Text in the current
|
||||||
|
* .blend.
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void BPY_run_python_script( char *fn )
|
void BPY_run_python_script( char *fn )
|
||||||
{
|
{
|
||||||
@@ -606,7 +607,19 @@ void BPY_run_python_script( char *fn )
|
|||||||
"%s (at line %d).\n", fn, BPY_Err_getLinenumber());
|
"%s (at line %d).\n", fn, BPY_Err_getLinenumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_blender_text) free_libblock(&G.main->text, text);
|
if (!is_blender_text) {
|
||||||
|
/* We can't simply free the text, since the script might have called
|
||||||
|
* Blender.Load() to load a new .blend, freeing previous data.
|
||||||
|
* So we check if the pointer is still valid. */
|
||||||
|
Text *txtptr = G.main->text.first;
|
||||||
|
while (txtptr) {
|
||||||
|
if (txtptr == text) {
|
||||||
|
free_libblock(&G.main->text, text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
txtptr = txtptr->id.next;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
|||||||
@@ -874,6 +874,7 @@ static int bpymenu_ParseDir(char *dirname, char *parentdir, int is_userdir )
|
|||||||
closedir(dir);
|
closedir(dir);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Dir_Depth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -423,9 +423,33 @@ static PyObject *Buffer_repr(PyObject *self)
|
|||||||
return repr;
|
return repr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BGL_Wrap defined in BGL.h */
|
/* Not a macro so that buffer dimensions are checked.
|
||||||
|
* XXX There are other places where buffers are used, so a new macro to handle
|
||||||
|
* all such cases may be a good idea. */
|
||||||
|
static PyObject *Method_DrawPixels (PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
int bgl_var1, bgl_var2, bgl_var3, bgl_var4;
|
||||||
|
Buffer *bgl_buffer5;
|
||||||
|
int i, bufsize;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "i" "i" "i" "i" "O!",
|
||||||
|
&bgl_var1, &bgl_var2, &bgl_var3, &bgl_var4, &buffer_Type, &bgl_buffer5))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bufsize = 1;
|
||||||
|
for (i = 0; i < bgl_buffer5->ndimensions; i++)
|
||||||
|
bufsize *= bgl_buffer5->dimensions[i];
|
||||||
|
|
||||||
|
if (bgl_var1*bgl_var2 > bufsize)
|
||||||
|
return EXPP_ReturnPyObjError(PyExc_AttributeError,
|
||||||
|
"pixel buffer size can't be smaller than drawing rect area");
|
||||||
|
|
||||||
|
glDrawPixels (bgl_var1, bgl_var2, bgl_var3, bgl_var4,
|
||||||
|
(bgl_buffer5)->buf.asvoid);
|
||||||
|
|
||||||
|
return EXPP_incr_ret(Py_None);
|
||||||
|
}
|
||||||
|
|
||||||
/* #ifndef __APPLE__ */
|
|
||||||
|
|
||||||
BGL_Wrap(2, Accum, void, (GLenum, GLfloat))
|
BGL_Wrap(2, Accum, void, (GLenum, GLfloat))
|
||||||
BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf))
|
BGL_Wrap(2, AlphaFunc, void, (GLenum, GLclampf))
|
||||||
@@ -487,7 +511,7 @@ BGL_Wrap(1, DepthMask, void, (GLboolean))
|
|||||||
BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd))
|
BGL_Wrap(2, DepthRange, void, (GLclampd, GLclampd))
|
||||||
BGL_Wrap(1, Disable, void, (GLenum))
|
BGL_Wrap(1, Disable, void, (GLenum))
|
||||||
BGL_Wrap(1, DrawBuffer, void, (GLenum))
|
BGL_Wrap(1, DrawBuffer, void, (GLenum))
|
||||||
BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))
|
/*BGL_Wrap(5, DrawPixels, void, (GLsizei, GLsizei, GLenum, GLenum, GLvoidP))*/
|
||||||
BGL_Wrap(1, EdgeFlag, void, (GLboolean))
|
BGL_Wrap(1, EdgeFlag, void, (GLboolean))
|
||||||
BGL_Wrap(1, EdgeFlagv, void, (GLbooleanP))
|
BGL_Wrap(1, EdgeFlagv, void, (GLbooleanP))
|
||||||
BGL_Wrap(1, Enable, void, (GLenum))
|
BGL_Wrap(1, Enable, void, (GLenum))
|
||||||
@@ -759,8 +783,6 @@ BGLU_Wrap(5, PickMatrix, void, (GLdouble, GLdouble, GLdouble, GLdoub
|
|||||||
BGLU_Wrap(9, Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
|
BGLU_Wrap(9, Project, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
|
||||||
BGLU_Wrap(9, UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
|
BGLU_Wrap(9, UnProject, GLint, (GLdouble, GLdouble, GLdouble, GLdoubleP, GLdoubleP, GLintP, GLdoubleP, GLdoubleP, GLdoubleP))
|
||||||
|
|
||||||
/* #endif */
|
|
||||||
|
|
||||||
#undef MethodDef
|
#undef MethodDef
|
||||||
#define MethodDef(func) {"gl"#func, Method_##func, METH_VARARGS, "no string"}
|
#define MethodDef(func) {"gl"#func, Method_##func, METH_VARARGS, "no string"}
|
||||||
#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, "no string"}
|
#define MethodDefu(func) {"glu"#func, Method_##func, METH_VARARGS, "no string"}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ struct ID; /*keep me up here */
|
|||||||
#include "BIF_usiblender.h"
|
#include "BIF_usiblender.h"
|
||||||
#include "BLI_blenlib.h"
|
#include "BLI_blenlib.h"
|
||||||
#include "BLO_writefile.h"
|
#include "BLO_writefile.h"
|
||||||
|
#include "BKE_blender.h"
|
||||||
#include "BKE_exotic.h"
|
#include "BKE_exotic.h"
|
||||||
#include "BKE_global.h"
|
#include "BKE_global.h"
|
||||||
#include "BKE_packedFile.h"
|
#include "BKE_packedFile.h"
|
||||||
@@ -480,7 +481,7 @@ static PyObject *Blender_Load( PyObject * self, PyObject * args )
|
|||||||
|
|
||||||
if( !PyArg_ParseTuple( args, "|si", &fname, &keep_oldfname ) )
|
if( !PyArg_ParseTuple( args, "|si", &fname, &keep_oldfname ) )
|
||||||
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||||
"expected filename and optional int or nothing as arguments" );
|
"expected filename and optional int or nothing as arguments" );
|
||||||
|
|
||||||
if( fname ) {
|
if( fname ) {
|
||||||
if( strlen( fname ) > FILE_MAXDIR ) /* G.main->name's max length */
|
if( strlen( fname ) > FILE_MAXDIR ) /* G.main->name's max length */
|
||||||
@@ -518,6 +519,7 @@ static PyObject *Blender_Load( PyObject * self, PyObject * args )
|
|||||||
is_blend_file = 1; /* no arg given means default: .B.blend */
|
is_blend_file = 1; /* no arg given means default: .B.blend */
|
||||||
|
|
||||||
if( is_blend_file ) {
|
if( is_blend_file ) {
|
||||||
|
|
||||||
int during_slink = during_scriptlink( );
|
int during_slink = during_scriptlink( );
|
||||||
|
|
||||||
/* when loading a .blend file from a scriptlink, the scriptlink pointer
|
/* when loading a .blend file from a scriptlink, the scriptlink pointer
|
||||||
@@ -546,21 +548,32 @@ static PyObject *Blender_Load( PyObject * self, PyObject * args )
|
|||||||
if( G.obedit )
|
if( G.obedit )
|
||||||
exit_editmode( 1 );
|
exit_editmode( 1 );
|
||||||
|
|
||||||
/* for safety, any filename with .B.blend is considered the default one.
|
if (G.background) { /* background mode */
|
||||||
* It doesn't seem necessary to compare file attributes (like st_ino and
|
if (is_blend_file)
|
||||||
* st_dev, according to the glibc info pages) to find out if the given
|
BKE_read_file(fname, NULL);
|
||||||
* filename, that may have been given with a twisted misgiving path, is the
|
else {
|
||||||
* default one for sure. Taking any .B.blend file as the default is good
|
return EXPP_ReturnPyObjError(PyExc_AttributeError,
|
||||||
* enough here. Note: the default file requires extra clean-up done by
|
"only .blend files can be loaded from command line,\n\
|
||||||
* BIF_read_homefile: freeing the user theme data. */
|
other file types require interactive mode.");
|
||||||
if( !fname || ( strstr( fname, ".B.blend" ) && is_blend_file ) )
|
}
|
||||||
BIF_read_homefile( );
|
}
|
||||||
else
|
else { /* interactive mode */
|
||||||
BIF_read_file( fname );
|
/* for safety, any filename with .B.blend is considered the default one.
|
||||||
|
* It doesn't seem necessary to compare file attributes (like st_ino and
|
||||||
|
* st_dev, according to the glibc info pages) to find out if the given
|
||||||
|
* filename, that may have been given with a twisted misgiving path, is the
|
||||||
|
* default one for sure. Taking any .B.blend file as the default is good
|
||||||
|
* enough here. Note: the default file requires extra clean-up done by
|
||||||
|
* BIF_read_homefile: freeing the user theme data. */
|
||||||
|
if( !fname || ( strstr( fname, ".B.blend" ) && is_blend_file ) )
|
||||||
|
BIF_read_homefile( );
|
||||||
|
else
|
||||||
|
BIF_read_file( fname );
|
||||||
|
|
||||||
if( fname && keep_oldfname ) {
|
if( fname && keep_oldfname ) {
|
||||||
/*BLI_strncpy(G.main->name, name, FILE_MAXDIR); */
|
/*BLI_strncpy(G.main->name, name, FILE_MAXDIR); */
|
||||||
BLI_strncpy( G.sce, name, FILE_MAXDIR );
|
BLI_strncpy( G.sce, name, FILE_MAXDIR );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_INCREF( Py_None );
|
Py_INCREF( Py_None );
|
||||||
|
|||||||
@@ -602,7 +602,7 @@ static int NMFace_setattr( PyObject * self, char *name, PyObject * v )
|
|||||||
|
|
||||||
if( strcmp( name, "v" ) == 0 ) {
|
if( strcmp( name, "v" ) == 0 ) {
|
||||||
|
|
||||||
if( PySequence_Check( v ) ) {
|
if( PyList_Check( v ) ) {
|
||||||
Py_DECREF( mf->v );
|
Py_DECREF( mf->v );
|
||||||
mf->v = EXPP_incr_ret( v );
|
mf->v = EXPP_incr_ret( v );
|
||||||
|
|
||||||
@@ -610,7 +610,7 @@ static int NMFace_setattr( PyObject * self, char *name, PyObject * v )
|
|||||||
}
|
}
|
||||||
} else if( strcmp( name, "col" ) == 0 ) {
|
} else if( strcmp( name, "col" ) == 0 ) {
|
||||||
|
|
||||||
if( PySequence_Check( v ) ) {
|
if( PyList_Check( v ) ) {
|
||||||
Py_DECREF( mf->col );
|
Py_DECREF( mf->col );
|
||||||
mf->col = EXPP_incr_ret( v );
|
mf->col = EXPP_incr_ret( v );
|
||||||
|
|
||||||
@@ -642,7 +642,7 @@ static int NMFace_setattr( PyObject * self, char *name, PyObject * v )
|
|||||||
|
|
||||||
} else if( strcmp( name, "uv" ) == 0 ) {
|
} else if( strcmp( name, "uv" ) == 0 ) {
|
||||||
|
|
||||||
if( PySequence_Check( v ) ) {
|
if( PyList_Check( v ) ) {
|
||||||
Py_DECREF( mf->uv );
|
Py_DECREF( mf->uv );
|
||||||
mf->uv = EXPP_incr_ret( v );
|
mf->uv = EXPP_incr_ret( v );
|
||||||
|
|
||||||
@@ -1054,6 +1054,10 @@ static PyObject *NMesh_getMaterials( PyObject * self, PyObject * args )
|
|||||||
"expected nothing or an int (bool) as argument" );
|
"expected nothing or an int (bool) as argument" );
|
||||||
|
|
||||||
if( all >= 0 ) {
|
if( all >= 0 ) {
|
||||||
|
if (!me)
|
||||||
|
return EXPP_ReturnPyObjError(PyExc_TypeError,
|
||||||
|
"meshes obtained with GetRawFromObject don't support this option");
|
||||||
|
|
||||||
list = EXPP_PyList_fromMaterialList( me->mat, me->totcol,
|
list = EXPP_PyList_fromMaterialList( me->mat, me->totcol,
|
||||||
all );
|
all );
|
||||||
Py_DECREF( nm->materials ); /* update nmesh.materials attribute */
|
Py_DECREF( nm->materials ); /* update nmesh.materials attribute */
|
||||||
@@ -1751,7 +1755,7 @@ static int NMesh_setattr( PyObject * self, char *name, PyObject * v )
|
|||||||
else if( !strcmp( name, "verts" ) || !strcmp( name, "faces" ) ||
|
else if( !strcmp( name, "verts" ) || !strcmp( name, "faces" ) ||
|
||||||
!strcmp( name, "materials" ) ) {
|
!strcmp( name, "materials" ) ) {
|
||||||
|
|
||||||
if( PySequence_Check( v ) ) {
|
if( PyList_Check( v ) ) {
|
||||||
|
|
||||||
if( strcmp( name, "materials" ) == 0 ) {
|
if( strcmp( name, "materials" ) == 0 ) {
|
||||||
Py_DECREF( me->materials );
|
Py_DECREF( me->materials );
|
||||||
@@ -1767,7 +1771,7 @@ static int NMesh_setattr( PyObject * self, char *name, PyObject * v )
|
|||||||
|
|
||||||
else
|
else
|
||||||
return EXPP_ReturnIntError( PyExc_TypeError,
|
return EXPP_ReturnIntError( PyExc_TypeError,
|
||||||
"expected a sequence" );
|
"expected a list" );
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( !strcmp( name, "maxSmoothAngle" ) ) {
|
else if( !strcmp( name, "maxSmoothAngle" ) ) {
|
||||||
|
|||||||
@@ -2076,37 +2076,35 @@ static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args )
|
|||||||
int i;
|
int i;
|
||||||
Material **matlist;
|
Material **matlist;
|
||||||
|
|
||||||
if( !PyArg_ParseTuple( args, "O", &list ) ) {
|
if( !PyArg_ParseTuple( args, "O!", &PyList_Type, &list ) )
|
||||||
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||||
|
"expected a list of materials (None's also accepted) as argument" );
|
||||||
|
|
||||||
|
len = PyList_Size(list);
|
||||||
|
|
||||||
|
if( len > MAXMAT )
|
||||||
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||||
|
"list must have from 1 up to 16 materials" );
|
||||||
|
|
||||||
|
matlist = EXPP_newMaterialList_fromPyList( list );
|
||||||
|
if( !matlist ) {
|
||||||
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
|
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
|
||||||
"expected a list of materials as argument" ) );
|
"material list must be a list of valid materials!" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
len = PySequence_Length( list );
|
if( self->object->mat )
|
||||||
if( len > 0 ) {
|
EXPP_releaseMaterialList( self->object->mat, self->object->totcol );
|
||||||
matlist = EXPP_newMaterialList_fromPyList( list );
|
|
||||||
if( !matlist ) {
|
|
||||||
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
||||||
"material list must be a list of valid materials!" ) );
|
|
||||||
}
|
|
||||||
if( ( len < 0 ) || ( len > MAXMAT ) ) {
|
|
||||||
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
|
||||||
"material list should have at least 1, at most 16 entries" ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( self->object->mat ) {
|
/* Increase the user count on all materials */
|
||||||
EXPP_releaseMaterialList( self->object->mat,
|
for( i = 0; i < len; i++ ) {
|
||||||
self->object->totcol );
|
if( matlist[i] )
|
||||||
}
|
id_us_plus( ( ID * ) matlist[i] );
|
||||||
/* Increase the user count on all materials */
|
}
|
||||||
for( i = 0; i < len; i++ ) {
|
self->object->mat = matlist;
|
||||||
if( matlist[i] )
|
self->object->totcol = (char)len;
|
||||||
id_us_plus( ( ID * ) matlist[i] );
|
self->object->actcol = (char)len;
|
||||||
}
|
|
||||||
self->object->mat = matlist;
|
|
||||||
self->object->totcol = (char)len;
|
|
||||||
self->object->actcol = (char)len;
|
|
||||||
|
|
||||||
switch ( self->object->type ) {
|
switch ( self->object->type ) {
|
||||||
case OB_CURVE: /* fall through */
|
case OB_CURVE: /* fall through */
|
||||||
case OB_FONT: /* fall through */
|
case OB_FONT: /* fall through */
|
||||||
case OB_MESH: /* fall through */
|
case OB_MESH: /* fall through */
|
||||||
@@ -2116,7 +2114,6 @@ static PyObject *Object_setMaterials( BPy_Object * self, PyObject * args )
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return EXPP_incr_ret( Py_None );
|
return EXPP_incr_ret( Py_None );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,6 +128,8 @@ def Load (filename = None):
|
|||||||
when this function is used to open .blend files.
|
when this function is used to open .blend files.
|
||||||
@warn: if in edit mode, this function leaves it, since Blender itself
|
@warn: if in edit mode, this function leaves it, since Blender itself
|
||||||
requires that.
|
requires that.
|
||||||
|
@note: for all types except .blend files, this function only works in
|
||||||
|
interactive mode, not in background, following what Blender itself does.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def Save (filename, overwrite = 0):
|
def Save (filename, overwrite = 0):
|
||||||
@@ -177,9 +179,7 @@ def ShowHelp (script):
|
|||||||
@note: this function uses L{Run} and the "Scripts Help Browser" script. This
|
@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
|
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).
|
help for it (otherwise it offers to load the script source code as text).
|
||||||
The necessary information about doc strings is in the
|
The necessary information about doc strings is L{given here<API_related>}.
|
||||||
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: 'script' doesn't need to be a full path name: "filename.py" is enough.
|
||||||
Note, though, that this function only works for properly registered
|
Note, though, that this function only works for properly registered
|
||||||
scripts (those that appear in menus).
|
scripts (those that appear in menus).
|
||||||
|
|||||||
@@ -438,7 +438,7 @@ class NMesh:
|
|||||||
- -1: return the current nmesh's list;
|
- -1: return the current nmesh's list;
|
||||||
- 0: retrieve a fresh list from the Blender mesh -- eventual
|
- 0: retrieve a fresh list from the Blender mesh -- eventual
|
||||||
modifications made by the script not included, unless
|
modifications made by the script not included, unless
|
||||||
L{NMesh.update}d is called before this method;
|
L{NMesh.update} is called before this method;
|
||||||
- 1: like 0, but empty slots are not ignored, they are returned as
|
- 1: like 0, but empty slots are not ignored, they are returned as
|
||||||
None's.
|
None's.
|
||||||
@note: what >= 0 also updates nmesh.materials attribute.
|
@note: what >= 0 also updates nmesh.materials attribute.
|
||||||
|
|||||||
Reference in New Issue
Block a user