This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/python/api2_2x/logic.c
Joseph Gilbert 3a816f1c30 - new internal Property module
- Object support for add/remove/modify object Properties
2004-06-11 13:15:50 +00:00

469 lines
16 KiB
C

/*
*
* ***** 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,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*
* This is a new part of Blender.
*
* Contributor(s): Joseph Gilbert
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
#include "logic.h"
#include "gen_utils.h"
#include <MEM_guardedalloc.h>
#include <BLI_blenlib.h>
//--------------- Python BPy_Property methods declarations:---------------------------------------------------
static PyObject *Property_getName (BPy_Property * self);
static PyObject *Property_setName (BPy_Property * self, PyObject * args);
static PyObject *Property_getData (BPy_Property * self);
static PyObject *Property_setData (BPy_Property * self, PyObject * args);
static PyObject *Property_getType (BPy_Property * self);
//--------------- Python BPy_Property methods table:-----------------------------------------------------------------
static PyMethodDef BPy_Property_methods[] = {
{"getName", (PyCFunction) Property_getName, METH_NOARGS,
"() - return Property name"},
{"setName", (PyCFunction)Property_setName, METH_VARARGS,
"() - set the name of this Property"},
{"getData", (PyCFunction) Property_getData, METH_NOARGS,
"() - return Property data"},
{"setData", (PyCFunction)Property_setData, METH_VARARGS,
"() - set the data of this Property"},
{"getType", (PyCFunction) Property_getType, METH_NOARGS,
"() - return Property type"},
{NULL, NULL, 0, NULL}
};
//--------------- Python TypeProperty callback function prototypes----------------------------------------
static void Property_dealloc (BPy_Property * Property);
static PyObject *Property_getAttr (BPy_Property * Property, char *name);
static int Property_setAttr (BPy_Property * Property, char *name, PyObject * v);
static PyObject *Property_repr (BPy_Property * Property);
static int Property_compare (BPy_Property * a1, BPy_Property * a2);
//--------------- Python TypeProperty structure definition------------------------------------------------------
PyTypeObject property_Type = {
PyObject_HEAD_INIT (NULL) 0, /* ob_size */
"Blender Property", /* tp_name */
sizeof (BPy_Property), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) Property_dealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc) Property_getAttr, /* tp_getattr */
(setattrfunc) Property_setAttr, /* tp_setattr */
(cmpfunc) Property_compare, /* tp_compare */
(reprfunc) Property_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_as_hash */
0, 0, 0, 0, 0, 0,
0, /* tp_doc */
0, 0, 0, 0, 0, 0,
BPy_Property_methods, /* tp_methods */
0, /* tp_members */
};
//--------------- Property module internal callbacks-------------------------------------------------------------
//--------------- updatePyProperty-------------------------------------------------------------------------------------
int
updatePyProperty(BPy_Property *self)
{
if(!self->property){
return 0; //nothing to update - not linked
}else{
BLI_strncpy(self->name, self->property->name, 32);
self->type = self->property->type;
if(self->property->type == PROP_BOOL){
if(*((int*)&self->property->poin)){
self->data = EXPP_incr_ret(Py_True);
}else{
self->data = EXPP_incr_ret(Py_False);
}
}else if (self->property->type == PROP_INT){
self->data = PyInt_FromLong(self->property->data);
}else if (self->property->type == PROP_FLOAT){
self->data = PyFloat_FromDouble(*((float*)&self->property->data));
}else if (self->property->type == PROP_TIME){
self->data = PyFloat_FromDouble(*((float*)&self->property->data));
}else if (self->property->type == PROP_STRING){
self->data = PyString_FromString(self->property->poin);
}
return 1;
}
return 0;
}
//--------------- updatePropertyData-------------------------------------------------------------------------------------
int
updateProperyData(BPy_Property *self)
{
if(!self->property){
//nothing to update - not linked
return 0;
}else{
BLI_strncpy(self->property->name, self->name, 32);
self->property->type = self->type;
if(PyInt_Check(self->data)){
*((int*)&self->property->data) = (int)PyInt_AsLong(self->data);
}else if (PyFloat_Check(self->data)){
*((float *)&self->property->data) = (float)PyFloat_AsDouble(self->data);
}else if (PyString_Check(self->data)){
BLI_strncpy(self->property->poin, PyString_AsString(self->data), MAX_PROPSTRING);
}
return 1;
}
return 0;
}
//--------------- checkValidData_ptr-------------------------------------------------------------------------------------
int
checkValidData_ptr(BPy_Property *self)
{
int length;
//test pointer to see if data was removed (oops)
length = MEM_allocN_len(self->property);
if(length != sizeof(bProperty)){ //data was freed
self->property = NULL;
return 0;
}else{ //it's ok as far as we can tell
return 1;
}
}
//---------------BPy_Property internal callbacks/methods---------------------------------------------
//--------------- dealloc---------------------------------------------------------------------------------------
static void
Property_dealloc (BPy_Property * self)
{
PyMem_Free (self->name);
PyObject_DEL (self);
}
//---------------getattr---------------------------------------------------------------------------------------
static PyObject *
Property_getAttr (BPy_Property * self, char *name)
{
PyObject *attr = Py_None;
checkValidData_ptr(self);
if (strcmp (name, "name") == 0)
attr = Property_getName (self);
else if (strcmp (name, "data") == 0)
attr = Property_getData (self);
else if (strcmp (name, "type") == 0)
attr = Property_getType (self);
else if (strcmp (name, "__members__") == 0){
attr = Py_BuildValue ("[s,s,s]", "name", "data","type");
}
if (!attr)
return (EXPP_ReturnPyObjError (PyExc_MemoryError,"couldn't create PyObject"));
if (attr != Py_None) return attr;
return Py_FindMethod (BPy_Property_methods, (PyObject *) self, name);
}
//--------------- setattr---------------------------------------------------------------------------------------
static int
Property_setAttr (BPy_Property * self, char *name, PyObject * value)
{
PyObject *valtuple;
PyObject *error = NULL;
checkValidData_ptr(self);
valtuple = Py_BuildValue ("(O)", value);
if (!valtuple)
return EXPP_ReturnIntError (PyExc_MemoryError,
"PropertySetAttr: couldn't create tuple");
if (strcmp (name, "name") == 0)
error = Property_setName (self, valtuple);
else if (strcmp(name, "data") == 0)
error = Property_setData (self, valtuple);
else{
Py_DECREF (valtuple);
return (EXPP_ReturnIntError (PyExc_KeyError, "attribute not found"));
}
Py_DECREF (valtuple);
if (error != Py_None) return -1;
Py_DECREF (Py_None);
return 0;
}
//--------------- repr---------------------------------------------------------------------------------------
static PyObject *
Property_repr (BPy_Property * self)
{
checkValidData_ptr(self);
if (self->property){
return PyString_FromFormat ("[Property \"%s\"]", self->property->name);
}else{
return PyString_FromFormat ("[Property \"%s\"]", self->name);
}
}
//--------------- compare---------------------------------------------------------------------------------------
//compares property.name and property.data
static int
Property_compare (BPy_Property * a, BPy_Property * b)
{
BPy_Property *py_propA, *py_propB;
int retval = -1;
checkValidData_ptr(a);
checkValidData_ptr(b);
//2 python objects
if (!a->property && !b->property) {
if(a->type != b->type) retval = -1;
if(BLI_streq(a->name, b->name)){
retval = PyObject_Compare(a->data, b->data);
}else retval = -1;
}else if (a->property && b->property){ //2 real properties
if(a->property->type != b->property->type) retval = -1;
if(BLI_streq(a->property->name, b->property->name)){
if(a->property->type == PROP_BOOL || a->property->type == PROP_INT){
if(a->property->data == b->property->data) retval = 0;
else retval = -1;
}else if (a->property->type == PROP_FLOAT || a->property->type == PROP_TIME){
if(*((float*)&a->property->data) == *((float*)&b->property->data)) retval = 0;
else retval = -1;
}else if (a->property->type == PROP_STRING){
if(BLI_streq(a->property->poin, b->property->poin)) retval = 0;
else retval = -1;
}
}else retval = -1;
}else{ //1 real 1 python
if(!a->property){
py_propA = a; py_propB = b;
}else {
py_propA = b; py_propB = a;
}
if(py_propB->property->type != py_propA->type) retval = -1;
if(BLI_streq(py_propB->property->name, py_propA->name)){
if(py_propB->property->type == PROP_BOOL ||
py_propB->property->type == PROP_INT){
retval = PyObject_Compare(py_propA->data,
PyInt_FromLong(py_propB->property->data));
}else if (py_propB->property->type == PROP_FLOAT ||
py_propB->property->type == PROP_TIME){
retval = PyObject_Compare(py_propA->data,
PyFloat_FromDouble(*((float*)&py_propB->property->data)));
}else if (py_propB->property->type == PROP_STRING){
retval = PyObject_Compare(py_propA->data,
PyString_FromString(py_propB->property->poin));
}
}else retval = -1;
}
return retval;
}
//--------------- Property visible functions--------------------------------------------------------------------
//--------------- Property_CreatePyObject--------------------------------------------------------------------
PyObject *
Property_CreatePyObject (struct bProperty * Property)
{
BPy_Property *py_property;
py_property = (BPy_Property *)PyObject_NEW (BPy_Property, &property_Type);
//set the struct flag
py_property->property = Property;
//allocate space for python vars
py_property->name= PyMem_Malloc (32);
if(!updatePyProperty(py_property))
return (EXPP_ReturnPyObjError (PyExc_AttributeError , "Property struct empty"));
return ((PyObject *) py_property);
}
//--------------- Property_CheckPyObject--------------------------------------------------------------------
int
Property_CheckPyObject (PyObject * py_obj)
{
return (py_obj->ob_type == &property_Type);
}
//--------------- Property_FromPyObject--------------------------------------------------------------------
struct bProperty *
Property_FromPyObject (PyObject * py_obj)
{
BPy_Property *py_property;
py_property = (BPy_Property *) py_obj;
if (!py_property->property) return NULL;
else return (py_property->property);
}
//--------------- newPropertyObject()----------------------------------------------------------------------------
PyObject *
newPropertyObject (char *name, PyObject *data, int type)
{
BPy_Property *py_property;
py_property = (BPy_Property *)PyObject_NEW (BPy_Property, &property_Type);
py_property->name= PyMem_Malloc (32);
py_property->property = NULL;
BLI_strncpy(py_property->name, name, 32);
py_property->data = data;
py_property->type = type;
return (PyObject*)py_property;
}
//--------------- Python BPy_Property methods------------------------------------------------------------------
//--------------- BPy_Property.getName()--------------------------------------------------------------------------
static PyObject *
Property_getName (BPy_Property * self)
{
PyObject *attr = NULL;
if (!self->property) attr = PyString_FromString (self->name);
else attr = PyString_FromString (self->property->name);
if (attr) return attr;
return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
"couldn't get Property.name attribute"));
}
//--------------- BPy_Property.setName()--------------------------------------------------------------------------
static PyObject *
Property_setName (BPy_Property * self, PyObject * args)
{
char *name;
if (!PyArg_ParseTuple (args, "s", &name))
return (EXPP_ReturnPyObjError (PyExc_AttributeError,
"expected string argument"));
if (!self->property){
BLI_strncpy(self->name, name, 32);
}else{
BLI_strncpy(self->property->name, name, 32);
updatePyProperty(self);
}
return EXPP_incr_ret (Py_None);
}
//--------------- BPy_Property.getData()--------------------------------------------------------------------------
static PyObject *
Property_getData (BPy_Property * self)
{
PyObject *attr = NULL;
if (!self->property) {
attr = EXPP_incr_ret(self->data);
}else{
if(self->property->type == PROP_BOOL){
if(*((int*)&self->property->poin))
attr = EXPP_incr_ret(Py_True);
else
attr = EXPP_incr_ret(Py_False);
}else if (self->property->type == PROP_INT){
attr = PyInt_FromLong(self->property->data);
}else if (self->property->type == PROP_FLOAT ||
self->property->type == PROP_TIME){
attr = PyFloat_FromDouble(*((float*)&self->property->data));
}else if (self->property->type == PROP_STRING){
attr = PyString_FromString(self->property->poin);
}
}
if (attr) return attr;
return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
"couldn't get Property.name attribute"));
}
//--------------- BPy_Property.setData()--------------------------------------------------------------------------
static PyObject *
Property_setData (BPy_Property * self, PyObject * args)
{
PyObject *data;
char *type_str = NULL;
int type = -1;
short *p_type = NULL;
if (!PyArg_ParseTuple (args, "O|s", &data, &type_str))
return (EXPP_ReturnPyObjError (PyExc_AttributeError,
"expected object and optional string argument"));
if(!PyInt_Check(data) && !PyFloat_Check(data) && !PyString_Check(data))
return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
"float, int, or string expected as data"));
//parse property name
if(type_str){
if(BLI_streq(type_str, "BOOL")) type = PROP_BOOL;
else if (BLI_streq(type_str, "INT")) type = PROP_INT;
else if (BLI_streq(type_str, "FLOAT")) type = PROP_FLOAT;
else if (BLI_streq(type_str, "TIME")) type = PROP_TIME;
else if (BLI_streq(type_str, "STRING")) type = PROP_STRING;
else return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
"BOOL, INT, FLOAT, TIME or STRING expected"));
}
//get pointer to type
if(self->property) p_type = &self->property->type;
else p_type = &self->type;
//set the type
if(PyInt_Check(data)){
if(type == -1 || type == PROP_INT) *p_type = PROP_INT;
else *p_type = PROP_BOOL;
}else if(PyFloat_Check(data)){
if(type == -1 || type == PROP_FLOAT) *p_type = PROP_FLOAT;
else *p_type = PROP_TIME;
}else if(PyString_Check(data)){
if(type == -1 || type == PROP_STRING) *p_type = PROP_STRING;
}else{
return (EXPP_ReturnPyObjError (PyExc_RuntimeError,
"cant set unknown data type"));
}
//set the data
if(self->property){
if(PyInt_Check(data)){
*((int*)&self->property->data) = (int)PyInt_AsLong(data);
}else if (PyFloat_Check(data)){
*((float *)&self->property->data) = (float)PyFloat_AsDouble(data);
}else if (PyString_Check(data)){
BLI_strncpy(self->property->poin, PyString_AsString(data), MAX_PROPSTRING);
}
updatePyProperty(self);
}else{
self->data = data;
}
return EXPP_incr_ret (Py_None);
}
//--------------- BPy_Property.getType()--------------------------------------------------------------------------
static PyObject *
Property_getType (BPy_Property * self)
{
PyObject *attr = Py_None;
int type;
if(self->property) type = self->property->type;
else type = self->type;
if(type == PROP_BOOL) attr = Py_BuildValue("s", "BOOL");
else if (type == PROP_INT) attr = Py_BuildValue("s", "INT");
else if (type == PROP_FLOAT) attr = Py_BuildValue("s", "FLOAT");
else if (type == PROP_STRING) attr = Py_BuildValue("s", "STRING");
else if (type == PROP_TIME) attr = Py_BuildValue("s", "TIME");
return attr;
}