2003-02-26 19:22:24 +00:00
|
|
|
/*
|
2004-09-18 18:47:03 +00:00
|
|
|
* $Id$
|
2003-02-26 19:22:24 +00:00
|
|
|
*
|
|
|
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version. The Blender
|
|
|
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
|
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
|
|
|
* about this.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
2004-06-24 09:43:13 +00:00
|
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
2003-02-26 19:22:24 +00:00
|
|
|
*
|
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* This is a new part of Blender.
|
|
|
|
|
*
|
2005-04-21 19:44:52 +00:00
|
|
|
* Contributor(s): Michel Selten, Willian P. Germano, Alex Mole, Ken Hughes
|
2003-02-26 19:22:24 +00:00
|
|
|
*
|
|
|
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
2005-07-18 03:50:37 +00:00
|
|
|
#include "gen_utils.h" /*This must come first*/
|
|
|
|
|
|
Mathutils update
- also included is some fixes for preprocessor inclues and some clean up of the previous commit
-rewrite and bugfixes
----------------------------------
Here's my changelog:
-fixed Rand() so that it doesn't seed everytime and should generate better random numbers
- changed a few error return types to something more appropriate
- clean up of uninitialized variables & removal of unneccessary objects
- NMesh returns wrapped vectors now
- World returns wrapped matrices now
- Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present
- Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix
- Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks
- Removed memory allocation (unneeded) from all methods
- Vector's resize methods are only applicable to new vectors not wrapped data.
- Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences
- Fixed Slerp() so that it now works correctly values are clamped between 0 and 1
- Euler.rotate does internal rotation now
- Slice assignment now works better for all types
- Vector * Vector and Quat * Quat are defined and return the DOT product
- Mat * Vec and Vec * Mat are defined now
- Moved #includes to .c file from headers. Also fixed prototypes in mathutils
- Added new helper functions for incref'ing to genutils
- Major cleanup of header files includes - include Mathutils.h for access to math types
- matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes
- Matrix() with no parameters now returns an identity matrix by default not a zero matrix
- printf() now prints with 6 digits instead of 4
- printf() now prints output with object descriptor
- Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4)
- Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix.
- slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data.
- slice assignment will no longer modify the data if the assignment operation fails
- fixed error in matrix * scalar multiplication
- euler.toMatrix(), toQuat() no longer causes "creep" from repeated use
- Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used
- Quats can be created with angle/axis, axis/angle
- 4x4 matrices can be multiplied by 3D vectors (by popular demand :))
- vec *quat / quat * vec is now defined
- vec.magnitude alias for vec.length
- all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none')
- these methods have been deprecated (still functioning but suggested to use the corrected functionality):
* CopyVec() - replaced by Vector() functionality
* CopyMat() - replaced by Matrix() functionality
* CopyQuat() - replace by Quaternion() functionality
* CopyEuler() - replaced by Euler() functionality
* RotateEuler() - replaced by Euler.rotate() funtionality
* MatMultVec() - replaced by matrix * vector
* VecMultMat() - replaced by vector * matrix
- New struct containers references to python object data or internally allocated blender data for wrapping
* Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python
* otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
|
|
|
#include "DNA_text_types.h"
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
|
#include "BIF_space.h"
|
2005-07-18 03:50:37 +00:00
|
|
|
#include "BKE_global.h"
|
|
|
|
|
#include "BKE_main.h"
|
- Blender: added option 'scriptsdir' to Blender.Get();
- small updates to the docs;
- Object: small fix to getMatrix: check during_script() to avoid undesired loops; added old behavior (pre 2.34) as option: .getMatrix('oldlocal');
- tentative fix for bug #1275: scene REDRAW scriptlinks were not being executed (the call to do so was missing):
http://projects.blender.org/tracker/index.php?func=detail&aid=1275&group_id=9&atid=125
added the call in drawview.c, in drawview3dspace(). This causes the scriptlink to be called for each visible view3d, but that's what happens with object redraw scriptlinks, too. Anyway, this is still a test. The place was chosen based on the idea that a scene redraw scriptlink is like an object redraw one, but for all objs in the scene at once.
- Window.Theme: new submodule, to get/set theme options in Blender;
- Added the script save_theme.py (Help menu for now), to save the current theme in Blender as an executable script (currently shown in the Scripts->Misc menu).
There's more work to do for themes, like defining a proper place for them in the interface, adding documentation (for now the added script and the ones it generates can give a pretty good idea of how to use the new module), probably extending themes to support SpaceScript and so on.
2004-09-21 05:28:17 +00:00
|
|
|
|
2006-09-17 02:31:16 +00:00
|
|
|
#include "Mathutils.h"
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
#include "constant.h"
|
|
|
|
|
|
2005-11-22 17:59:49 +00:00
|
|
|
//---------------------- EXPP_FloatsAreEqual -------------------------
|
|
|
|
|
//Floating point comparisons
|
|
|
|
|
//floatStep = number of representable floats allowable in between
|
|
|
|
|
// float A and float B to be considered equal.
|
|
|
|
|
int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
|
|
|
|
|
{
|
|
|
|
|
int a, b, delta;
|
|
|
|
|
assert(floatSteps > 0 && floatSteps < (4 * 1024 * 1024));
|
|
|
|
|
a = *(int*)&A;
|
|
|
|
|
if (a < 0)
|
|
|
|
|
a = 0x80000000 - a;
|
|
|
|
|
b = *(int*)&B;
|
|
|
|
|
if (b < 0)
|
|
|
|
|
b = 0x80000000 - b;
|
|
|
|
|
delta = abs(a - b);
|
|
|
|
|
if (delta <= floatSteps)
|
|
|
|
|
return 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
//---------------------- EXPP_VectorsAreEqual -------------------------
|
|
|
|
|
//Builds on EXPP_FloatsAreEqual to test vectors
|
|
|
|
|
int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
|
|
|
|
|
|
|
|
|
|
int x;
|
|
|
|
|
for (x=0; x< size; x++){
|
|
|
|
|
if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2005-08-17 14:26:00 +00:00
|
|
|
//---------------------- EXPP_GetModuleConstant -------------------------
|
|
|
|
|
//Helper function for returning a module constant
|
|
|
|
|
PyObject *EXPP_GetModuleConstant(char *module, char *constant)
|
|
|
|
|
{
|
|
|
|
|
PyObject *py_module = NULL, *py_dict = NULL, *py_constant = NULL;
|
|
|
|
|
|
|
|
|
|
/*Careful to pass the correct Package.Module string here or
|
|
|
|
|
* else you add a empty module somewhere*/
|
|
|
|
|
py_module = PyImport_AddModule(module);
|
|
|
|
|
if(!py_module){ //null = error returning module
|
|
|
|
|
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
|
|
|
|
"error encountered with returning module constant..." ) );
|
|
|
|
|
}
|
|
|
|
|
py_dict = PyModule_GetDict(py_module); //never fails
|
|
|
|
|
|
|
|
|
|
py_constant = PyDict_GetItemString(py_dict, constant);
|
|
|
|
|
if(!py_constant){ //null = key not found
|
|
|
|
|
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
|
|
|
|
"error encountered with returning module constant..." ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EXPP_incr_ret(py_constant);
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-17 04:29:49 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: This function clamps an int to the given interval */
|
|
|
|
|
/* [min, max]. */
|
2003-05-17 04:29:49 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
int EXPP_ClampInt( int value, int min, int max )
|
2003-05-17 04:29:49 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
if( value < min )
|
|
|
|
|
return min;
|
|
|
|
|
else if( value > max )
|
|
|
|
|
return max;
|
2003-05-17 04:29:49 +00:00
|
|
|
return value;
|
|
|
|
|
}
|
2003-03-08 18:10:20 +00:00
|
|
|
|
2003-04-08 19:54:14 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: This function clamps a float to the given interval */
|
|
|
|
|
/* [min, max]. */
|
2003-04-08 19:54:14 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
float EXPP_ClampFloat( float value, float min, float max )
|
2003-04-08 19:54:14 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
if( value < min )
|
|
|
|
|
return min;
|
|
|
|
|
else if( value > max )
|
|
|
|
|
return max;
|
2003-04-08 19:54:14 +00:00
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
/* Description: This function returns true if both given strings are equal, */
|
2004-09-25 20:30:40 +00:00
|
|
|
/* otherwise it returns false. */
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
int StringEqual( const char *string1, const char *string2 )
|
2003-03-08 18:10:20 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
return ( strcmp( string1, string2 ) == 0 );
|
2003-03-08 18:10:20 +00:00
|
|
|
}
|
|
|
|
|
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: This function returns the name of the given ID struct */
|
|
|
|
|
/* without the Object type identifying characters prepended. */
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
char *GetIdName( ID * id )
|
2003-03-15 19:14:16 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
return ( ( id->name ) + 2 );
|
2003-03-15 19:14:16 +00:00
|
|
|
}
|
|
|
|
|
|
2003-05-17 04:29:49 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: This function returns the ID of the object with given name */
|
|
|
|
|
/* from a given list. */
|
2003-05-17 04:29:49 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
ID *GetIdFromList( ListBase * list, char *name )
|
2003-05-17 04:29:49 +00:00
|
|
|
{
|
|
|
|
|
ID *id = list->first;
|
|
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
while( id ) {
|
|
|
|
|
if( strcmp( name, id->name + 2 ) == 0 )
|
|
|
|
|
break;
|
|
|
|
|
id = id->next;
|
2003-05-17 04:29:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: These functions set an internal string with the given type */
|
|
|
|
|
/* and error_msg arguments. */
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2003-03-08 18:10:20 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
PyObject *EXPP_ReturnPyObjError( PyObject * type, char *error_msg )
|
|
|
|
|
{ /* same as above, just to change its name smoothly */
|
|
|
|
|
PyErr_SetString( type, error_msg );
|
2003-05-08 03:06:46 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
int EXPP_ReturnIntError( PyObject * type, char *error_msg )
|
2003-04-08 19:54:14 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
PyErr_SetString( type, error_msg );
|
2003-04-08 19:54:14 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2005-08-17 14:26:00 +00:00
|
|
|
|
|
|
|
|
int EXPP_intError(PyObject *type, const char *format, ...)
|
|
|
|
|
{
|
2005-12-27 15:28:09 +00:00
|
|
|
PyObject *error;
|
2005-08-17 14:26:00 +00:00
|
|
|
va_list vlist;
|
|
|
|
|
|
|
|
|
|
va_start(vlist, format);
|
2005-12-27 15:28:09 +00:00
|
|
|
error = PyString_FromFormatV(format, vlist);
|
2005-08-17 14:26:00 +00:00
|
|
|
va_end(vlist);
|
|
|
|
|
|
2005-12-27 15:28:09 +00:00
|
|
|
PyErr_SetObject(type, error);
|
|
|
|
|
Py_DECREF(error);
|
2005-08-17 14:26:00 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
//Like EXPP_ReturnPyObjError but takes a printf format string and multiple arguments
|
|
|
|
|
PyObject *EXPP_objError(PyObject *type, const char *format, ...)
|
|
|
|
|
{
|
2005-12-27 15:28:09 +00:00
|
|
|
PyObject *error;
|
2005-08-17 14:26:00 +00:00
|
|
|
va_list vlist;
|
|
|
|
|
|
|
|
|
|
va_start(vlist, format);
|
2005-12-27 15:28:09 +00:00
|
|
|
error = PyString_FromFormatV(format, vlist);
|
2005-08-17 14:26:00 +00:00
|
|
|
va_end(vlist);
|
|
|
|
|
|
2005-12-27 15:28:09 +00:00
|
|
|
PyErr_SetObject(type, error);
|
|
|
|
|
Py_DECREF(error);
|
2005-08-17 14:26:00 +00:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: This function increments the reference count of the given */
|
|
|
|
|
/* Python object (usually Py_None) and returns it. */
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2003-03-08 18:10:20 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
PyObject *EXPP_incr_ret( PyObject * object )
|
2003-05-08 03:06:46 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
Py_INCREF( object );
|
|
|
|
|
return ( object );
|
2003-05-08 03:06:46 +00:00
|
|
|
}
|
2004-06-06 22:42:51 +00:00
|
|
|
|
2005-02-09 15:53:35 +00:00
|
|
|
/* return Py_False - to avoid warnings, we use the fact that
|
|
|
|
|
* 0 == False in Python: */
|
|
|
|
|
PyObject *EXPP_incr_ret_False()
|
|
|
|
|
{
|
|
|
|
|
return Py_BuildValue("i", 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* return Py_True - to avoid warnings, we use the fact that
|
|
|
|
|
* 1 == True in Python: */
|
|
|
|
|
PyObject *EXPP_incr_ret_True()
|
|
|
|
|
{
|
|
|
|
|
return Py_BuildValue("i", 1);
|
|
|
|
|
}
|
|
|
|
|
|
Mathutils update
- also included is some fixes for preprocessor inclues and some clean up of the previous commit
-rewrite and bugfixes
----------------------------------
Here's my changelog:
-fixed Rand() so that it doesn't seed everytime and should generate better random numbers
- changed a few error return types to something more appropriate
- clean up of uninitialized variables & removal of unneccessary objects
- NMesh returns wrapped vectors now
- World returns wrapped matrices now
- Object.getEuler() and Object.getBoundingBox() return Wrapped data when data is present
- Object.getMatrix() returns wrapped data if it's worldspace, 'localspace' returns a new matrix
- Vector, Euler, Mat, Quat, call all now internally wrap object without destroying internal datablocks
- Removed memory allocation (unneeded) from all methods
- Vector's resize methods are only applicable to new vectors not wrapped data.
- Matrix(), Quat(), Euler(), Vector() now accepts ANY sequence list, including tuples, list, or a self object to copy - matrices accept multiple sequences
- Fixed Slerp() so that it now works correctly values are clamped between 0 and 1
- Euler.rotate does internal rotation now
- Slice assignment now works better for all types
- Vector * Vector and Quat * Quat are defined and return the DOT product
- Mat * Vec and Vec * Mat are defined now
- Moved #includes to .c file from headers. Also fixed prototypes in mathutils
- Added new helper functions for incref'ing to genutils
- Major cleanup of header files includes - include Mathutils.h for access to math types
- matrix.toQuat() and .toEuler() now fixed take appropriate matrix sizes
- Matrix() with no parameters now returns an identity matrix by default not a zero matrix
- printf() now prints with 6 digits instead of 4
- printf() now prints output with object descriptor
- Matrices now support [x][y] assignment (e.g. matrix[x][y] = 5.4)
- Matrix[index] = value now expectes a sequence not an integer. This will now set a ROW of the matrix through a sequence. index cannot go above the row size of the matrix.
- slice operations on matrices work with sequences now (rows of the matrix) example: mymatrix[0:2] returns a list of 2 wrapped vectors with access to the matrix data.
- slice assignment will no longer modify the data if the assignment operation fails
- fixed error in matrix * scalar multiplication
- euler.toMatrix(), toQuat() no longer causes "creep" from repeated use
- Wrapped data will generate wrapped objects when toEuler(), toQuat(), toMatrix() is used
- Quats can be created with angle/axis, axis/angle
- 4x4 matrices can be multiplied by 3D vectors (by popular demand :))
- vec *quat / quat * vec is now defined
- vec.magnitude alias for vec.length
- all self, internal methods return a pointer to self now so you can do print vector.internalmethod() or vector.internalmethod().nextmethod() (no more print matrix.inverse() returning 'none')
- these methods have been deprecated (still functioning but suggested to use the corrected functionality):
* CopyVec() - replaced by Vector() functionality
* CopyMat() - replaced by Matrix() functionality
* CopyQuat() - replace by Quaternion() functionality
* CopyEuler() - replaced by Euler() functionality
* RotateEuler() - replaced by Euler.rotate() funtionality
* MatMultVec() - replaced by matrix * vector
* VecMultMat() - replaced by vector * matrix
- New struct containers references to python object data or internally allocated blender data for wrapping
* Explaination here: math structs now function as a 'simple wrapper' or a 'py_object' - data that is created on the fly will now be a 'py_object' with its memory managed by python
* otherwise if the data is returned by blender's G.main then the math object is a 'simple wrapper' and data can be accessed directly from the struct just like other python objects.
2005-07-14 03:34:56 +00:00
|
|
|
void EXPP_incr2( PyObject * ob1, PyObject * ob2 )
|
|
|
|
|
{
|
|
|
|
|
Py_INCREF( ob1 );
|
|
|
|
|
Py_INCREF( ob2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EXPP_incr3( PyObject * ob1, PyObject * ob2, PyObject * ob3 )
|
|
|
|
|
{
|
|
|
|
|
Py_INCREF( ob1 );
|
|
|
|
|
Py_INCREF( ob2 );
|
|
|
|
|
Py_INCREF( ob3 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EXPP_decr2( PyObject * ob1, PyObject * ob2 )
|
|
|
|
|
{
|
|
|
|
|
Py_DECREF( ob1 );
|
|
|
|
|
Py_DECREF( ob2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EXPP_decr3( PyObject * ob1, PyObject * ob2, PyObject * ob3 )
|
|
|
|
|
{
|
|
|
|
|
Py_DECREF( ob1 );
|
|
|
|
|
Py_DECREF( ob2 );
|
|
|
|
|
Py_DECREF( ob3 );
|
|
|
|
|
}
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: This function maps the event identifier to a string. */
|
2003-03-18 20:21:26 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
char *event_to_name( short event )
|
2003-03-08 18:10:20 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
switch ( event ) {
|
|
|
|
|
case SCRIPT_FRAMECHANGED:
|
|
|
|
|
return "FrameChanged";
|
|
|
|
|
case SCRIPT_ONLOAD:
|
|
|
|
|
return "OnLoad";
|
|
|
|
|
case SCRIPT_ONSAVE:
|
|
|
|
|
return "OnSave";
|
|
|
|
|
case SCRIPT_REDRAW:
|
|
|
|
|
return "Redraw";
|
BPython:
- Made Blender.event var (previously only used by script links) hold ascii value -- where it applies -- of current event during events callback registered with Draw.Register(gui, events, button_events). Useful for gui scripts like Campbell's Python console. No problem using this var to hold the value, since in gui scripts it was not used (always None).
- Updated Window and Window.Theme with new theme vars and the Time space.
- Script links:
-- Added "Render" event for script links (runs twice, second time as "PostEvent", for clean-up actions). Now FrameChanged links don't run when a single pic is rendered.
-- Added "Enable Script Links" button in the script buttons tab. Now this bit gets saved in .blends along with the rest of G.f, so users can define per .blend if they are on or off by default. "blender -y" also disables all slinks as happened before with OnLoad ones only.
-- Other small changes in the script buttons tab:
When a link is added (button "new"), it becomes the active one for the window, no need to press a button to reach it.
Also, a pupmenu showing all available texts is shown when "new" is pressed, so users can choose a text w/o having to type. Cancel the popup to leave the string button empty (link exists, but has no script assigned). A pulldown would be better UI-wise, but it's kinda weird to show both scripts and normal texts (Blender doesn't differentiate them) in a script links pulldown. With a popup we can show only texts ending in ".py" (not done in this commit, need opinions) and if the script has no or another extension, case of many in old and current .blend's, there's still the string box for writing its name.
-- Implemented Ton's space handler script links:
Right now only for the 3d View, but it's trivial to add for others. There are two types: EVENT, to receive 3d View events from a chosen window and DRAW, to draw on the window. Ton's idea was to give scripts a controlled way to integrate better within Blender.
Here's how it works:
- scripts must have a proper header, like:
# SPACEHANDLER.VIEW3D.EVENT
and then they are shown in 3d View's View menu, "Space Handler Scripts" submenu. Check (mark, click on it) a script to make it active.
EVENT handlers should consult the Blender.event var to get the current event, which can be compared with values from the Draw module:
import Blender
from Blender import Draw
evt = Blender.event
if evt == Draw.AKEY:
print "a"
elif evt == Draw.LEFTMOUSE:
print "left mouse button"
else:
return # ignore, pass event back to Blender
Blender.event = None # tell Blender not to process itself the event
DRAW handlers are free to draw to their owner 3D View. OpenGL attributes and modelview and projection matrices are pushed before running the handler and poped when it finishes.
To communicate between EVENT and DRAW handler scripts we have the Blender.Registry module, as always.
Still need to code some nice example, which should also serve to test properly space handlers. Simple tests went fine.
- doc updates about the additions.
=======
Note: the UI part of the space handlers and script links is of course open for changes, I just tried to make it understandable. Probably we won't use the scriptlinks icon for "None Available" (check 3d View -> View -> Space Handler Scripts), though it hints at what space handlers are. The tooltips may not be accepted either, since other menus don't use them. Opinions welcomed.
2005-05-08 21:20:34 +00:00
|
|
|
case SCRIPT_RENDER:
|
|
|
|
|
return "Render";
|
|
|
|
|
case SCRIPT_POSTRENDER:
|
|
|
|
|
return "PostRender";
|
2004-09-25 20:30:40 +00:00
|
|
|
default:
|
|
|
|
|
return "Unknown";
|
2003-03-08 18:10:20 +00:00
|
|
|
}
|
2004-09-25 20:30:40 +00:00
|
|
|
}
|
2003-02-26 19:22:24 +00:00
|
|
|
|
2003-05-17 04:29:49 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
/* Description: Checks whether all objects in a PySequence are of a same */
|
|
|
|
|
/* given type. Returns 0 if not, 1 on success. */
|
2003-05-17 04:29:49 +00:00
|
|
|
/*****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
int EXPP_check_sequence_consistency( PyObject * seq, PyTypeObject * against )
|
2003-05-17 04:29:49 +00:00
|
|
|
{
|
|
|
|
|
PyObject *ob;
|
2004-09-25 20:30:40 +00:00
|
|
|
int len = PySequence_Length( seq );
|
2004-07-20 08:16:46 +00:00
|
|
|
int i, result = 1;
|
2003-05-17 04:29:49 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
for( i = 0; i < len; i++ ) {
|
|
|
|
|
ob = PySequence_GetItem( seq, i );
|
|
|
|
|
if( ob == Py_None )
|
|
|
|
|
result = 2;
|
|
|
|
|
else if( ob->ob_type != against ) {
|
|
|
|
|
Py_DECREF( ob );
|
2003-05-17 04:29:49 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2004-09-25 20:30:40 +00:00
|
|
|
Py_DECREF( ob );
|
2003-05-17 04:29:49 +00:00
|
|
|
}
|
2004-09-25 20:30:40 +00:00
|
|
|
return result; /* 1 if all of 'against' type, 2 if there are (also) Nones */
|
2003-05-17 04:29:49 +00:00
|
|
|
}
|
2003-06-22 20:14:11 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
PyObject *EXPP_tuple_repr( PyObject * self, int size )
|
2003-06-22 20:14:11 +00:00
|
|
|
{
|
2003-07-06 20:34:59 +00:00
|
|
|
PyObject *repr, *item;
|
2003-06-22 20:14:11 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/*@ note: a value must be built because the list is decrefed!
|
|
|
|
|
* otherwise we have nirvana pointers inside python.. */
|
|
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
repr = PyString_FromString( "" );
|
|
|
|
|
if( !repr )
|
|
|
|
|
return 0;
|
2003-06-22 20:14:11 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
item = PySequence_GetItem( self, 0 );
|
|
|
|
|
PyString_ConcatAndDel( &repr, PyObject_Repr( item ) );
|
|
|
|
|
Py_DECREF( item );
|
2003-06-22 20:14:11 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
for( i = 1; i < size; i++ ) {
|
|
|
|
|
item = PySequence_GetItem( self, i );
|
|
|
|
|
PyString_ConcatAndDel( &repr, PyObject_Repr( item ) );
|
|
|
|
|
Py_DECREF( item );
|
2003-06-22 20:14:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return repr;
|
|
|
|
|
}
|
2003-11-23 17:46:06 +00:00
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
|
/* Description: searches through a map for a pair with a given name. If the */
|
2004-09-25 20:30:40 +00:00
|
|
|
/* pair is present, its ival is stored in *ival and nonzero is */
|
|
|
|
|
/* returned. If the pair is absent, zero is returned. */
|
2003-11-23 17:46:06 +00:00
|
|
|
/****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
int EXPP_map_getIntVal( const EXPP_map_pair * map, const char *sval,
|
|
|
|
|
int *ival )
|
2003-11-23 17:46:06 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
while( map->sval ) {
|
|
|
|
|
if( StringEqual( sval, map->sval ) ) {
|
|
|
|
|
*ival = map->ival;
|
|
|
|
|
return 1;
|
2004-06-24 09:43:13 +00:00
|
|
|
}
|
2004-09-25 20:30:40 +00:00
|
|
|
++map;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2003-11-23 17:46:06 +00:00
|
|
|
}
|
|
|
|
|
|
- Blender: added option 'scriptsdir' to Blender.Get();
- small updates to the docs;
- Object: small fix to getMatrix: check during_script() to avoid undesired loops; added old behavior (pre 2.34) as option: .getMatrix('oldlocal');
- tentative fix for bug #1275: scene REDRAW scriptlinks were not being executed (the call to do so was missing):
http://projects.blender.org/tracker/index.php?func=detail&aid=1275&group_id=9&atid=125
added the call in drawview.c, in drawview3dspace(). This causes the scriptlink to be called for each visible view3d, but that's what happens with object redraw scriptlinks, too. Anyway, this is still a test. The place was chosen based on the idea that a scene redraw scriptlink is like an object redraw one, but for all objs in the scene at once.
- Window.Theme: new submodule, to get/set theme options in Blender;
- Added the script save_theme.py (Help menu for now), to save the current theme in Blender as an executable script (currently shown in the Scripts->Misc menu).
There's more work to do for themes, like defining a proper place for them in the interface, adding documentation (for now the added script and the ones it generates can give a pretty good idea of how to use the new module), probably extending themes to support SpaceScript and so on.
2004-09-21 05:28:17 +00:00
|
|
|
/* same as above, but string case is ignored */
|
2004-09-25 20:30:40 +00:00
|
|
|
int EXPP_map_case_getIntVal( const EXPP_map_pair * map, const char *sval,
|
|
|
|
|
int *ival )
|
- Blender: added option 'scriptsdir' to Blender.Get();
- small updates to the docs;
- Object: small fix to getMatrix: check during_script() to avoid undesired loops; added old behavior (pre 2.34) as option: .getMatrix('oldlocal');
- tentative fix for bug #1275: scene REDRAW scriptlinks were not being executed (the call to do so was missing):
http://projects.blender.org/tracker/index.php?func=detail&aid=1275&group_id=9&atid=125
added the call in drawview.c, in drawview3dspace(). This causes the scriptlink to be called for each visible view3d, but that's what happens with object redraw scriptlinks, too. Anyway, this is still a test. The place was chosen based on the idea that a scene redraw scriptlink is like an object redraw one, but for all objs in the scene at once.
- Window.Theme: new submodule, to get/set theme options in Blender;
- Added the script save_theme.py (Help menu for now), to save the current theme in Blender as an executable script (currently shown in the Scripts->Misc menu).
There's more work to do for themes, like defining a proper place for them in the interface, adding documentation (for now the added script and the ones it generates can give a pretty good idea of how to use the new module), probably extending themes to support SpaceScript and so on.
2004-09-21 05:28:17 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
while( map->sval ) {
|
2005-04-02 15:36:57 +00:00
|
|
|
if( !BLI_strcasecmp( sval, map->sval ) ) {
|
2004-09-25 20:30:40 +00:00
|
|
|
*ival = map->ival;
|
|
|
|
|
return 1;
|
- Blender: added option 'scriptsdir' to Blender.Get();
- small updates to the docs;
- Object: small fix to getMatrix: check during_script() to avoid undesired loops; added old behavior (pre 2.34) as option: .getMatrix('oldlocal');
- tentative fix for bug #1275: scene REDRAW scriptlinks were not being executed (the call to do so was missing):
http://projects.blender.org/tracker/index.php?func=detail&aid=1275&group_id=9&atid=125
added the call in drawview.c, in drawview3dspace(). This causes the scriptlink to be called for each visible view3d, but that's what happens with object redraw scriptlinks, too. Anyway, this is still a test. The place was chosen based on the idea that a scene redraw scriptlink is like an object redraw one, but for all objs in the scene at once.
- Window.Theme: new submodule, to get/set theme options in Blender;
- Added the script save_theme.py (Help menu for now), to save the current theme in Blender as an executable script (currently shown in the Scripts->Misc menu).
There's more work to do for themes, like defining a proper place for them in the interface, adding documentation (for now the added script and the ones it generates can give a pretty good idea of how to use the new module), probably extending themes to support SpaceScript and so on.
2004-09-21 05:28:17 +00:00
|
|
|
}
|
2004-09-25 20:30:40 +00:00
|
|
|
++map;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
- Blender: added option 'scriptsdir' to Blender.Get();
- small updates to the docs;
- Object: small fix to getMatrix: check during_script() to avoid undesired loops; added old behavior (pre 2.34) as option: .getMatrix('oldlocal');
- tentative fix for bug #1275: scene REDRAW scriptlinks were not being executed (the call to do so was missing):
http://projects.blender.org/tracker/index.php?func=detail&aid=1275&group_id=9&atid=125
added the call in drawview.c, in drawview3dspace(). This causes the scriptlink to be called for each visible view3d, but that's what happens with object redraw scriptlinks, too. Anyway, this is still a test. The place was chosen based on the idea that a scene redraw scriptlink is like an object redraw one, but for all objs in the scene at once.
- Window.Theme: new submodule, to get/set theme options in Blender;
- Added the script save_theme.py (Help menu for now), to save the current theme in Blender as an executable script (currently shown in the Scripts->Misc menu).
There's more work to do for themes, like defining a proper place for them in the interface, adding documentation (for now the added script and the ones it generates can give a pretty good idea of how to use the new module), probably extending themes to support SpaceScript and so on.
2004-09-21 05:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
2003-11-23 17:46:06 +00:00
|
|
|
/****************************************************************************/
|
|
|
|
|
/* Description: searches through a map for a pair with a given name. If the */
|
2004-09-25 20:30:40 +00:00
|
|
|
/* pair is present, its ival is stored in *ival and nonzero is */
|
|
|
|
|
/* returned. If the pair is absent, zero is returned. */
|
|
|
|
|
/* note: this function is identical to EXPP_map_getIntVal except that the */
|
|
|
|
|
/* output is stored in a short value. */
|
2003-11-23 17:46:06 +00:00
|
|
|
/****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
int EXPP_map_getShortVal( const EXPP_map_pair * map,
|
|
|
|
|
const char *sval, short *ival )
|
2003-11-23 17:46:06 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
while( map->sval ) {
|
|
|
|
|
if( StringEqual( sval, map->sval ) ) {
|
2005-07-18 03:50:37 +00:00
|
|
|
*ival = (short)map->ival;
|
2004-09-25 20:30:40 +00:00
|
|
|
return 1;
|
2004-06-24 09:43:13 +00:00
|
|
|
}
|
2004-09-25 20:30:40 +00:00
|
|
|
++map;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
2003-11-23 17:46:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
|
/* Description: searches through a map for a pair with a given ival. If the */
|
2004-09-25 20:30:40 +00:00
|
|
|
/* pair is present, a pointer to its name is stored in *sval */
|
|
|
|
|
/* and nonzero is returned. If the pair is absent, zero is */
|
|
|
|
|
/* returned. */
|
2003-11-23 17:46:06 +00:00
|
|
|
/****************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
int EXPP_map_getStrVal( const EXPP_map_pair * map, int ival,
|
|
|
|
|
const char **sval )
|
2003-11-23 17:46:06 +00:00
|
|
|
{
|
2004-09-25 20:30:40 +00:00
|
|
|
while( map->sval ) {
|
|
|
|
|
if( ival == map->ival ) {
|
2004-06-24 09:43:13 +00:00
|
|
|
*sval = map->sval;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
++map;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
BPython:
- Scripts:
fixed error in "Save Current Theme" which prevented it from automatically updating script registration in menus.
cosmetic changes in a couple of Campbell's sel_same.py script strings + more descriptive name for its new menu place (3d view, face mode -> select menu).
small updates to help_browser.py script.
The above changes are related to this:
- Added new script menu entries: Render (for exporters to renderers), Themes, FaceSelect (this already at the proper place). Updated Scripts win->Scripts menu so it won't show all available entries, only the ones we mean to see there.
- Updated menu registration so that scripts folders can become trees. The release/scripts/ dir should be updated soon with subdirs like converters/, modifiers/, generators/ or whatever -- better discuss first (or is it? /me afraid of long irc discussions during meetings :) ).
- Modules:
Blender: added 'udatadir' option to .Get() function and added var Blender.mode to tell if Blender is in bg or interactive mode.
NMesh: added Campbell's nmesh.transform(matrix, recalc_normals = False) method (reworked, so my fault if it doesn't work).
- Bugs fixed:
#2123: http://projects.blender.org/tracker/?func=detail&atid=125&aid=2123&group_id=9
Reported by Ken Hughes (thanks!), who also found the exact problem later (it was in Text.Load, not with script links -- if only I had checked emails these days ... lost > 1 hour today to find the problem: passed filename to M_Text_Load was later being written over by a function called by add_text). Also saw that Text.Load wasn't checking existence of passed filename (duh!), now it does.
#1655: http://projects.blender.org/tracker/?func=detail&atid=125&aid=1655&group_id=9
Reported by Chris Want (thanks!): command line "blender -P script" not working properly for bg mode ("blender -b blendfile -P script").
Had to make some small updates to get it working (bg mode for scripts was never explicitely handled, it worked due to collateral effects, let's say), interested readers can check the report after I update it or the API_intro.py doc file. After more testing we can make further updates. Updated many places to not call redraws if in bg mode, now it is officially available. Blender outputs its own info when rendering in bg mode, if that is considered a nuissance we'll have to add a few "if (during_script())" calls outside bpython.
- Removed a few warnings here and there and also updated docs.
2005-03-19 06:24:55 +00:00
|
|
|
/* Redraw wrappers */
|
|
|
|
|
|
|
|
|
|
/* this queues redraws if we're not in background mode: */
|
|
|
|
|
void EXPP_allqueue(unsigned short event, short val)
|
|
|
|
|
{
|
|
|
|
|
if (!G.background) allqueue(event, val);
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-24 09:43:13 +00:00
|
|
|
/************************************************************************/
|
|
|
|
|
/* Scriptlink-related functions, used by scene, object, etc. bpyobjects */
|
|
|
|
|
/************************************************************************/
|
2004-09-25 20:30:40 +00:00
|
|
|
PyObject *EXPP_getScriptLinks( ScriptLink * slink, PyObject * args,
|
|
|
|
|
int is_scene )
|
2004-06-24 09:43:13 +00:00
|
|
|
{
|
|
|
|
|
PyObject *list = NULL;
|
|
|
|
|
char *eventname = NULL;
|
|
|
|
|
int i, event = 0;
|
|
|
|
|
|
|
|
|
|
/* actually !scriptlink shouldn't happen ... */
|
2004-09-25 20:30:40 +00:00
|
|
|
if( !slink || !slink->totscript )
|
|
|
|
|
return EXPP_incr_ret( Py_None );
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
if( !PyArg_ParseTuple( args, "s", &eventname ) )
|
|
|
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
|
|
|
"expected event name (string) as argument" );
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
list = PyList_New( 0 );
|
|
|
|
|
if( !list )
|
|
|
|
|
return EXPP_ReturnPyObjError( PyExc_MemoryError,
|
|
|
|
|
"couldn't create PyList!" );
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
if( !strcmp( eventname, "FrameChanged" ) )
|
2004-06-24 09:43:13 +00:00
|
|
|
event = SCRIPT_FRAMECHANGED;
|
2004-09-25 20:30:40 +00:00
|
|
|
else if( !strcmp( eventname, "Redraw" ) )
|
2004-06-24 09:43:13 +00:00
|
|
|
event = SCRIPT_REDRAW;
|
BPython:
- Made Blender.event var (previously only used by script links) hold ascii value -- where it applies -- of current event during events callback registered with Draw.Register(gui, events, button_events). Useful for gui scripts like Campbell's Python console. No problem using this var to hold the value, since in gui scripts it was not used (always None).
- Updated Window and Window.Theme with new theme vars and the Time space.
- Script links:
-- Added "Render" event for script links (runs twice, second time as "PostEvent", for clean-up actions). Now FrameChanged links don't run when a single pic is rendered.
-- Added "Enable Script Links" button in the script buttons tab. Now this bit gets saved in .blends along with the rest of G.f, so users can define per .blend if they are on or off by default. "blender -y" also disables all slinks as happened before with OnLoad ones only.
-- Other small changes in the script buttons tab:
When a link is added (button "new"), it becomes the active one for the window, no need to press a button to reach it.
Also, a pupmenu showing all available texts is shown when "new" is pressed, so users can choose a text w/o having to type. Cancel the popup to leave the string button empty (link exists, but has no script assigned). A pulldown would be better UI-wise, but it's kinda weird to show both scripts and normal texts (Blender doesn't differentiate them) in a script links pulldown. With a popup we can show only texts ending in ".py" (not done in this commit, need opinions) and if the script has no or another extension, case of many in old and current .blend's, there's still the string box for writing its name.
-- Implemented Ton's space handler script links:
Right now only for the 3d View, but it's trivial to add for others. There are two types: EVENT, to receive 3d View events from a chosen window and DRAW, to draw on the window. Ton's idea was to give scripts a controlled way to integrate better within Blender.
Here's how it works:
- scripts must have a proper header, like:
# SPACEHANDLER.VIEW3D.EVENT
and then they are shown in 3d View's View menu, "Space Handler Scripts" submenu. Check (mark, click on it) a script to make it active.
EVENT handlers should consult the Blender.event var to get the current event, which can be compared with values from the Draw module:
import Blender
from Blender import Draw
evt = Blender.event
if evt == Draw.AKEY:
print "a"
elif evt == Draw.LEFTMOUSE:
print "left mouse button"
else:
return # ignore, pass event back to Blender
Blender.event = None # tell Blender not to process itself the event
DRAW handlers are free to draw to their owner 3D View. OpenGL attributes and modelview and projection matrices are pushed before running the handler and poped when it finishes.
To communicate between EVENT and DRAW handler scripts we have the Blender.Registry module, as always.
Still need to code some nice example, which should also serve to test properly space handlers. Simple tests went fine.
- doc updates about the additions.
=======
Note: the UI part of the space handlers and script links is of course open for changes, I just tried to make it understandable. Probably we won't use the scriptlinks icon for "None Available" (check 3d View -> View -> Space Handler Scripts), though it hints at what space handlers are. The tooltips may not be accepted either, since other menus don't use them. Opinions welcomed.
2005-05-08 21:20:34 +00:00
|
|
|
else if( !strcmp( eventname, "Render" ) )
|
|
|
|
|
event = SCRIPT_RENDER;
|
2004-09-25 20:30:40 +00:00
|
|
|
else if( is_scene && !strcmp( eventname, "OnLoad" ) )
|
2004-06-24 09:43:13 +00:00
|
|
|
event = SCRIPT_ONLOAD;
|
2004-09-25 20:30:40 +00:00
|
|
|
else if( is_scene && !strcmp( eventname, "OnSave" ) )
|
2004-08-17 04:26:00 +00:00
|
|
|
event = SCRIPT_ONSAVE;
|
2004-06-24 09:43:13 +00:00
|
|
|
else
|
2004-09-25 20:30:40 +00:00
|
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
|
|
|
"invalid event name" );
|
|
|
|
|
|
|
|
|
|
for( i = 0; i < slink->totscript; i++ ) {
|
|
|
|
|
if( ( slink->flag[i] == event ) && slink->scripts[i] )
|
|
|
|
|
PyList_Append( list,
|
|
|
|
|
PyString_FromString( slink->scripts[i]->
|
|
|
|
|
name + 2 ) );
|
2004-06-24 09:43:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return list;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-21 19:44:52 +00:00
|
|
|
PyObject *EXPP_clearScriptLinks( ScriptLink * slink, PyObject * args )
|
2004-06-24 09:43:13 +00:00
|
|
|
{
|
2005-04-21 19:44:52 +00:00
|
|
|
int i, j, totLinks, deleted = 0;
|
|
|
|
|
PyObject *seq = NULL;
|
|
|
|
|
ID **stmp = NULL;
|
|
|
|
|
short *ftmp = NULL;
|
|
|
|
|
|
|
|
|
|
/* check for an optional list of strings */
|
|
|
|
|
if( !PyArg_ParseTuple( args, "|O", &seq ) )
|
|
|
|
|
return ( EXPP_ReturnPyObjError
|
|
|
|
|
( PyExc_TypeError,
|
|
|
|
|
"expected no arguments or a list of strings" ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* if there was a parameter, handle it */
|
|
|
|
|
if ( seq != NULL ) {
|
|
|
|
|
/* check that parameter IS list of strings */
|
|
|
|
|
if ( !PyList_Check ( seq ) )
|
|
|
|
|
return ( EXPP_ReturnPyObjError
|
|
|
|
|
( PyExc_TypeError,
|
|
|
|
|
"expected a list of strings" ) );
|
|
|
|
|
|
|
|
|
|
totLinks = PyList_Size ( seq );
|
|
|
|
|
for ( i = 0 ; i < totLinks ; ++i ) {
|
|
|
|
|
if ( !PyString_Check ( PySequence_GetItem( seq, i ) ) )
|
|
|
|
|
return ( EXPP_ReturnPyObjError
|
|
|
|
|
( PyExc_TypeError,
|
|
|
|
|
"expected list to contain strings" ) );
|
|
|
|
|
}
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2005-04-21 19:44:52 +00:00
|
|
|
/*
|
|
|
|
|
parameters OK: now look for each script, and delete
|
|
|
|
|
its link as we find it (this handles multiple links)
|
|
|
|
|
*/
|
|
|
|
|
for ( i = 0 ; i < totLinks ; ++i )
|
|
|
|
|
{
|
|
|
|
|
char *str;
|
|
|
|
|
str = PyString_AsString ( PySequence_GetItem( seq, i ) );
|
|
|
|
|
for ( j = 0 ; j < slink->totscript ; ++j ) {
|
2005-12-10 19:36:05 +00:00
|
|
|
if ( slink->scripts[j] && !strcmp( slink->scripts[j]->name+2, str ) )
|
2005-04-21 19:44:52 +00:00
|
|
|
slink->scripts[j] = NULL;
|
2005-12-10 19:36:05 +00:00
|
|
|
if( !slink->scripts[j] )
|
2005-04-21 19:44:52 +00:00
|
|
|
++deleted;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* if no parameter, then delete all scripts */
|
|
|
|
|
else {
|
|
|
|
|
deleted = slink->totscript;
|
|
|
|
|
}
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2005-04-21 19:44:52 +00:00
|
|
|
/*
|
|
|
|
|
if not all scripts deleted, create new lists and copy remaining
|
|
|
|
|
links to them
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if ( slink->totscript > deleted ) {
|
2005-07-18 03:50:37 +00:00
|
|
|
slink->totscript = slink->totscript - (short)deleted;
|
2005-04-21 19:44:52 +00:00
|
|
|
|
|
|
|
|
stmp = slink->scripts;
|
|
|
|
|
slink->scripts =
|
|
|
|
|
MEM_mallocN( sizeof( ID * ) * ( slink->totscript ),
|
|
|
|
|
"bpySlinkL" );
|
|
|
|
|
|
|
|
|
|
ftmp = slink->flag;
|
|
|
|
|
slink->flag =
|
|
|
|
|
MEM_mallocN( sizeof( short * ) * ( slink->totscript ),
|
|
|
|
|
"bpySlinkF" );
|
|
|
|
|
|
|
|
|
|
for ( i = 0, j = 0 ; i < slink->totscript ; ++j ) {
|
|
|
|
|
if ( stmp[j] != NULL ) {
|
|
|
|
|
memcpy( slink->scripts+i, stmp+j, sizeof( ID * ) );
|
|
|
|
|
memcpy( slink->flag+i, ftmp+j, sizeof( short ) );
|
|
|
|
|
++i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MEM_freeN( stmp );
|
|
|
|
|
MEM_freeN( ftmp );
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2005-04-21 19:44:52 +00:00
|
|
|
/*EXPP_allqueue (REDRAWBUTSSCRIPT, 0 );*/
|
|
|
|
|
slink->actscript = 1;
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* all scripts deleted, so delete entire list and free memory */
|
|
|
|
|
|
|
|
|
|
if( slink->scripts )
|
|
|
|
|
MEM_freeN( slink->scripts );
|
|
|
|
|
if( slink->flag )
|
|
|
|
|
MEM_freeN( slink->flag );
|
|
|
|
|
|
|
|
|
|
slink->scripts = NULL;
|
|
|
|
|
slink->flag = NULL;
|
|
|
|
|
slink->totscript = slink->actscript = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return EXPP_incr_ret( Py_None );
|
2004-06-24 09:43:13 +00:00
|
|
|
}
|
|
|
|
|
|
2005-04-21 19:44:52 +00:00
|
|
|
|
|
|
|
|
PyObject *EXPP_addScriptLink(ScriptLink *slink, PyObject *args, int is_scene)
|
2004-06-24 09:43:13 +00:00
|
|
|
{
|
|
|
|
|
int event = 0, found_txt = 0;
|
|
|
|
|
void *stmp = NULL, *ftmp = NULL;
|
|
|
|
|
Text *bltxt = G.main->text.first;
|
|
|
|
|
char *textname = NULL;
|
|
|
|
|
char *eventname = NULL;
|
|
|
|
|
|
|
|
|
|
/* !scriptlink shouldn't happen ... */
|
2004-09-25 20:30:40 +00:00
|
|
|
if( !slink ) {
|
2005-04-21 19:44:52 +00:00
|
|
|
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
|
|
|
|
"internal error: no scriptlink!" );
|
2004-06-24 09:43:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
if( !PyArg_ParseTuple( args, "ss", &textname, &eventname ) )
|
2005-04-21 19:44:52 +00:00
|
|
|
return EXPP_ReturnPyObjError( PyExc_TypeError,
|
|
|
|
|
"expected two strings as arguments" );
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
while( bltxt ) {
|
|
|
|
|
if( !strcmp( bltxt->id.name + 2, textname ) ) {
|
2004-06-24 09:43:13 +00:00
|
|
|
found_txt = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
bltxt = bltxt->id.next;
|
|
|
|
|
}
|
|
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
if( !found_txt )
|
2005-04-21 19:44:52 +00:00
|
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
|
|
|
|
"no such Blender Text" );
|
2004-06-24 09:43:13 +00:00
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
if( !strcmp( eventname, "FrameChanged" ) )
|
2004-06-24 09:43:13 +00:00
|
|
|
event = SCRIPT_FRAMECHANGED;
|
2004-09-25 20:30:40 +00:00
|
|
|
else if( !strcmp( eventname, "Redraw" ) )
|
2004-06-24 09:43:13 +00:00
|
|
|
event = SCRIPT_REDRAW;
|
BPython:
- Made Blender.event var (previously only used by script links) hold ascii value -- where it applies -- of current event during events callback registered with Draw.Register(gui, events, button_events). Useful for gui scripts like Campbell's Python console. No problem using this var to hold the value, since in gui scripts it was not used (always None).
- Updated Window and Window.Theme with new theme vars and the Time space.
- Script links:
-- Added "Render" event for script links (runs twice, second time as "PostEvent", for clean-up actions). Now FrameChanged links don't run when a single pic is rendered.
-- Added "Enable Script Links" button in the script buttons tab. Now this bit gets saved in .blends along with the rest of G.f, so users can define per .blend if they are on or off by default. "blender -y" also disables all slinks as happened before with OnLoad ones only.
-- Other small changes in the script buttons tab:
When a link is added (button "new"), it becomes the active one for the window, no need to press a button to reach it.
Also, a pupmenu showing all available texts is shown when "new" is pressed, so users can choose a text w/o having to type. Cancel the popup to leave the string button empty (link exists, but has no script assigned). A pulldown would be better UI-wise, but it's kinda weird to show both scripts and normal texts (Blender doesn't differentiate them) in a script links pulldown. With a popup we can show only texts ending in ".py" (not done in this commit, need opinions) and if the script has no or another extension, case of many in old and current .blend's, there's still the string box for writing its name.
-- Implemented Ton's space handler script links:
Right now only for the 3d View, but it's trivial to add for others. There are two types: EVENT, to receive 3d View events from a chosen window and DRAW, to draw on the window. Ton's idea was to give scripts a controlled way to integrate better within Blender.
Here's how it works:
- scripts must have a proper header, like:
# SPACEHANDLER.VIEW3D.EVENT
and then they are shown in 3d View's View menu, "Space Handler Scripts" submenu. Check (mark, click on it) a script to make it active.
EVENT handlers should consult the Blender.event var to get the current event, which can be compared with values from the Draw module:
import Blender
from Blender import Draw
evt = Blender.event
if evt == Draw.AKEY:
print "a"
elif evt == Draw.LEFTMOUSE:
print "left mouse button"
else:
return # ignore, pass event back to Blender
Blender.event = None # tell Blender not to process itself the event
DRAW handlers are free to draw to their owner 3D View. OpenGL attributes and modelview and projection matrices are pushed before running the handler and poped when it finishes.
To communicate between EVENT and DRAW handler scripts we have the Blender.Registry module, as always.
Still need to code some nice example, which should also serve to test properly space handlers. Simple tests went fine.
- doc updates about the additions.
=======
Note: the UI part of the space handlers and script links is of course open for changes, I just tried to make it understandable. Probably we won't use the scriptlinks icon for "None Available" (check 3d View -> View -> Space Handler Scripts), though it hints at what space handlers are. The tooltips may not be accepted either, since other menus don't use them. Opinions welcomed.
2005-05-08 21:20:34 +00:00
|
|
|
else if( !strcmp( eventname, "Render" ) )
|
|
|
|
|
event = SCRIPT_RENDER;
|
2004-09-25 20:30:40 +00:00
|
|
|
else if( is_scene && !strcmp( eventname, "OnLoad" ) )
|
2004-06-24 09:43:13 +00:00
|
|
|
event = SCRIPT_ONLOAD;
|
2004-09-25 20:30:40 +00:00
|
|
|
else if( is_scene && !strcmp( eventname, "OnSave" ) )
|
2004-08-17 04:26:00 +00:00
|
|
|
event = SCRIPT_ONSAVE;
|
2004-06-24 09:43:13 +00:00
|
|
|
else
|
2005-04-24 19:32:04 +00:00
|
|
|
return EXPP_ReturnPyObjError( PyExc_AttributeError,
|
2005-04-21 19:44:52 +00:00
|
|
|
"invalid event name" );
|
2004-09-25 20:30:40 +00:00
|
|
|
|
|
|
|
|
stmp = slink->scripts;
|
|
|
|
|
slink->scripts =
|
|
|
|
|
MEM_mallocN( sizeof( ID * ) * ( slink->totscript + 1 ),
|
|
|
|
|
"bpySlinkL" );
|
|
|
|
|
|
|
|
|
|
ftmp = slink->flag;
|
|
|
|
|
slink->flag =
|
|
|
|
|
MEM_mallocN( sizeof( short * ) * ( slink->totscript + 1 ),
|
|
|
|
|
"bpySlinkF" );
|
|
|
|
|
|
|
|
|
|
if( slink->totscript ) {
|
|
|
|
|
memcpy( slink->scripts, stmp,
|
|
|
|
|
sizeof( ID * ) * ( slink->totscript ) );
|
|
|
|
|
MEM_freeN( stmp );
|
|
|
|
|
|
|
|
|
|
memcpy( slink->flag, ftmp,
|
|
|
|
|
sizeof( short ) * ( slink->totscript ) );
|
|
|
|
|
MEM_freeN( ftmp );
|
2004-06-24 09:43:13 +00:00
|
|
|
}
|
|
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
slink->scripts[slink->totscript] = ( ID * ) bltxt;
|
2005-07-18 03:50:37 +00:00
|
|
|
slink->flag[slink->totscript] = (short)event;
|
2004-06-24 09:43:13 +00:00
|
|
|
|
|
|
|
|
slink->totscript++;
|
|
|
|
|
|
2004-09-25 20:30:40 +00:00
|
|
|
if( slink->actscript < 1 )
|
|
|
|
|
slink->actscript = 1;
|
|
|
|
|
|
2005-04-21 19:44:52 +00:00
|
|
|
return EXPP_incr_ret (Py_None); /* normal exit */
|
2003-11-23 17:46:06 +00:00
|
|
|
}
|
2005-08-27 18:44:56 +00:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Utility routines to clamp and store various datatypes. The object type
|
|
|
|
|
* is checked and a exception is raised if it's not the correct type.
|
|
|
|
|
*
|
|
|
|
|
* Inputs:
|
|
|
|
|
* value: PyObject containing the new value
|
|
|
|
|
* param: pointer to destination variable
|
|
|
|
|
* max, min: range of values for clamping
|
2005-09-21 19:48:40 +00:00
|
|
|
* type: kind of pointer and data (uses the same characters as
|
|
|
|
|
* PyArgs_ParseTuple() and Py_BuildValue()
|
2005-08-27 18:44:56 +00:00
|
|
|
*
|
|
|
|
|
* Return 0 on success, -1 on error.
|
|
|
|
|
*/
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
int EXPP_setFloatClamped( PyObject *value, float *param,
|
|
|
|
|
float min, float max )
|
2005-08-27 18:44:56 +00:00
|
|
|
{
|
2005-09-21 19:48:40 +00:00
|
|
|
if( !PyNumber_Check ( value ) ) {
|
2005-08-27 18:44:56 +00:00
|
|
|
char errstr[128];
|
2005-09-21 19:48:40 +00:00
|
|
|
sprintf ( errstr, "expected float argument in [%f,%f]", min, max );
|
2005-08-27 18:44:56 +00:00
|
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
|
|
|
}
|
|
|
|
|
|
2005-09-26 14:46:14 +00:00
|
|
|
*param = EXPP_ClampFloat( (float)PyFloat_AsDouble( value ), min, max );
|
2005-08-27 18:44:56 +00:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
int EXPP_setIValueClamped( PyObject *value, void *param,
|
|
|
|
|
int min, int max, char type )
|
2005-08-27 18:44:56 +00:00
|
|
|
{
|
2005-09-21 19:48:40 +00:00
|
|
|
char errstr[128];
|
|
|
|
|
int number;
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
sprintf ( errstr, "expected int argument in [%d,%d]", min, max );
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
if( !PyInt_CheckExact ( value ) )
|
2005-08-27 18:44:56 +00:00
|
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
number = PyInt_AS_LONG( value );
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
switch ( type ) {
|
|
|
|
|
case 'b':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(char *)param = (char)EXPP_ClampInt( number, min, max );
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
case 'h':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(short *)param = (short)EXPP_ClampInt( number, min, max );
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
case 'H':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(unsigned short *)param = (unsigned short)EXPP_ClampInt( number, min, max );
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
case 'i':
|
|
|
|
|
*(int *)param = EXPP_ClampInt( number, min, max );
|
|
|
|
|
return 0;
|
|
|
|
|
default:
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_RuntimeError,
|
|
|
|
|
"EXPP_setIValueClamped(): invalid type code" );
|
2005-08-27 18:44:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-09-20 17:30:47 +00:00
|
|
|
int EXPP_setVec3Clamped( PyObject *value, float *param,
|
2006-09-17 02:31:16 +00:00
|
|
|
float min, float max )
|
|
|
|
|
{
|
|
|
|
|
if( VectorObject_Check( value ) ) {
|
|
|
|
|
VectorObject *vect = (VectorObject *)value;
|
|
|
|
|
if( vect->size == 3 ) {
|
2006-09-20 17:30:47 +00:00
|
|
|
param[0] = EXPP_ClampFloat( vect->vec[0], min, max );
|
|
|
|
|
param[1] = EXPP_ClampFloat( vect->vec[1], min, max );
|
|
|
|
|
param[2] = EXPP_ClampFloat( vect->vec[2], min, max );
|
2006-09-17 02:31:16 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (1) {
|
|
|
|
|
char errstr[128];
|
|
|
|
|
sprintf ( errstr, "expected vector argument in [%f,%f]", min, max );
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
|
2005-08-27 18:44:56 +00:00
|
|
|
/*
|
|
|
|
|
* Utility routines to range-check and store various datatypes. The object
|
|
|
|
|
* type is checked and a exception is raised if it's not the correct type.
|
|
|
|
|
* An exception is also raised if the value lies outside of the specified
|
|
|
|
|
* range.
|
|
|
|
|
*
|
|
|
|
|
* Inputs:
|
|
|
|
|
* value: PyObject containing the new value
|
|
|
|
|
* param: pointer to destination variable
|
|
|
|
|
* max, min: valid range for value
|
2005-09-21 19:48:40 +00:00
|
|
|
* type: kind of pointer and data (uses the same characters as
|
|
|
|
|
* PyArgs_ParseTuple() and Py_BuildValue()
|
2005-08-27 18:44:56 +00:00
|
|
|
*
|
|
|
|
|
* Return 0 on success, -1 on error.
|
|
|
|
|
*/
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
int EXPP_setFloatRange( PyObject *value, float *param,
|
|
|
|
|
float min, float max )
|
2005-08-27 18:44:56 +00:00
|
|
|
{
|
|
|
|
|
char errstr[128];
|
2005-10-03 22:06:16 +00:00
|
|
|
float number;
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
sprintf ( errstr, "expected int argument in [%f,%f]", min, max );
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
if( !PyNumber_Check ( value ) )
|
2005-08-27 18:44:56 +00:00
|
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
|
|
|
|
2005-10-03 22:06:16 +00:00
|
|
|
number = (float)PyFloat_AsDouble( value );
|
2005-08-27 18:44:56 +00:00
|
|
|
if ( number < min || number > max )
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_ValueError, errstr );
|
|
|
|
|
|
|
|
|
|
*param = number;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
int EXPP_setIValueRange( PyObject *value, void *param,
|
|
|
|
|
int min, int max, char type )
|
2005-08-27 18:44:56 +00:00
|
|
|
{
|
|
|
|
|
char errstr[128];
|
2005-09-21 19:48:40 +00:00
|
|
|
int number;
|
2005-08-27 18:44:56 +00:00
|
|
|
|
|
|
|
|
sprintf ( errstr, "expected int argument in [%d,%d]", min, max );
|
|
|
|
|
|
|
|
|
|
if( !PyInt_CheckExact ( value ) )
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_TypeError, errstr );
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
number = PyInt_AS_LONG( value );
|
|
|
|
|
if( number < min || number > max )
|
2005-08-27 18:44:56 +00:00
|
|
|
return EXPP_ReturnIntError( PyExc_ValueError, errstr );
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
switch ( type ) {
|
|
|
|
|
case 'b':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(char *)param = (char)number;
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
case 'h':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(short *)param = (short)number;
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
case 'H':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(unsigned short *)param = (unsigned short)number;
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
case 'i':
|
|
|
|
|
*(int *)param = number;
|
|
|
|
|
return 0;
|
|
|
|
|
default:
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_RuntimeError,
|
|
|
|
|
"EXPP_setIValueRange(): invalid type code" );
|
|
|
|
|
}
|
2005-08-27 18:44:56 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
/*
|
|
|
|
|
* Utility routines to handle all attribute setters which use module
|
|
|
|
|
* constants. Generic pointer to destination variable is used, and typecast
|
|
|
|
|
* to the appropriate type based on the "type" specifier.
|
|
|
|
|
*
|
|
|
|
|
* Inputs:
|
|
|
|
|
* constant: constant_Type value
|
|
|
|
|
* param: pointer to destination variable
|
|
|
|
|
* type: kind of pointer and data
|
|
|
|
|
*
|
|
|
|
|
* Return 0 on success, -1 on error.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int EXPP_setModuleConstant ( BPy_constant *constant, void *param, char type )
|
2005-08-27 18:44:56 +00:00
|
|
|
{
|
2005-09-21 19:48:40 +00:00
|
|
|
PyObject *item;
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
if( constant->ob_type != &constant_Type )
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_TypeError,
|
|
|
|
|
"expected module constant" );
|
|
|
|
|
|
|
|
|
|
item = PyDict_GetItemString( constant->dict, "value" );
|
|
|
|
|
if( !item )
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_RuntimeError,
|
|
|
|
|
"module constant has no \"value\" key" );
|
|
|
|
|
|
|
|
|
|
switch ( type ) {
|
|
|
|
|
case 'h':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(short *)param = (short)PyInt_AS_LONG( item );
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
case 'i':
|
|
|
|
|
*(int *)param = PyInt_AS_LONG( item );
|
|
|
|
|
return 0;
|
|
|
|
|
case 'f':
|
2005-09-26 14:46:14 +00:00
|
|
|
*(float *)param = (float)PyFloat_AS_DOUBLE( item );
|
2006-07-27 01:18:21 +00:00
|
|
|
Py_DECREF(item); /* line above increfs */
|
2005-09-21 19:48:40 +00:00
|
|
|
return 0;
|
|
|
|
|
default:
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_RuntimeError,
|
|
|
|
|
"EXPP_setModuleConstant(): invalid type code" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Utility routines to get/set bits in bitfields. Adapted from code in
|
|
|
|
|
* sceneRender.c (thanks, ascotan!).
|
|
|
|
|
*
|
|
|
|
|
* Inputs:
|
|
|
|
|
* param: pointer to source/destination variable
|
|
|
|
|
* setting: the bit to get/set
|
|
|
|
|
* type: pointer type ('h' == short, 'i' == integer)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
PyObject *EXPP_getBitfield( void *param, int setting, char type )
|
|
|
|
|
{
|
|
|
|
|
switch ( type ) {
|
|
|
|
|
case 'b':
|
|
|
|
|
return (*(char *)param & setting)
|
|
|
|
|
? EXPP_incr_ret_True() : EXPP_incr_ret_False();
|
|
|
|
|
case 'h':
|
|
|
|
|
return (*(short *)param & setting)
|
|
|
|
|
? EXPP_incr_ret_True() : EXPP_incr_ret_False();
|
|
|
|
|
case 'i':
|
|
|
|
|
return (*(int *)param & setting)
|
|
|
|
|
? EXPP_incr_ret_True() : EXPP_incr_ret_False();
|
|
|
|
|
default:
|
|
|
|
|
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
|
|
|
|
"EXPP_getBit(): invalid type code" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int EXPP_setBitfield( PyObject * value, void *param, int setting, char type )
|
|
|
|
|
{
|
2006-05-01 05:28:51 +00:00
|
|
|
int flag = PyObject_IsTrue( value );
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
switch ( type ) {
|
|
|
|
|
case 'b':
|
|
|
|
|
if ( flag )
|
|
|
|
|
*(char *)param |= setting;
|
|
|
|
|
else
|
|
|
|
|
*(char *)param &= ~setting;
|
|
|
|
|
return 0;
|
|
|
|
|
case 'h':
|
|
|
|
|
if ( flag )
|
|
|
|
|
*(short *)param |= setting;
|
|
|
|
|
else
|
|
|
|
|
*(short *)param &= ~setting;
|
|
|
|
|
return 0;
|
|
|
|
|
case 'i':
|
|
|
|
|
if ( flag )
|
|
|
|
|
*(int *)param |= setting;
|
|
|
|
|
else
|
|
|
|
|
*(int *)param &= ~setting;
|
|
|
|
|
return 0;
|
|
|
|
|
default:
|
|
|
|
|
return EXPP_ReturnIntError( PyExc_RuntimeError,
|
|
|
|
|
"EXPP_setBit(): invalid type code" );
|
|
|
|
|
}
|
2005-08-27 18:44:56 +00:00
|
|
|
}
|
|
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
/*
|
|
|
|
|
* Procedure to handle older setStuff() methods. Assumes that argument
|
|
|
|
|
* is a tuple with one object, and so grabs the object and passes it to
|
|
|
|
|
* the specified tp_getset setter for the corresponding attribute.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
PyObject *EXPP_setterWrapper ( PyObject * self, PyObject * args,
|
|
|
|
|
setter func)
|
2005-08-27 18:44:56 +00:00
|
|
|
{
|
2005-09-21 19:48:40 +00:00
|
|
|
int error;
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
if ( !PyTuple_Check( args ) || PyTuple_Size( args ) != 1 )
|
|
|
|
|
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
|
|
|
|
"expected tuple of one item" );
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-10-03 22:06:16 +00:00
|
|
|
error = func ( self, PyTuple_GET_ITEM( args, 0 ), NULL );
|
2005-09-21 19:48:40 +00:00
|
|
|
if ( !error ) {
|
|
|
|
|
Py_INCREF( Py_None );
|
|
|
|
|
return Py_None;
|
|
|
|
|
} else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
/*
|
|
|
|
|
* Procedure to handle older setStuff() methods. Assumes that argument
|
|
|
|
|
* is a tuple, so just passes it to the specified tp_getset setter for
|
|
|
|
|
* the corresponding attribute.
|
|
|
|
|
*/
|
2005-08-27 18:44:56 +00:00
|
|
|
|
2005-09-21 19:48:40 +00:00
|
|
|
PyObject *EXPP_setterWrapperTuple ( PyObject * self, PyObject * args,
|
|
|
|
|
setter func)
|
|
|
|
|
{
|
|
|
|
|
int error;
|
|
|
|
|
|
|
|
|
|
if ( !PyTuple_Check( args ) )
|
|
|
|
|
return EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
|
|
|
|
"expected tuple" );
|
|
|
|
|
|
|
|
|
|
error = func ( self, args, NULL );
|
|
|
|
|
if ( !error ) {
|
|
|
|
|
Py_INCREF( Py_None );
|
|
|
|
|
return Py_None;
|
|
|
|
|
} else
|
|
|
|
|
return NULL;
|
2005-08-27 18:44:56 +00:00
|
|
|
}
|
2005-09-21 19:48:40 +00:00
|
|
|
|
2005-11-30 08:18:06 +00:00
|
|
|
/*
|
|
|
|
|
* Helper to keep dictionaries from causing memory leaks. When some object
|
|
|
|
|
* is just created to be added to the dictionary, its reference count needs
|
|
|
|
|
* to be decremented so it can be reclaimed.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
int EXPP_dict_set_item_str( PyObject *dict, char *key, PyObject *value)
|
|
|
|
|
{
|
|
|
|
|
/* add value to dictionary */
|
|
|
|
|
int ret = PyDict_SetItemString(dict, key, value);
|
|
|
|
|
Py_DECREF( value ); /* delete original */
|
|
|
|
|
return ret;
|
|
|
|
|
}
|