From 9f43accdb2319b567551f652a6966a5fa56f086b Mon Sep 17 00:00:00 2001 From: Willian Padovani Germano Date: Thu, 13 Jan 2005 03:04:12 +0000 Subject: BPython: - patch by Jonathan Merritt: new function Blender.Draw.Image() + its doc; - patch by Campbell Barton: .users attribute for many types; - tiny internal change in nmesh.hasVertexUV() method. Thanks to Jonathan and Campbell for the patches and the patience! --- source/blender/python/api2_2x/Camera.c | 6 +- source/blender/python/api2_2x/Draw.c | 116 ++++++++++++++++++++++++++++++ source/blender/python/api2_2x/Image.c | 7 +- source/blender/python/api2_2x/Lamp.c | 10 +-- source/blender/python/api2_2x/Lattice.c | 7 +- source/blender/python/api2_2x/Material.c | 10 +-- source/blender/python/api2_2x/Metaball.c | 2 + source/blender/python/api2_2x/NMesh.c | 24 ++++--- source/blender/python/api2_2x/Texture.c | 6 +- source/blender/python/api2_2x/World.c | 2 + source/blender/python/api2_2x/doc/Draw.py | 61 ++++++++++++++++ 11 files changed, 225 insertions(+), 26 deletions(-) (limited to 'source/blender/python') diff --git a/source/blender/python/api2_2x/Camera.c b/source/blender/python/api2_2x/Camera.c index b0a3ebc76d9..f1ff823f050 100644 --- a/source/blender/python/api2_2x/Camera.c +++ b/source/blender/python/api2_2x/Camera.c @@ -794,6 +794,8 @@ static PyObject *Camera_getAttr( BPy_Camera * self, char *name ) attr = PyFloat_FromDouble( self->camera->clipend ); else if( strcmp( name, "drawSize" ) == 0 ) attr = PyFloat_FromDouble( self->camera->drawsize ); + else if( strcmp( name, "users" ) == 0 ) + attr = PyInt_FromLong( self->camera->id.us ); else if( strcmp( name, "ipo" ) == 0 ) { Ipo *ipo = self->camera->ipo; if( ipo ) @@ -813,10 +815,10 @@ static PyObject *Camera_getAttr( BPy_Camera * self, char *name ) } else if( strcmp( name, "__members__" ) == 0 ) { - attr = Py_BuildValue( "[s,s,s,s,s,s,s,s,s,s]", + attr = Py_BuildValue( "[s,s,s,s,s,s,s,s,s,s,s]", "name", "type", "mode", "lens", "clipStart", "ipo", "clipEnd", - "drawSize", "Types", "Modes" ); + "drawSize", "Types", "Modes", "users" ); } if( !attr ) diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index bd01c871978..62469d481d3 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -55,6 +55,7 @@ #include "DNA_text_types.h" #include "BKE_global.h" +#include "BKE_image.h" #include "BKE_library.h" #include "BKE_object.h" @@ -67,6 +68,9 @@ #include "BPI_script.h" /* script struct */ +#include "Image.h" /* for accessing Blender.Image objects */ +#include "IMB_imbuf_types.h" /* for the IB_rect define */ + #include "interface.h" #include "mydevice.h" /*@ for all the event constants */ @@ -112,6 +116,8 @@ static PyObject *Method_PupMenu( PyObject * self, PyObject * args ); static PyObject *Method_PupIntInput( PyObject * self, PyObject * args ); static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args ); static PyObject *Method_PupStrInput( PyObject * self, PyObject * args ); +/* next by Jonathan Merritt (lancelet): */ +static PyObject *Method_Image( PyObject * self, PyObject * args); static uiBlock *Get_uiBlock( void ); static void py_slider_update( void *butv, void *data2_unused ); @@ -267,6 +273,14 @@ static char Method_PupFloatInput_doc[] = the float value show.\n\ Return the user input value or None on user exit"; +static char Method_Image_doc[] = + "(image, x, y, zoomx = 1.0, zoomy = 1.0, [clipx, clipy, clipw, cliph])) \n\ + - Draw an image.\n\ +(image) - Blender.Image to draw.\n\ +(x, y) - floats specifying the location of the image.\n\ +(zoomx, zoomy) - float zoom factors in horizontal and vertical directions.\n\ +(clipx, clipy, clipw, cliph) - integers specifying a clipping rectangle within the original image."; + static char Method_PupStrInput_doc[] = "(text, default, max = 20) - Display a float pop-up input.\n\ (text) - text string to display on the button;\n\ @@ -304,6 +318,7 @@ static struct PyMethodDef Draw_methods[] = { MethodDef( PupIntInput ), MethodDef( PupFloatInput ), MethodDef( PupStrInput ), + MethodDef( Image ), MethodDef( Exit ), MethodDef( Redraw ), MethodDef( Draw ), @@ -1196,6 +1211,107 @@ static PyObject *Method_PupStrInput( PyObject * self, PyObject * args ) "couldn't create a PyString" ); } +/***************************************************************************** + * Function: Method_Image * + * Python equivalent: Blender.Draw.Image * + * * + * @author Jonathan Merritt * + ****************************************************************************/ +static PyObject *Method_Image( PyObject * self, PyObject * args ) +{ + PyObject *pyObjImage; + BPy_Image *py_img; + Image *image; + float originX, originY; + float zoomX = 1.0, zoomY = 1.0; + int clipX = 0, clipY = 0, clipW = -1, clipH = -1; + GLfloat scissorBox[4]; + + /* parse the arguments passed-in from Python */ + if( !PyArg_ParseTuple( args, "Off|ffiiii", &pyObjImage, + &originX, &originY, &zoomX, &zoomY, + &clipX, &clipY, &clipW, &clipH ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a Blender.Image and 2 floats, and " \ + "optionally 2 floats and 4 ints as arguments" ); + /* check that the first PyObject is actually a Blender.Image */ + if( !Image_CheckPyObject( pyObjImage ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected a Blender.Image and 2 floats, and " \ + "optionally 2 floats and 4 ints as arguments" ); + /* check that the zoom factors are valid */ + if( ( zoomX <= 0.0 ) || ( zoomY <= 0.0 ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "invalid zoom factors - they must be >= 0.0" ); + + /* fetch a C Image pointer from the passed-in Python object */ + py_img = ( BPy_Image * ) pyObjImage; + image = py_img->image; + + /* load the image data if necessary */ + if( !image->ibuf ) /* if no image data is available ... */ + load_image( image, IB_rect, "", 0 ); /* ... load it */ + if( !image->ibuf ) /* if failed to load the image */ + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "couldn't load image data in Blender" ); + + /* set up a valid clipping rectangle. if no clip rectangle was + * given, this results in inclusion of the entire image. otherwise, + * the clipping is just checked against the bounds of the image. + * if clipW or clipH are less than zero then they include as much of + * the image as they can. */ + clipX = EXPP_ClampInt( clipX, 0, image->ibuf->x ); + clipY = EXPP_ClampInt( clipY, 0, image->ibuf->y ); + if( ( clipW < 0 ) || ( clipW > ( image->ibuf->x - clipW ) ) ) + clipW = image->ibuf->x - clipX; + if( ( clipH < 0 ) || ( clipH > ( image->ibuf->y - clipH ) ) ) + clipH = image->ibuf->y - clipY; + + /* -- we are "Go" to Draw! -- */ + + /* set the raster position. + * + * If the raster position is negative, then using glRasterPos2i() + * directly would cause it to be clipped. Instead, we first establish + * a valid raster position within the clipping rectangle of the + * window and then use glBitmap() with a NULL image pointer to offset + * it to the true position we require. To pick an initial valid + * raster position within the viewport, we query the clipping rectangle + * and use its lower-left pixel. + * + * This particular technique is documented in the glRasterPos() man + * page, although I haven't seen it used elsewhere in Blender. + */ + glGetFloatv( GL_SCISSOR_BOX, scissorBox ); + glRasterPos2i( scissorBox[0], scissorBox[1] ); + glBitmap( 0, 0, 0.0, 0.0, + originX-scissorBox[0], originY-scissorBox[1], NULL ); + + /* set the zoom */ + glPixelZoom( zoomX, zoomY ); + + /* set the width of the image (ROW_LENGTH), and the offset to the + * clip origin within the image in x (SKIP_PIXELS) and + * y (SKIP_ROWS) */ + glPixelStorei( GL_UNPACK_ROW_LENGTH, image->ibuf->x ); + glPixelStorei( GL_UNPACK_SKIP_PIXELS, clipX ); + glPixelStorei( GL_UNPACK_SKIP_ROWS, clipY ); + + /* draw the image */ + glDrawPixels( clipW, clipH, GL_RGBA, GL_UNSIGNED_BYTE, + image->ibuf->rect ); + + /* restore the defaults for some parameters (we could also use a + * glPushClientAttrib() and glPopClientAttrib() pair). */ + glPixelZoom( 1.0, 1.0 ); + glPixelStorei( GL_UNPACK_SKIP_ROWS, 0 ); + glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0 ); + glPixelStorei( GL_UNPACK_ROW_LENGTH, 0 ); + + Py_INCREF( Py_None ); + return Py_None; + +} PyObject *Draw_Init( void ) { diff --git a/source/blender/python/api2_2x/Image.c b/source/blender/python/api2_2x/Image.c index ce70db0cf75..a27cba7d2a2 100644 --- a/source/blender/python/api2_2x/Image.c +++ b/source/blender/python/api2_2x/Image.c @@ -606,11 +606,12 @@ static PyObject *Image_getAttr( BPy_Image * self, char *name ) attr = PyInt_FromLong( self->image->yrep ); else if( strcmp( name, "bindcode" ) == 0 ) attr = PyInt_FromLong( self->image->bindcode ); - + else if( strcmp( name, "users" ) == 0 ) + attr = PyInt_FromLong( self->image->id.us ); else if( strcmp( name, "__members__" ) == 0 ) - attr = Py_BuildValue( "[s,s,s,s,s,s,s]", + attr = Py_BuildValue( "[s,s,s,s,s,s,s,s]", "name", "filename", "size", "depth", - "xrep", "yrep", "bindcode" ); + "xrep", "yrep", "bindcode", "users" ); if( !attr ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index bb84c766a56..0e9935d0c78 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -1311,7 +1311,9 @@ static PyObject *Lamp_getAttr( BPy_Lamp * self, char *name ) attr = PyFloat_FromDouble( self->lamp->att1 ); else if( strcmp( name, "quad2" ) == 0 ) attr = PyFloat_FromDouble( self->lamp->att2 ); - + else if( strcmp( name, "users" ) == 0 ) + attr = PyInt_FromLong( self->lamp->id.us ); + else if( strcmp( name, "Types" ) == 0 ) { attr = Py_BuildValue( "{s:h,s:h,s:h,s:h,s:h,s:h}", "Lamp", EXPP_LAMP_TYPE_LAMP, @@ -1336,16 +1338,16 @@ static PyObject *Lamp_getAttr( BPy_Lamp * self, char *name ) EXPP_LAMP_MODE_NODIFFUSE, "NoSpecular", EXPP_LAMP_MODE_NOSPECULAR ); } - + else if( strcmp( name, "__members__" ) == 0 ) { /* 23 entries */ attr = Py_BuildValue - ( "[s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s]", + ( "[s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s]", "name", "type", "mode", "samples", "bufferSize", "haloStep", "R", "G", "B", "energy", "dist", "spotSize", "spotBlend", "clipStart", "clipEnd", "bias", "softness", "haloInt", "quad1", "quad2", - "Types", "Modes", "col" ); + "Types", "Modes", "col", "users" ); } if( !attr ) diff --git a/source/blender/python/api2_2x/Lattice.c b/source/blender/python/api2_2x/Lattice.c index e10755f28ec..c4dc04a4747 100644 --- a/source/blender/python/api2_2x/Lattice.c +++ b/source/blender/python/api2_2x/Lattice.c @@ -804,12 +804,15 @@ static PyObject *Lattice_getAttr( BPy_Lattice * self, char *name ) attr = Py_BuildValue( "i", self->Lattice->pntsu * self->Lattice->pntsv * self->Lattice->pntsw ); + } else if( strcmp( name, "users" ) == 0 ) { + attr = PyInt_FromLong( self->Lattice->id.us ); + } else if( strcmp( name, "__members__" ) == 0 ) attr = Py_BuildValue( "[s,s,s,s,s,s,s,s,s]", "name", "width", "height", "depth", "widthType", "heightType", "depthType", "mode", - "latSize" ); - + "latSize", "users" ); + if( !attr ) return ( EXPP_ReturnPyObjError( PyExc_MemoryError, "couldn't create PyObject" ) ); diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 37c250b6c13..9ab493eddcb 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -1995,11 +1995,13 @@ static PyObject *Material_getAttr( BPy_Material * self, char *name ) else if( strcmp( name, "fresnelTransFac" ) == 0 ) attr = PyFloat_FromDouble( ( double ) self->material-> fresnel_tra_i ); - + else if( strcmp( name, "users" ) == 0 ) + attr = PyInt_FromLong( ( double ) self->material-> + id.us ); else if( strcmp( name, "__members__" ) == 0 ) { - attr = /* 27 items */ + attr = /* 28 items */ Py_BuildValue - ( "[s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s]", + ( "[s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s]", "name", "mode", "rgbCol", "specCol", "mirCol", "R", "G", "B", "alpha", "amb", "emit", "ref", "spec", "specTransp", "add", "zOffset", "haloSize", @@ -2007,7 +2009,7 @@ static PyObject *Material_getAttr( BPy_Material * self, char *name ) "subSize", "hard", "nFlares", "nStars", "nLines", "nRings", "rayMirr", "rayMirrDepth", "fresnelDepth", "fresnelDepthFac", "IOR", "transDepth", - "fresnelTrans", "fresnelTransFac" ); + "fresnelTrans", "fresnelTransFac", "users" ); } if( !attr ) diff --git a/source/blender/python/api2_2x/Metaball.c b/source/blender/python/api2_2x/Metaball.c index 9a64820cd07..67645d61d2e 100644 --- a/source/blender/python/api2_2x/Metaball.c +++ b/source/blender/python/api2_2x/Metaball.c @@ -1092,6 +1092,8 @@ static PyObject *MetaballGetAttr( BPy_Metaball * self, char *name ) return Metaball_getloc( self ); if( strcmp( name, "size" ) == 0 ) return Metaball_getsize( self ); + if( strcmp( name, "users" ) == 0 ) + return PyInt_FromLong( self->metaball->id.us ); return Py_FindMethod( BPy_Metaball_methods, ( PyObject * ) self, name ); } diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c index 354e7303134..c2d4656cfbc 100644 --- a/source/blender/python/api2_2x/NMesh.c +++ b/source/blender/python/api2_2x/NMesh.c @@ -1031,17 +1031,23 @@ static PyObject *NMesh_getActiveFace( PyObject * self, PyObject * args ) static PyObject *NMesh_hasVertexUV( PyObject * self, PyObject * args ) { BPy_NMesh *me = ( BPy_NMesh * ) self; - int flag; + int flag = -1; - if( args ) { - if( PyArg_ParseTuple( args, "i", &flag ) ) { - if( flag ) - me->flags |= NMESH_HASVERTUV; - else - me->flags &= ~NMESH_HASVERTUV; - } + if( !PyArg_ParseTuple( args, "|i", &flag ) ) + return EXPP_ReturnPyObjError( PyExc_TypeError, + "expected int argument (or nothing)" ); + + switch ( flag ) { + case 0: + me->flags &= ~NMESH_HASVERTUV; + break; + case 1: + me->flags |= NMESH_HASVERTUV; + break; + default: + break; } - PyErr_Clear( ); + if( me->flags & NMESH_HASVERTUV ) return EXPP_incr_ret( Py_True ); else diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index 144f200f045..fe0fc1dacca 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -1805,10 +1805,12 @@ static PyObject *Texture_getAttr( BPy_Texture * self, char *name ) attr = PyFloat_FromDouble( tex->vn_w4 ); else if( STREQ( name, "distAmnt" ) ) attr = PyFloat_FromDouble( tex->vn_w4 ); + else if( STREQ( name, "users" ) ) + attr = PyInt_FromLong( tex->id.us ); else if( STREQ( name, "__members__" ) ) attr = Py_BuildValue - ( "[s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s]", + ( "[s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s,s]", "animFrames", "animLength", "animMontage", "animOffset", "animStart", "brightness", "contrast", "crop", "extend", "fieldsPerImage", "filterSize", @@ -1816,7 +1818,7 @@ static PyObject *Texture_getAttr( BPy_Texture * self, char *name ) "noiseSize", "noiseType", "repeat", "rgbCol", "stype", "turbulence", "type", "hFracDim", "lacunarity", "octs", "iScale", "exp", "weight1", - "weight2", "weight3", "weight4", "distAmnt" ); + "weight2", "weight3", "weight4", "distAmnt", "users" ); if( !attr ) return EXPP_ReturnPyObjError( PyExc_MemoryError, diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index 01355dd0322..88f8576cde8 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -921,6 +921,8 @@ static PyObject *World_GetAttr( BPy_World * self, char *name ) return World_getStar( self ); if( strcmp( name, "mist" ) == 0 ) return World_getMist( self ); + if( strcmp( name, "users" ) == 0 ) + return PyInt_FromLong( self->world->id.us ); return Py_FindMethod( BPy_World_methods, ( PyObject * ) self, name ); } diff --git a/source/blender/python/api2_2x/doc/Draw.py b/source/blender/python/api2_2x/doc/Draw.py index 2b89fb34b0b..67d9203b5f5 100644 --- a/source/blender/python/api2_2x/doc/Draw.py +++ b/source/blender/python/api2_2x/doc/Draw.py @@ -594,6 +594,67 @@ def Text(string, fontsize = 'normal'): @return: The width of I{string} drawn with the chosen I{fontsize}. """ +def Image(image, x, y, zoomx=1.0, zoomy=1.0, clipx=0, clipy=0, clipw=-1, cliph=-1): + """ + Draw an image on the screen. + + The image is drawn at the location specified by the coordinates (x,y). A + pair of optional zoom factors (in horizontal and vertical directions) can + be applied to the image as it is drawn, and an additional clipping rectangle + can be applied to extract a particular sub-region of the image to draw. + + Note that the clipping rectangle is given in image space coordinates. In + image space, the origin is located at the bottom left, with x coordinates + increasing to the right and y coordinates increasing upwards. No matter + where the clipping rectangle is placed in image space, the lower-left pixel + drawn on the screen is always placed at the coordinates (x,y). The + clipping rectangle is itself clipped to the dimensions of the image. If + either the width or the height of the clipping rectangle are negative then + the corresponding dimension (width or height) is set to include as much of + the image as possible. + + Example:: + import Blender + from Blender import BGL, Image, Draw + + myimage = Image.Load('myimage.png') + + def gui(): + Draw.Image(myimage, 50, 50) + def event(evt, val): + if evt == Draw.ESCKEY: + Draw.Exit() + + Draw.Register(gui, event, None) + + @type image: Blender.Image + @param image: The image to draw. + @type x: int + @param x: The lower left x (horizontal) position of the origin of the image. + @type y: int + @param y: The lower left y (vertical) position of the origin of the image. + @type zoomx: float + @param zoomx: The x (horizontal) zoom factor to use when drawing the image. + @type zoomy: float + @param zoomy: The y (vertical) zoom factor to use when drawing the image. + @type clipx: int + @param clipx: The lower left x (horizontal) origin of the clipping rectangle + within the image. A value of 0 indicates the left of the + image. + @type clipy: int + @param clipy: The lower left y (vertical) origin of the clipping rectangle + within the image. A value of 0 indicates the bottom of the + image. + @type clipw: int + @param clipw: The width of the clipping rectangle within the image. If this + value is negative then the clipping rectangle includes as much + of the image as possible in the x (horizontal) direction. + @type cliph: int + @param cliph: The height of the clipping rectangle within the image. If this + value is negative then the clipping rectangle includes as much + of the image as possible in the y (vertical) direction. + """ + class Button: """ The Button object -- cgit v1.2.3