* got rid of a warning in editipo.c:

changed "get_ipo(key, ..." to "get_ipo((ID *)key, ..." in line 107.
* changed insert_meshkey(Mesh *me) to insert_meshkey(Mesh *me, short offline):
   To call this function from a script, so that it doesn't pop the
   "relative / absolute" dialog window when the "offline" arg is non-zero.

Exppython:

* NMesh module:
   - Added method NMesh.addMaterial(mat) to the NMesh module:
   alternative safer (aka slower) way to add materials.
   - Added optional arg to NMesh_update():
   if given and equal to 1, the mesh normals are recalculated.
   - Fixed NMesh.getVertexInfluences: it was segfaulting when a NULL bone was
   linked to the vertex.  Thanks to Jiba on the bf-python mailing list for
   bug report and sample .blend file.  Also made this method give an IndexError
   when the vertex index is out of range.
* Material module:
   Added specR, specG, specB vars for compatibility with the 2.25 API.
   Pointed by Manuel Bastioni.
* Image module:
    Exposed image width, height and depth parameters.
    From a suggestion by jms.
* BPython Ref Doc:
  - Small updates to reflect the above additions.
  - Added info for the Bone type in the Armature doc.
This commit is contained in:
Willian Padovani Germano
2003-07-30 21:15:41 +00:00
parent 35c4c3222c
commit fe07b232b7
12 changed files with 376 additions and 42 deletions

View File

@@ -109,7 +109,7 @@ static PyMethodDef BPy_Bone_methods[] = {
{"getQuat", (PyCFunction)Bone_getQuat, METH_NOARGS, "() - return Bone quat"},
{"getParent", (PyCFunction)Bone_hasParent, METH_NOARGS,
"() - return the parent bone of this one if it exists."
" Otherwise raise an error. Check this condition with the "
" None if not found. You can check this condition with the "
"hasParent() method."},
{"hasParent", (PyCFunction)Bone_hasParent, METH_NOARGS,
"() - return true if bone has a parent"},

View File

@@ -34,7 +34,7 @@
#include <BKE_library.h>
#include <BKE_image.h>
#include <BLI_blenlib.h>
#include <IMB_imbuf_types.h> /* for the IB_rect define */
#include "gen_utils.h"
#include "Image.h"
@@ -226,6 +226,8 @@ PyObject *Image_Init (void)
/*****************************************************************************/
static PyObject *Image_getName(BPy_Image *self);
static PyObject *Image_getFilename(BPy_Image *self);
static PyObject *Image_getSize(BPy_Image *self);
static PyObject *Image_getDepth(BPy_Image *self);
static PyObject *Image_getXRep(BPy_Image *self);
static PyObject *Image_getYRep(BPy_Image *self);
static PyObject *Image_setName(BPy_Image *self, PyObject *args);
@@ -241,6 +243,10 @@ static PyMethodDef BPy_Image_methods[] = {
"() - Return Image object name"},
{"getFilename", (PyCFunction)Image_getFilename, METH_NOARGS,
"() - Return Image object filename"},
{"getSize", (PyCFunction)Image_getSize, METH_NOARGS,
"() - Return Image object [width, height] dimension in pixels"},
{"getDepth", (PyCFunction)Image_getDepth, METH_NOARGS,
"() - Return Image object pixel depth"},
{"getXRep", (PyCFunction)Image_getXRep, METH_NOARGS,
"() - Return Image object x repetition value"},
{"getYRep", (PyCFunction)Image_getYRep, METH_NOARGS,
@@ -354,6 +360,47 @@ static PyObject *Image_getFilename(BPy_Image *self)
"couldn't get Image.filename attribute"));
}
static PyObject *Image_getSize(BPy_Image *self)
{
PyObject *attr;
Image *image = self->image;
if (!image->ibuf) /* if no image data available */
load_image(image, IB_rect, "", 0); /* loading it */
if (!image->ibuf) /* didn't work */
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"couldn't load image data in Blender");
attr = Py_BuildValue("[hh]", image->ibuf->x, image->ibuf->y);
if (attr) return attr;
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"couldn't get Image.size attribute");
}
static PyObject *Image_getDepth(BPy_Image *self)
{
PyObject *attr;
Image *image = self->image;
if (!image->ibuf) /* if no image data available */
load_image(image, IB_rect, "", 0); /* loading it */
if (!image->ibuf) /* didn't work */
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"couldn't load image data in Blender");
attr = Py_BuildValue("h", image->ibuf->depth);
if (attr) return attr;
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"couldn't get Image.depth attribute");
}
static PyObject *Image_getXRep(BPy_Image *self)
{
PyObject *attr = PyInt_FromLong(self->image->xrep);
@@ -441,14 +488,18 @@ static PyObject *Image_getAttr (BPy_Image *self, char *name)
attr = PyString_FromString(self->image->id.name+2);
else if (strcmp(name, "filename") == 0)
attr = PyString_FromString(self->image->name);
else if (strcmp(name, "size") == 0)
attr = Image_getSize(self);
else if (strcmp(name, "depth") == 0)
attr = Image_getDepth(self);
else if (strcmp(name, "xrep") == 0)
attr = PyInt_FromLong(self->image->xrep);
else if (strcmp(name, "yrep") == 0)
attr = PyInt_FromLong(self->image->yrep);
else if (strcmp(name, "__members__") == 0)
attr = Py_BuildValue("[s,s,s,s]",
"name", "filename", "xrep", "yrep");
attr = Py_BuildValue("[s,s,s,s,s,s]",
"name", "filename", "size", "depth", "xrep", "yrep");
if (!attr)
return (EXPP_ReturnPyObjError (PyExc_MemoryError,

View File

@@ -583,6 +583,16 @@ int Material_CheckPyObject (PyObject *pyobj)
return (pyobj->ob_type == &Material_Type);
}
/*****************************************************************************/
/* Function: Material_FromPyObject */
/* Description: This function returns the Blender material from the given */
/* PyObject. */
/*****************************************************************************/
Material *Material_FromPyObject (PyObject *pyobj)
{
return ((BPy_Material *)pyobj)->material;
}
/*****************************************************************************/
/* Description: Returns the object with the name specified by the argument */
/* name. Note that the calling function has to remove the first */
@@ -988,6 +998,12 @@ static PyObject *Material_setColorComponent(BPy_Material *self, char *key,
self->material->g = value;
else if (!strcmp(key, "B"))
self->material->b = value;
else if (!strcmp(key, "specR"))
self->material->specr = value;
else if (!strcmp(key, "specG"))
self->material->specg = value;
else if (!strcmp(key, "specB"))
self->material->specb = value;
return EXPP_incr_ret (Py_None);
}
@@ -1287,6 +1303,12 @@ static PyObject *Material_getAttr (BPy_Material *self, char *name)
attr = PyFloat_FromDouble((double)self->material->g);
else if (strcmp(name, "B") == 0)
attr = PyFloat_FromDouble((double)self->material->b);
else if (strcmp(name, "specR") == 0)
attr = PyFloat_FromDouble((double)self->material->specr);
else if (strcmp(name, "specG") == 0)
attr = PyFloat_FromDouble((double)self->material->specg);
else if (strcmp(name, "specB") == 0)
attr = PyFloat_FromDouble((double)self->material->specb);
else if (strcmp(name, "amb") == 0)
attr = PyFloat_FromDouble((double)self->material->amb);
else if (strcmp(name, "emit") == 0)
@@ -1389,6 +1411,12 @@ static int Material_setAttr (BPy_Material *self, char *name, PyObject *value)
error = Material_setColorComponent (self, "G", valtuple);
else if (strcmp (name, "B") == 0)
error = Material_setColorComponent (self, "B", valtuple);
else if (strcmp (name, "specR") == 0)
error = Material_setColorComponent (self, "specR", valtuple);
else if (strcmp (name, "specG") == 0)
error = Material_setColorComponent (self, "specG", valtuple);
else if (strcmp (name, "specB") == 0)
error = Material_setColorComponent (self, "specB", valtuple);
else if (strcmp (name, "amb") == 0)
error = Material_setAmb (self, valtuple);
else if (strcmp (name, "emit") == 0)

View File

@@ -58,6 +58,7 @@ extern PyTypeObject Material_Type; /* The Material PyType Object */
/*****************************************************************************/
PyObject *M_Material_Init (void);
PyObject *Material_CreatePyObject (Material *mat);
Material *Material_FromPyObject (PyObject *pyobj);
int Material_CheckPyObject (PyObject *pyobj);
/* Some functions needed by NMesh.c */

View File

@@ -29,11 +29,10 @@
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
/* This file is opy_nmesh.c from bpython modified to work with the new
* implementation of the Blender Python API */
#include "NMesh.h"
#define NMESH_FRAME_MAX 18000
void mesh_update(Mesh *mesh)
{
edge_drawflags_mesh(mesh);
@@ -551,10 +550,42 @@ static void NMesh_dealloc(PyObject *self)
Py_DECREF(me->name);
Py_DECREF(me->verts);
Py_DECREF(me->faces);
Py_DECREF(me->materials);
PyObject_DEL(self);
}
static PyObject *NMesh_addMaterial (PyObject *self, PyObject *args)
{
BPy_NMesh *me = (BPy_NMesh *)self;
BPy_Material *pymat;
Material *mat;
PyObject *iter;
int i, len = 0;
if (!PyArg_ParseTuple (args, "O!", &Material_Type, &pymat))
return EXPP_ReturnPyObjError (PyExc_TypeError,
"expected Blender Material PyObject");
mat = pymat->material;
len = PyList_Size(me->materials);
if (len >= 16)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"object data material lists can't have more than 16 materials");
for (i = 0; i < len; i++) {
iter = PyList_GetItem(me->materials, i);
if (mat == Material_FromPyObject(iter))
return EXPP_ReturnPyObjError (PyExc_AttributeError,
"material already in the list");
}
PyList_Append(me->materials, (PyObject *)pymat);
return EXPP_incr_ret (Py_None);
}
static PyObject *NMesh_removeAllKeys (PyObject *self, PyObject *args)
{
BPy_NMesh *nm = (BPy_NMesh *)self;
@@ -575,14 +606,25 @@ static PyObject *NMesh_removeAllKeys (PyObject *self, PyObject *args)
static PyObject *NMesh_insertKey(PyObject *self, PyObject *args)
{
int fra = -1, oldfra = -1;
char *type = NULL;
short typenum;
BPy_NMesh *nm = (BPy_NMesh *)self;
Mesh *mesh = nm->mesh;
if (!PyArg_ParseTuple(args, "|i", &fra))
if (!PyArg_ParseTuple(args, "|is", &fra, &type))
return EXPP_ReturnPyObjError (PyExc_TypeError,
"expected int argument (or nothing)");
"expected nothing or an int and optionally a string as arguments");
if (!type || !strcmp(type, "relative"))
typenum = 1;
else if (!strcmp(type, "absolute"))
typenum = 2;
else
return EXPP_ReturnPyObjError (PyExc_AttributeError,
"if given, type should be 'relative' or 'absolute'");
if (fra > 0) {
fra = EXPP_ClampInt(fra, 1, NMESH_FRAME_MAX);
oldfra = G.scene->r.cfra;
G.scene->r.cfra = fra;
}
@@ -591,7 +633,7 @@ static PyObject *NMesh_insertKey(PyObject *self, PyObject *args)
return EXPP_ReturnPyObjError (PyExc_RuntimeError,
"update this NMesh first with its .update() method");
insert_meshkey(mesh);
insert_meshkey(mesh, typenum);
if (fra > 0) G.scene->r.cfra = oldfra;
@@ -710,17 +752,26 @@ static PyObject *NMesh_hasVertexColours(PyObject *self, PyObject *args)
static PyObject *NMesh_update(PyObject *self, PyObject *args)
{
int recalc_normals = 0;
BPy_NMesh *nmesh = (BPy_NMesh *)self;
Mesh *mesh = nmesh->mesh;
if (!PyArg_ParseTuple(args, "|i", &recalc_normals))
return EXPP_ReturnPyObjError (PyExc_AttributeError,
"expected nothing or an int (0 or 1) as argument");
if (mesh) {
unlink_existingMeshData(mesh);
convert_NMeshToMesh(mesh, nmesh);
mesh_update(mesh);
} else {
} else {
nmesh->mesh = Mesh_fromNMesh(nmesh);
}
if(recalc_normals == 1)
vertexnormals_mesh(mesh, 0);
mesh_update(mesh);
nmesh_updateMaterials(nmesh);
/**@ This is another ugly fix due to the weird material handling of blender.
* it makes sure that object material lists get updated (by their length)
@@ -737,7 +788,7 @@ static PyObject *NMesh_update(PyObject *self, PyObject *args)
/** Implementation of the python method getVertexInfluence for an NMesh object.
* This method returns a list of pairs (string,float) with bone nemaes and
* This method returns a list of pairs (string,float) with bone names and
* influences that this vertex receives.
* @author Jordi Rovira i Bonet
*/
@@ -765,29 +816,36 @@ static PyObject *NMesh_getVertexInfluences(PyObject *self, PyObject *args)
int i;
MDeformWeight *sweight = NULL;
/* Number of bones influencig the vertex */
/* Number of bones influencing the vertex */
int totinfluences=me->dvert[index].totweight;
/* Build the list only with weights and names of the influent bones */
influence_list = PyList_New(totinfluences);
/*influence_list = PyList_New(totinfluences);*/
influence_list = PyList_New(0);
/* Get the reference of the first wwight structure */
/* Get the reference of the first weight structure */
sweight = me->dvert[index].dw;
for (i=0; i<totinfluences; i++) {
/* Some check that should always be true */
/* assert(sweight->data);*/
/*Add the weight and the name of the bone, which is used to identify it*/
PyList_SetItem(influence_list, i,
if (sweight->data) /* valid bone: return its name */
/* PyList_SetItem(influence_list, i,
Py_BuildValue("[sf]", sweight->data->name, sweight->weight));
else // NULL bone: return Py_None instead
PyList_SetItem(influence_list, i,
Py_BuildValue("[Of]", Py_None, sweight->weight));*/
PyList_Append(influence_list,
Py_BuildValue("[sf]", sweight->data->name, sweight->weight));
/* Next weight */
sweight++;
}
}
else influence_list = PyList_New(0);
else //influence_list = PyList_New(0);
return EXPP_ReturnPyObjError (PyExc_IndexError,
"vertex index out of range");
}
else influence_list = PyList_New(0);
@@ -804,7 +862,6 @@ Mesh *Mesh_fromNMesh(BPy_NMesh *nmesh)
"FATAL: could not create mesh object");
convert_NMeshToMesh(mesh, nmesh);
mesh_update(mesh);
return mesh;
}
@@ -833,6 +890,7 @@ static struct PyMethodDef NMesh_methods[] =
MethodDef(getActiveFace),
MethodDef(getSelectedFaces),
MethodDef(getVertexInfluences),
MethodDef(addMaterial),
MethodDef(insertKey),
MethodDef(removeAllKeys),
MethodDef(update),
@@ -1811,8 +1869,11 @@ int NMesh_CheckPyObject (PyObject *pyobj)
Mesh *NMesh_FromPyObject (PyObject *pyobj)
{
if (pyobj->ob_type == &NMesh_Type)
return Mesh_fromNMesh ((BPy_NMesh *)pyobj);
if (pyobj->ob_type == &NMesh_Type) {
Mesh *me = Mesh_fromNMesh ((BPy_NMesh *)pyobj);
mesh_update(me);
return me;
}
return NULL;
}

View File

@@ -55,10 +55,12 @@
#include "BIF_space.h"
#include "DNA_mesh_types.h"
#include "DNA_key_types.h"
#include "DNA_listBase.h"
#include "DNA_object_types.h"
#include "DNA_material_types.h"
#include "DNA_armature_types.h"
#include "mydevice.h"
#include "BIF_editkey.h" /* insert_meshkey */
#include "Material.h"
#include "Image.h"
@@ -68,8 +70,6 @@
#include "modules.h"
void insert_meshkey(Mesh *me); /* defined in editkey.c */
/* EXPP PyType Objects */
PyTypeObject NMesh_Type;
@@ -107,9 +107,15 @@ static char M_NMesh_Vert_doc[] =
"([x, y, z]) - Get a new vertice\n\n\
[x, y, z] Specify new coordinates";
static char NMesh_addMaterial_doc[] =
"(material) - add a new Blender Material 'material' to this Mesh's materials\n\
list.";
static char NMesh_insertKey_doc[] =
"(frame = None) - inserts a Mesh key at the given frame\n\
if called without arguments, it inserts the key at the current Scene frame";
"(frame = None, type = 'relative') - inserts a Mesh key at the given frame\n\
if called without arguments, it inserts the key at the current Scene frame.\n\
(type) - 'relative' or 'absolute'. Only relevant on the first call to this\n\
function for each nmesh.";
static char NMesh_removeAllKeys_doc[] =
"() - removes all keys from this mesh\n\
@@ -141,7 +147,8 @@ specified by index. The list contains pairs with the \n\
bone name and the weight.";
static char NMesh_update_doc[] = "updates the Mesh";
static char NMesh_update_doc[] = "(recalc_normals = 0) - updates the Mesh.\n\
if recalc_normals is given and is equal to 1, normal vectors are recalculated.";
/*
static char NMesh_asMesh_doc[] = "returns free Mesh datablock object from NMesh";

View File

@@ -74,3 +74,150 @@ class Armature:
Set the Armature root bones (still unimplemented).
@warn: This method wasn't implemented yet.
"""
class Bone:
"""
The Bone object
===============
This object gives access to Bone-specific data in Blender.
@cvar name: The name of this Bone.
@cvar roll: This Bone's roll value.
@cvar head: This Bone's "head" ending position when in rest state.
@cvar tail: This Bone's "tail" ending position when in rest state.
@cvar loc: This Bone's location.
@cvar size: This Bone's size.
@cvar quat: This Bone's quaternion.
@cvar parent: The parent Bone.
@cvar children: The children bones.
"""
def getName():
"""
Get the name of this Bone.
@rtype: string
"""
def getRoll():
"""
Get the roll value.
@rtype: float
"""
def getHead():
"""
Get the "head" ending position.
@rtype: list of three floats
"""
def getTail():
"""
Get the "tail" ending position.
@rtype: list of three floats
"""
def getLoc():
"""
Get the location of this Bone.
@rtype: list of three floats
"""
def getSize():
"""
Get the size attribute.
@rtype: list of three floats
"""
def getQuat():
"""
Get this Bone's quaternion.
@rtype: list of four floats.
"""
def hasParent():
"""
True if this Bone has a parent Bone.
@rtype: true or false
"""
def getParent():
"""
Get this Bone's parent Bone, if available.
@rtype: Blender Bone
"""
def getChildren():
"""
Get this Bone's children Bones, if available.
@rtype: list of Blender Bones
"""
def setName(name):
"""
Rename this Bone.
@type name: string
@param name: The new name.
"""
def setRoll(roll):
"""
Set the roll value.
@type roll: float
@param roll: The new value.
"""
def setHead(x,y,z):
"""
Set the "head" ending position.
@type x: float
@type y: float
@type z: float
@param x: The new x value.
@param y: The new y value.
@param z: The new z value.
"""
def setTail(x,y,z):
"""
Set the "tail" ending position.
@type x: float
@type y: float
@type z: float
@param x: The new x value.
@param y: The new y value.
@param z: The new z value.
"""
def setLoc(x,y,z):
"""
Set the new location for this Bone.
@type x: float
@type y: float
@type z: float
@param x: The new x value.
@param y: The new y value.
@param z: The new z value.
"""
def setSize(x,y,z):
"""
Set the new size for this Bone.
@type x: float
@type y: float
@type z: float
@param x: The new x value.
@param y: The new y value.
@param z: The new z value.
"""
def setQuat(real,imag_i,imag_j,imag_k):
"""
Set the new quaternion orientation for this Bone.
@type real: float
@type imag_i: float
@type imag_j: float
@type imag_k: float
@param real: The new quat[0] value.
@param imag_i: The new quat[1] value.
@param imag_j: The new quat[2] value.
@param imag_k: The new quat[3] value.
"""

View File

@@ -55,11 +55,12 @@ class Image:
"""
The Image object
================
This object gives access to Images in Blender. In the future it will allow
direct read/write access to their pixel buffers, too.
This object gives access to Images in Blender.
@cvar name: The name of this Image object.
@cvar filename: The filename (path) to the image file loaded into this Image
object.
@cvar size: The [width, height] dimensions of the image (in pixels).
@cvar depth: The pixel depth of the image.
@cvar xrep: Texture tiling: the number of repetitions in the x (horizontal)
axis.
@cvar yrep: Texture tiling: the number of repetitions in the y (vertical)
@@ -78,6 +79,18 @@ class Image:
@rtype: string
"""
def getSize():
"""
Get the [width, height] dimensions (in pixels) of this image.
@rtype: list of 2 ints
"""
def getDepth():
"""
Get the pixel depth of this image.
@rtype: int
"""
def getXRep():
"""
Get the number of repetitions in the x (horizontal) axis for this Image.
@@ -112,4 +125,3 @@ class Image:
@type yrep: int
@param yrep: The new value in [1, 16].
"""

View File

@@ -110,11 +110,15 @@ def GetRaw(name = None):
def GetRawFromObject(name):
"""
Get the mesh data object from the Object in Blender called I{name}.
Get the raw mesh data object from the Object in Blender called I{name}.
@type name: string
@param name: The name of an Object of type "Mesh".
@rtype: NMesh
@return: The NMesh wrapper of the mesh data from the Object called I{name}.
@warn: This function gets I{deformed} mesh data, already modified for
rendering (think "display list"). It also doesn't let you overwrite the
original mesh in Blender, so if you try to update it, a new mesh will
be created.
"""
def PutRaw(nmesh, name = None, recalculate_normals = 1):
@@ -187,7 +191,7 @@ class NMFace:
@param vertex: An NMVert object.
"""
class NMesh :
class NMesh:
"""
The NMesh Data object
=====================
@@ -201,6 +205,16 @@ class NMesh :
@cvar faces: The list of NMesh faces (NMFaces).
"""
def addMaterial(material):
"""
Add a new material to this NMesh's list of materials. This method is the
slower but safer way to add materials, since it checks if the argument
given is really a material, imposes a limit of 16 materials and only adds
the material if it wasn't already in the list.
@type material: Blender Material
@param material: A Blender Material.
"""
def hasVertexColours(flag = None):
"""
Get (and optionally set) if this NMesh has vertex colours.
@@ -272,14 +286,18 @@ class NMesh :
and its weight is a float value.
"""
def insertKey(frame = None):
def insertKey(frame = None, type = 'relative'):
"""
Insert a mesh key at the given frame. Remember to L{update} the nmesh
before doing this, or changes in the vertices won't be updated in the
Blender mesh.
@type frame: int
@type type: string
@param frame: The Scene frame where the mesh key should be inserted. If
None, the current frame is used.
@param type: The mesh key type: 'relative' or 'absolute'. This is only
relevant on the first call to insertKey for each nmesh (and after all
keys were removed with L{removeAllKeys}, of course).
@warn: This and L{removeAllKeys} were included in this release only to
make accessing vertex keys possible, but may not be a proper solution
and may be substituted by something better later. For example, it
@@ -301,9 +319,12 @@ class NMesh :
add them.
"""
def update():
def update(recalc_normals = 0):
"""
Update the mesh in Blender. The changes made are put back to the mesh in
Blender, if available, or put in a newly created mesh object if this NMesh
wasn't linked to one, yet.
@type recalc_normals: int
@param recalc_normals: If given and equal to 1, the vertex normals are
recalculated.
"""