/** * $Id:$ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * The contents of this file may be used under the terms of either the GNU * General Public License Version 2 or later (the "GPL", see * http://www.gnu.org/licenses/gpl.html ), or the Blender License 1.0 or * later (the "BL", see http://www.blender.org/BL/ ) which has to be * bought from the Blender Foundation to become active, in which case the * above mentioned GPL option does not apply. * * The Original Code is Copyright (C) 2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ /* python code for Blender, written by Daniel Dunbar */ /* Version: $Id: py_datablock.c,v 1.8 2000/07/21 09:05:28 nzc Exp $ */ #include "blender.h" #include "py_blender.h" ID *find_datablock_from_list(ID *list, char *name) { while (list) { if(STREQ(name, list->name+2)) break; list= list->next; } return list; } #define DATABLOCK_GET(uname, docname, list) \ static char uname##_Get_doc[]= \ "([name]) - Get " #docname "s from Blender\n" \ "\n" \ "[name] The name of the " #docname " to return\n" \ "\n" \ "Returns a list of all " #docname "s if name is not specified"; \ \ static PyObject* uname##_Get (PyObject *self, PyObject *args) { \ return py_find_from_list(list, args); \ } PyObject *named_enum_get(int val, NamedEnum *enums) { while (enums->name) { if (enums->num == val) return PyString_FromString(enums->name); enums++; } PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown enumerated type"); return NULL; } int named_enum_set(char *name, NamedEnum *enums) { while (enums->name) { if (STREQ(enums->name, name)) return enums->num; enums++; } return -1; } static int calc_offset_subsize(int *dlist, int *idx, int *subsize) { int n= *dlist; if (n<=0) { *subsize= -n; return 0; } else { int ss; int off= calc_offset_subsize(dlist+1, idx+1, &ss); *subsize= n*ss; return off + (*idx)*ss; } } static int calc_offset(int *dlist, int *idx) { int subsize; return calc_offset_subsize(dlist, idx, &subsize); } static void *get_db_ptr(DataBlockProperty *prop, char *structname, void *struct_ptr) { int size, offset= findstruct_offset(structname, prop->struct_name); void *ptr= struct_ptr; if (offset==-1) { printf ("Internal error, Invalid prop entry\n"); return NULL; } ptr= (void *) (((char *)ptr) + offset); offset= calc_offset(prop->dlist, prop->idx); ptr= (void *) (((char *)ptr) + offset); return ptr; } PyObject *datablock_getattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr) { if (STREQ(name, "properties")) { PyObject *l= PyList_New(0); DataBlockProperty *p= props; while (p->public_name) { PyList_Append(l, PyString_FromString(p->public_name)); p++; } return l; } while (props->public_name) { if (STREQ(name, props->public_name)) { void *ptr; int val; DBPtrToObFP conv_fp; if (props->handling==DBP_HANDLING_NONE || props->handling==DBP_HANDLING_NENM) { ptr= get_db_ptr(props, structname, struct_ptr); if (!ptr) return NULL; } else if (props->handling==DBP_HANDLING_FUNC) { DBGetPtrFP fp= (DBGetPtrFP) props->extra1; ptr= fp(struct_ptr, props->struct_name, 0); if (!ptr) return NULL; } switch(props->type) { case DBP_TYPE_CHA: val= *((char *)ptr); if (props->handling==DBP_HANDLING_NENM) return named_enum_get(val, props->extra1); else return PyInt_FromLong(val); case DBP_TYPE_SHO: val= *((short *)ptr); if (props->handling==DBP_HANDLING_NENM) return named_enum_get(val, props->extra1); else return PyInt_FromLong(val); case DBP_TYPE_INT: val= *((int *)ptr); if (props->handling==DBP_HANDLING_NENM) return named_enum_get(val, props->extra1); else return PyInt_FromLong(val); case DBP_TYPE_FLO: return PyFloat_FromDouble ( *((float *)ptr) ); case DBP_TYPE_VEC: return newVectorObject ( ((float *)ptr), (int) props->min ); case DBP_TYPE_FUN: conv_fp= (DBPtrToObFP) props->extra2; return conv_fp( ptr ); default: PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type"); return NULL; } } props++; } PyErr_SetString(PyExc_AttributeError, name); return NULL; } int datablock_setattr(DataBlockProperty *props, char *structname, char *name, void *struct_ptr, PyObject *setto) { while (props->public_name) { if (STREQ(props->public_name, name)) { void *ptr; int type; DBSetPtrFP conv_fp; int clamp= props->min!=props->max; int enum_val= -1; char cha_data; short sho_data; int int_data; float flo_data; char* str_data; type= props->stype; if (type==DBP_TYPE_NON) type= props->type; if (props->handling==DBP_HANDLING_NONE) { ptr= get_db_ptr(props, structname, struct_ptr); if (!ptr) return 0; } else if (props->handling==DBP_HANDLING_FUNC) { if (type!=DBP_TYPE_FUN) { DBGetPtrFP fp= (DBGetPtrFP) props->extra1; ptr= fp(struct_ptr, props->struct_name, 1); if (!ptr) return 0; } } else if (props->handling==DBP_HANDLING_NENM) { char *str; if (!PyArg_Parse(setto, "s", &str)) return -1; ptr= get_db_ptr(props, structname, struct_ptr); if (!ptr) return 0; enum_val= named_enum_set(str, props->extra1); if (enum_val==-1) return py_err_ret_int(PyExc_AttributeError, "invalid setting for field"); } switch(type) { case DBP_TYPE_CHA: if (enum_val==-1) { if (!PyArg_Parse(setto, "b", &cha_data)) return -1; } else cha_data= (char) enum_val; if (clamp) CLAMP(cha_data, (char) props->min, (char) props->max); *((char *)ptr)= cha_data; return 0; case DBP_TYPE_SHO: if (enum_val==-1) { if (!PyArg_Parse(setto, "h", &sho_data)) return -1; } else sho_data= (short) enum_val; if (clamp) CLAMP(sho_data, (short) props->min, (short) props->max); *((short *)ptr)= sho_data; return 0; case DBP_TYPE_INT: if (enum_val==-1) { if (!PyArg_Parse(setto, "i", &int_data)) return -1; } else int_data= (int) enum_val; if (clamp) CLAMP(int_data, (int) props->min, (int) props->max); *((int *)ptr)= int_data; return 0; case DBP_TYPE_FLO: if (!PyArg_Parse(setto, "f", &flo_data)) return -1; if (clamp) CLAMP(flo_data, (float) props->min, (float) props->max); *((float *)ptr)= flo_data; return 0; case DBP_TYPE_VEC: return py_err_ret_int(PyExc_AttributeError, "cannot directly assign to vector, use slice assignment instead"); case DBP_TYPE_FUN: conv_fp= (DBSetPtrFP) props->extra3; if (conv_fp) return conv_fp( struct_ptr, props->struct_name, setto ); else return py_err_ret_int(PyExc_AttributeError, "cannot directly assign to item"); default: PyErr_SetString(PyExc_AttributeError, "Internal error, Unknown prop type"); return -1; } } props++; } PyErr_SetString(PyExc_AttributeError, name); return -1; } /*********************/ /* Texture Datablocks */ /* DATABLOCK_GET(Texture, texture, G.main->tex.first) static struct PyMethodDef Texture_methods[] = { {"Get", Texture_Get, 1, Texture_Get_doc}, {NULL, NULL} }; */ /*********************/ /* Camera Datablocks */ DATABLOCK_GET(Camera, camera, G.main->camera.first) static struct PyMethodDef Camera_methods[] = { {"Get", Camera_Get, 1, Camera_Get_doc}, {NULL, NULL} }; /***********************/ /* Material Datablocks */ DATABLOCK_GET(Material, material, G.main->mat.first) static struct PyMethodDef Material_methods[] = { {"Get", Material_Get, 1, Material_Get_doc}, {NULL, NULL} }; /*******************/ /* Lamp Datablocks */ DATABLOCK_GET(Lamp, lamp, G.main->lamp.first) static struct PyMethodDef Lamp_methods[] = { {"Get", Lamp_Get, 1, Lamp_Get_doc}, {NULL, NULL} }; /********************/ /* World Datablocks */ DATABLOCK_GET(World, world, G.main->world.first) static char World_GetActive_doc[]="() - Returns the active world"; static PyObject *World_GetActive (PyObject *self, PyObject *args) { if (G.scene->world) return add_pyblock(G.scene->world); else return py_incr_ret(Py_None); } static struct PyMethodDef World_methods[] = { {"Get", World_Get, 1, World_Get_doc}, {"GetActive", World_GetActive, 1, World_GetActive_doc}, {NULL, NULL} }; /*********************/ /* Object Datablocks */ DATABLOCK_GET(Object, object, G.main->object.first) static char Object_GetSelected_doc[]= "() - Returns a list of all selected objects"; static PyObject *Object_GetSelected (PyObject *self, PyObject *args) { PyObject *list; Object *tmp; list= PyList_New(0); tmp= G.main->object.first; while (tmp) { if (tmp->flag & SELECT) { PyObject *ob= add_pyblock(tmp); if (!ob) { Py_DECREF(list); return NULL; } PyList_Append(list, ob); } tmp= tmp->id.next; } return list; } static char Object_Update_doc[]= "(name) - Updates the specified object during user-transformation\n\ \n\ (name) Name of the object to update\n\ \n\ NOTE: This is an experimental function for combating 'lag'."; static PyObject *Object_Update (PyObject *self, PyObject *args) { Base *base; char *name= NULL; Py_Try(PyArg_ParseTuple(args, "s", &name)); base= FIRSTBASE; while (base) { if (strcmp(name, base->object->id.name+2)==0) base->flag|= BA_WHERE_UPDATE|BA_PARSEL|BA_DISP_UPDATE; base= base->next; } Py_INCREF(Py_None); return Py_None; } static struct PyMethodDef Object_methods[] = { {"Get", Object_Get, 1, Object_Get_doc}, {"GetSelected", Object_GetSelected, 1, Object_GetSelected_doc}, {"Update", Object_Update, 1, Object_Update_doc}, {NULL, NULL} }; /******************/ /* IPO Datablocks */ PyTypeObject PyBezTriple_Type; typedef struct _PyBezTriple { PyObject_VAR_HEAD BezTriple bzt; } PyBezTriple; PyTypeObject PyBezTriple_Type; void pybzt_dealloc(PyObject *self) { PyMem_DEL(self); } int pybzt_print(PyObject *self, FILE *fp, int flags) { fprintf (fp, "[BezTriple]"); return 0; } NamedEnum bez_triple_flags[]= { {"Free", 0}, {"Auto", 1}, {"Vect", 2}, {"Align", 3}, {NULL} }; DataBlockProperty BezTriple_Properties[]= { {"h1", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {0,0}, {3,3,-sizeof(float)}}, {"pt", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {1,0}, {3,3,-sizeof(float)}}, {"h2", "vec[3][3]", DBP_TYPE_VEC, 0, 2.0, 0.0, {2,0}, {3,3,-sizeof(float)}}, {"f1", "f1", DBP_TYPE_CHA, 0, 0.0, 1.0}, {"f2", "f2", DBP_TYPE_CHA, 0, 0.0, 1.0}, {"f3", "f3", DBP_TYPE_CHA, 0, 0.0, 1.0}, {"h1t", "h1", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags}, {"h2t", "h2", DBP_TYPE_SHO, 0, 0.0, 0.0, {0}, {0}, DBP_HANDLING_NENM, bez_triple_flags}, {NULL} }; PyObject *pybzt_getattr(PyObject *self, char *name) { PyBezTriple *pybzt= (PyBezTriple *) self; return datablock_getattr(BezTriple_Properties, "BezTriple", name, &pybzt->bzt); } int pybzt_setattr(PyObject *self, char *name, PyObject *ob) { PyBezTriple *pybzt= (PyBezTriple *) self; return datablock_setattr(BezTriple_Properties, "BezTriple", name, &pybzt->bzt, ob); } PyTypeObject PyBezTriple_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "BezTriple", /*tp_name*/ sizeof(PyBezTriple), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor) pybzt_dealloc, /*tp_dealloc*/ (printfunc) pybzt_print, /*tp_print*/ (getattrfunc) pybzt_getattr, /*tp_getattr*/ (setattrfunc) pybzt_setattr, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ }; static char pybzt_create_doc[]= "() - Create a new BezTriple object"; PyObject *pybzt_create(PyObject *self, PyObject *args) { PyBezTriple *py_bzt= PyObject_NEW(PyBezTriple, &PyBezTriple_Type); BezTriple *bzt= &py_bzt->bzt; Py_Try(PyArg_ParseTuple(args, "")); memset(&py_bzt->bzt,0,sizeof(py_bzt->bzt)); return (PyObject *) py_bzt; } PyObject *pybzt_from_bzt(BezTriple *bzt) { PyBezTriple *py_bzt= PyObject_NEW(PyBezTriple, &PyBezTriple_Type); memcpy(&py_bzt->bzt, bzt, sizeof(*bzt)); return (PyObject *) py_bzt; } PyTypeObject PyIpoCurve_Type; typedef struct _PyIpoCurve { PyObject_VAR_HEAD IpoCurve *icu; } PyIpoCurve; void pyicu_dealloc(PyObject *self) { PyMem_DEL(self); } int pyicu_print(PyObject *self, FILE *fp, int flags) { fprintf (fp, "[IpoCurve]"); return 0; } PyObject *pyicu_getattr(PyObject *self, char *name) { PyIpoCurve *py_icu= (PyIpoCurve *) self; IpoCurve *icu= py_icu->icu; if (STREQ(name, "type")) { switch (icu->ipo) { case IPO_CONST: return PyString_FromString("Constant"); case IPO_LIN: return PyString_FromString("Linear"); case IPO_BEZ: return PyString_FromString("Bezier"); } } else if (STREQ(name, "extend")) { switch (icu->extrap) { case IPO_HORIZ: return PyString_FromString("Constant"); case IPO_DIR: return PyString_FromString("Extrapolate"); case IPO_CYCL: return PyString_FromString("Cyclic"); case IPO_CYCLX: return PyString_FromString("CyclicX"); } } else if (STREQ(name, "name")) { char icu_name[32]= ""; switch (icu->blocktype) { case ID_OB: getname_ob_ei(icu->adrcode, icu_name, 0); break; case ID_MA: getname_mat_ei(icu->adrcode, icu_name, 0); break; case ID_WO: getname_world_ei(icu->adrcode, icu_name, 0); break; case ID_SEQ: getname_seq_ei(icu->adrcode, icu_name, 0); break; case ID_CU: getname_cu_ei(icu->adrcode, icu_name, 0); break; case ID_KE: getname_key_ei(icu->adrcode, icu_name, 0); break; case ID_LA: getname_la_ei(icu->adrcode, icu_name, 0); break; case ID_CA: getname_cam_ei(icu->adrcode, icu_name, 0); break; } return PyString_FromString(icu_name); } else if (STREQ(name, "points")) { PyObject *list= PyList_New(icu->totvert); BezTriple *bzt= icu->bezt; int i; for (i=0; itotvert; i++) { PyList_SetItem(list, i, pybzt_from_bzt(bzt)); bzt++; } return list; } PyErr_SetString(PyExc_AttributeError, name); return NULL; } int pyicu_setattr(PyObject *self, char *name, PyObject *ob) { PyIpoCurve *py_icu= (PyIpoCurve *) self; IpoCurve *icu= py_icu->icu; if (STREQ(name, "points")) { int i, len; BezTriple *bzt; if (!PySequence_Check(ob) || !py_check_sequence_consistency(ob, &PyBezTriple_Type)) return py_err_ret_int(PyExc_AttributeError, "Expected list of BezTriples"); len= PySequence_Length(ob); freeN(icu->bezt); icu->totvert= len; if (len) icu->bezt= mallocN(len*sizeof(BezTriple), "beztriples"); bzt= icu->bezt; for (i=0; ibzt, sizeof(BezTriple)); bzt++; Py_DECREF(pybzt); } /* Twice for auto handles */ calchandles_ipocurve(icu); calchandles_ipocurve(icu); boundbox_ipocurve(icu); sort_time_ipocurve(icu); return 0; } PyErr_SetString(PyExc_AttributeError, name); return -1; } PyObject *pyicu_from_icu(IpoCurve *icu) { PyIpoCurve *ob= PyObject_NEW(PyIpoCurve, &PyIpoCurve_Type); ob->icu= icu; return (PyObject *) ob; } PyTypeObject PyIpoCurve_Type = { PyObject_HEAD_INIT(NULL) 0, /*ob_size*/ "IpoCurve", /*tp_name*/ sizeof(PyIpoCurve), /*tp_basicsize*/ 0, /*tp_itemsize*/ /* methods */ (destructor) pyicu_dealloc, /*tp_dealloc*/ (printfunc) pyicu_print, /*tp_print*/ (getattrfunc) pyicu_getattr, /*tp_getattr*/ (setattrfunc) pyicu_setattr, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ 0, /*tp_as_number*/ 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash*/ }; DATABLOCK_GET(Ipo, ipo, G.main->ipo.first) #include "ipo.h" extern PyTypeObject Block_Type; static char Ipo_Recalc_doc[]= "(ipo) - Recalculate the ipo and update linked objects\n\ \n\ (ipo) The ipo to recalculate"; PyObject *Ipo_Recalc(PyObject *self, PyObject *args) { PyBlock *ob; Key *key; Py_Try(PyArg_ParseTuple(args, "O!", &Block_Type, &ob)); if (!pyblock_is_type(ob,ID_IP)) return py_err_ret_ob(PyExc_AttributeError, "Expected IPO object"); do_ipo((Ipo *) ob->data); /* here we should signal all objects with keys that the ipo changed */ key= G.main->key.first; while(key) { if(key->ipo == (Ipo *)ob->data) do_spec_key(key); key= key->id.next; } return py_incr_ret(Py_None); } static char Ipo_Eval_doc[]= "(curve, [time]) - Evaluate the value of the curve at some time\n\ \n\ (curve) The curve to evaluate\n\ [time= current frame] The time at which to evaluate the curve"; PyObject *Ipo_Eval(PyObject *self, PyObject *args) { PyIpoCurve *ob; float time= CFRA; Py_Try(PyArg_ParseTuple(args, "O!|f", &PyIpoCurve_Type, &ob, &time)); return PyFloat_FromDouble(eval_icu(ob->icu, time)); } static struct PyMethodDef Ipo_methods[] = { {"Get", Ipo_Get, 1, Ipo_Get_doc}, {"Eval", Ipo_Eval, 1, Ipo_Eval_doc}, {"Recalc", Ipo_Recalc, 1, Ipo_Recalc_doc}, {"BezTriple", pybzt_create, 1, pybzt_create_doc}, {NULL, NULL} }; void load_py_datablocks(PyObject *dict) { #define MODLOAD(name) PyDict_SetItemString(dict, #name, Py_InitModule("Blender." #name, name##_methods)) PyIpoCurve_Type.ob_type= &PyType_Type; PyBezTriple_Type.ob_type= &PyType_Type; MODLOAD(Object); MODLOAD(Camera); MODLOAD(Lamp); MODLOAD(Material); MODLOAD(World); MODLOAD(Ipo); /* MODLOAD(Texture); */ }