BPython bug fixes:

- bug #2033 reported by Ken Hughes: Vertices of mesh parented to lattice is scaled incorrectly:
https://projects.blender.org/tracker/?func=detail&aid=2033&group_id=9&atid=125

- bug #2211 reported by German Alonso Tamayo (servivo): Add a vertex to a mesh with groups using a script and then edit that mesh hangs blender:
https://projects.blender.org/tracker/index.php?func=detail&aid=2211&group_id=9&atid=125

(#2211's hang was already fixed with previous commit, but this way should work better)

- doc updates (Ken reported missing info about Render slinks, thanks).
This commit is contained in:
2005-05-22 07:22:34 +00:00
parent ae2acbf49b
commit 2f3dbcc5b7
10 changed files with 103 additions and 23 deletions

View File

@@ -96,7 +96,7 @@ static PyObject *Lattice_setMode( BPy_Lattice * self, PyObject * args );
static PyObject *Lattice_getMode( BPy_Lattice * self, PyObject * args );
static PyObject *Lattice_setPoint( BPy_Lattice * self, PyObject * args );
static PyObject *Lattice_getPoint( BPy_Lattice * self, PyObject * args );
static PyObject *Lattice_applyDeform( BPy_Lattice * self );
static PyObject *Lattice_applyDeform( BPy_Lattice * self, PyObject *args );
static PyObject *Lattice_insertKey( BPy_Lattice * self, PyObject * args );
/*****************************************************************************/
@@ -132,7 +132,12 @@ static char Lattice_getPoint_doc[] =
"(str) - Get the coordinates of a point on the lattice";
static char Lattice_applyDeform_doc[] =
"(str) - Apply the new lattice deformation to children";
"(force = False) - Apply the new lattice deformation to children\n\n\
(force = False) - if given and True, children of mesh type are not ignored.\n\
Meshes are treated differently in Blender, deformation is stored directly in\n\
their vertices when first redrawn (ex: with Blender.Redraw) after getting a\n\
Lattice parent, without needing this method (except for command line bg\n\
mode). If forced, the deformation will be applied over any previous one(s).";
static char Lattice_insertKey_doc[] =
"(str) - Set a new key for the lattice at specified frame";
@@ -162,7 +167,7 @@ static PyMethodDef BPy_Lattice_methods[] = {
Lattice_setPoint_doc},
{"getPoint", ( PyCFunction ) Lattice_getPoint, METH_VARARGS,
Lattice_getPoint_doc},
{"applyDeform", ( PyCFunction ) Lattice_applyDeform, METH_NOARGS,
{"applyDeform", ( PyCFunction ) Lattice_applyDeform, METH_VARARGS,
Lattice_applyDeform_doc},
{"insertKey", ( PyCFunction ) Lattice_insertKey, METH_VARARGS,
Lattice_insertKey_doc},
@@ -675,22 +680,35 @@ static PyObject *Lattice_getPoint( BPy_Lattice * self, PyObject * args )
}
//This function will not do anything if there are no children
static PyObject *Lattice_applyDeform( BPy_Lattice * self )
static PyObject *Lattice_applyDeform( BPy_Lattice * self, PyObject *args )
{
//Object* ob; unused
Base *base;
Object *par;
int forced = 0;
if( !Lattice_IsLinkedToObject( self ) )
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"Lattice must be linked to an object to apply it's deformation!" ) );
if( !PyArg_ParseTuple( args, "|i", &forced ) )
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"expected nothing or True or False argument" ) );
/* deform children */
base = FIRSTBASE;
while( base ) {
if( ( par = base->object->parent ) ) { /* checking if object has a parent, assigning if so */
if((par->type == OB_LATTICE) && (self->Lattice == par->data)) {
object_deform( base->object );
if( ( par = base->object->parent ) ) { /* check/assign if ob has parent */
/* meshes have their mverts deformed, others ob types use displist,
* so we're not doing meshes here (unless forced), or else they get
* deformed twice, since parenting a Lattice to an object and redrawing
* already applies lattice deformation. 'forced' is useful for
* command line background mode, when no redraws occur and so this
* method is needed. Or for users who actually want to apply the
* deformation n times. */
if((self->Lattice == par->data)) {
if ((base->object->type != OB_MESH) || forced)
object_deform( base->object );
}
}
base = base->next;

View File

@@ -93,6 +93,7 @@ static PyObject *g_nmeshmodule = NULL;
static int unlink_existingMeshData( Mesh * mesh );
static int convert_NMeshToMesh( Mesh *mesh, BPy_NMesh *nmesh, int store_edges );
static void check_dverts(Mesh *me, int old_totverts);
static PyObject *NMesh_printDebug( PyObject * self );
static PyObject *NMesh_addEdge( PyObject * self, PyObject * args );
static PyObject *NMesh_findEdge( PyObject * self, PyObject * args );
@@ -1292,6 +1293,7 @@ static PyObject *NMesh_update( PyObject *self, PyObject *a, PyObject *kwd )
static char *kwlist[] = {"recalc_normals", "store_edges",
"vertex_shade", NULL};
int needs_redraw = 1;
int old_totvert = 0;
if (!PyArg_ParseTupleAndKeywords(a, kwd, "|iii", kwlist, &recalc_normals,
&store_edges, &vertex_shade ) )
@@ -1299,8 +1301,10 @@ static PyObject *NMesh_update( PyObject *self, PyObject *a, PyObject *kwd )
"expected nothing or one to three bool(s) (0 or 1) as argument" );
if( mesh ) {
old_totvert = mesh->totvert;
unlink_existingMeshData( mesh );
convert_NMeshToMesh( mesh, nmesh, store_edges );
if (mesh->dvert) check_dverts(mesh, old_totvert);
} else {
nmesh->mesh = Mesh_fromNMesh( nmesh, store_edges );
mesh = nmesh->mesh;
@@ -2411,8 +2415,6 @@ static int unlink_existingMeshData( Mesh * mesh )
{
freedisplist( &mesh->disp );
EXPP_unlink_mesh( mesh );
if( mesh->dvert )
free_dverts( mesh->dvert, mesh->totvert );
if( mesh->mvert )
MEM_freeN( mesh->mvert );
if( mesh->medge ) {
@@ -2601,6 +2603,39 @@ static void fill_medge_from_nmesh(Mesh * mesh, BPy_NMesh * nmesh)
MEM_freeN( faces_edges );
}
/* this should ensure meshes don't end up with wrongly sized
* me->dvert arrays, which can cause hangs; it's not ideal,
* it's better to wrap dverts in NMesh, but it should do for now
* since there are also methods in NMesh to edit dverts in the actual
* mesh in Blender and anyway this is memory friendly */
static void check_dverts(Mesh *me, int old_totvert)
{
int totvert = me->totvert;
/* if vert count didn't change or there are no dverts, all is fine */
if ((totvert == old_totvert) || (!me->dvert)) return;
/* if all verts have been deleted, free old dverts */
else if (totvert == 0) free_dverts(me->dvert, old_totvert);
/* if verts have been added, expand me->dvert */
else if (totvert > old_totvert) {
MDeformVert *mdv = me->dvert;
me->dvert = NULL;
create_dverts(me);
copy_dverts(me->dvert, mdv, old_totvert);
free_dverts(mdv, old_totvert);
}
/* if verts have been deleted, shrink me->dvert */
else {
MDeformVert *mdv = me->dvert;
me->dvert = NULL;
create_dverts(me);
copy_dverts(me->dvert, mdv, totvert);
free_dverts(mdv, old_totvert);
}
return;
}
static int convert_NMeshToMesh( Mesh * mesh, BPy_NMesh * nmesh, int store_edges)
{
MFace *newmf;
@@ -2782,6 +2817,7 @@ static PyObject *M_NMesh_PutRaw( PyObject * self, PyObject * args )
BPy_NMesh *nmesh;
int recalc_normals = 1;
int store_edges = 0;
int old_totvert = 0;
if( !PyArg_ParseTuple( args, "O!|sii",
&NMesh_Type, &nmesh, &name, &recalc_normals, &store_edges ) )
@@ -2830,10 +2866,14 @@ static PyObject *M_NMesh_PutRaw( PyObject * self, PyObject * args )
new_id( &( G.main->mesh ), &mesh->id,
PyString_AsString( nmesh->name ) );
old_totvert = mesh->totvert;
unlink_existingMeshData( mesh );
convert_NMeshToMesh( mesh, nmesh, store_edges );
nmesh->mesh = mesh;
if (mesh->dvert) check_dverts(mesh, old_totvert);
if( recalc_normals )
vertexnormals_mesh( mesh, 0 );

View File

@@ -1553,6 +1553,12 @@ static PyObject *Object_makeParent( BPy_Object * self, PyObject * args )
"expected a list of objects" ) );
}
parent = ( Object * ) self->object;
if (parent->id.us == 0)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"object must be linked to a scene before it can become a parent");
/* Check if the PyObject passed in list is a Blender object. */
for( i = 0; i < PySequence_Length( list ); i++ ) {
child = NULL;
@@ -1561,12 +1567,13 @@ static PyObject *Object_makeParent( BPy_Object * self, PyObject * args )
child = ( Object * ) Object_FromPyObject( py_child );
if( child == NULL ) {
Py_DECREF (py_child);
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
"Object Type expected" ) );
}
parent = ( Object * ) self->object;
if( test_parent_loop( parent, child ) ) {
Py_DECREF (py_child);
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
"parenting loop detected - parenting failed" ) );
}
@@ -1587,7 +1594,7 @@ static PyObject *Object_makeParent( BPy_Object * self, PyObject * args )
sort_baselist( G.scene );
}
// We don't need the child object anymore.
//Py_DECREF ((PyObject *) child);
Py_DECREF (py_child);
}
return EXPP_incr_ret( Py_None );
}

View File

@@ -752,7 +752,7 @@ static PyObject *Scene_link( BPy_Scene * self, PyObject * args )
/* not linked, go get mem for a new base object */
base = MEM_callocN( sizeof( Base ), "newbase" );
base = MEM_callocN( sizeof( Base ), "pynewbase" );
if( !base )
return EXPP_ReturnPyObjError( PyExc_MemoryError,

View File

@@ -205,7 +205,7 @@ class Camera:
"""
Get a list with this Camera's script links of type 'event'.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw" or "Render".
@rtype: list
@return: a list with Blender L{Text} names (the script links of the given
'event' type) or None if there are no script links at all.
@@ -225,7 +225,7 @@ class Camera:
@type text: string
@param text: the name of an existing Blender L{Text}.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw" or "Render".
"""
def insertIpoKey(keytype):

View File

@@ -329,7 +329,7 @@ class Lamp:
"""
Get a list with this Lamp's script links of type 'event'.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw" or "Render".
@rtype: list
@return: a list with Blender L{Text} names (the script links of the given
'event' type) or None if there are no script links at all.
@@ -349,7 +349,7 @@ class Lamp:
@type text: string
@param text: the name of an existing Blender L{Text}.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw" or "Render".
"""
def getIpo():

View File

@@ -171,10 +171,22 @@ class Lattice:
@param position: The x,y,z coordinates that you want the point to be: [x,y,z]
"""
def applyDeform():
def applyDeform(force = False):
"""
@type force: bool
@param force: if True, meshes are not ignored.
Applies the current Lattice deformation to any child objects that have this
Lattice as the parent.
@note: simply parenting to a Lattice and redrawing the screen is enough to
get the deformation done, this applyDeform method is useful when the
script won't call a redraw, like in command line background (GUI-less)
mode.
@note: by default, this method doesn't apply deformations to meshes. This
is because unlike other kinds of objects, meshes store lattice
deformation directly in their vertices and calling this applyDeform
method will apply the deformation a second time, giving double
deformation, which can be a feature (set force = True if you want it) or
much probably an undesired effect.
"""
def insertKey(frame):

View File

@@ -443,6 +443,9 @@ class Object:
0 - update scene hierarchy automatically
1 - don't update scene hierarchy (faster). In this case, you must
explicitely update the Scene hierarchy.
@warn: objects must first be linked to a scene before they can become
parents of other objects. Calling this makeParent method for an
unlinked object will result in an error.
"""
def setDeltaLocation(delta_location):
@@ -595,7 +598,7 @@ class Object:
"""
Get a list with this Object's script links of type 'event'.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw" or "Render".
@rtype: list
@return: a list with Blender L{Text} names (the script links of the given
'event' type) or None if there are no script links at all.
@@ -615,7 +618,7 @@ class Object:
@type text: string
@param text: the name of an existing Blender L{Text}.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw" or "Render".
"""
def makeTrack (tracked, fast = 0):

View File

@@ -236,7 +236,7 @@ class Scene:
"""
Get a list with this Scene's script links of type 'event'.
@type event: string
@param event: "FrameChanged", "OnLoad", "OnSave" or "Redraw".
@param event: "FrameChanged", "OnLoad", "OnSave", "Redraw" or "Render".
@rtype: list
@return: a list with Blender L{Text} names (the script links of the given
'event' type) or None if there are no script links at all.
@@ -256,7 +256,7 @@ class Scene:
@type text: string
@param text: the name of an existing Blender L{Text}.
@type event: string
@param event: "FrameChanged", "OnLoad", "OnSave" or "Redraw".
@param event: "FrameChanged", "OnLoad", "OnSave", "Redraw" or "Render".
"""
def play (mode = 0, win = '<VIEW3D>'):

View File

@@ -293,7 +293,7 @@ class World:
"""
Get a list with this World's script links of type 'event'.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw", "Render".
@rtype: list
@return: a list with Blender L{Text} names (the script links of the given
'event' type) or None if there are no script links at all.
@@ -313,7 +313,7 @@ class World:
@type text: string
@param text: the name of an existing Blender L{Text}.
@type event: string
@param event: "FrameChanged" or "Redraw".
@param event: "FrameChanged", "Redraw" or "Render".
"""
def setCurrent ():