diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index 759bbcce885..ce63eace501 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -34,6 +34,8 @@ #include #include +#include + #include #include #include @@ -43,6 +45,9 @@ #include #include "api2_2x/interface.h" +/* unfortunately the following #include is needed because of some missing */ +/* functionality in BKE/DNA */ +/* #include "api2_2x/gen_utils.h" */ /*****************************************************************************/ /* Structure definitions */ @@ -63,6 +68,8 @@ ScriptError g_script_error; /*****************************************************************************/ PyObject * RunPython(Text *text, PyObject *globaldict); char * GetName(Text *text); +PyObject * CreateGlobalDictionary (void); +void ReleaseGlobalDictionary (PyObject * dict); /*****************************************************************************/ /* Description: This function will initialise Python and all the implemented */ @@ -165,68 +172,41 @@ void BPY_do_all_scripts(short event) return; } -/* - * Description: Execute a Python script when an event occurs. The following - * events are possible: frame changed, load script and redraw. - * Only events happening to one of the following object types are - * handled: Object, Lamp, Camera, Material, World and Scene - * Notes: The call to BLO_findstruct_offset needs to be removed. - * Somehow the object triggered by the event has to be retrieved. - */ +/*****************************************************************************/ +/* Description: Execute a Python script when an event occurs. The following */ +/* events are possible: frame changed, load script and redraw. */ +/* Only events happening to one of the following object types */ +/* are handled: Object, Lamp, Camera, Material, World and */ +/* Scene. */ +/*****************************************************************************/ void BPY_do_pyscript(struct ID *id, short event) { - int obj_id; - char structname[10]; - int offset; - ScriptLink * scriptlink; + ScriptLink * scriptlink; + int index; + PyObject * dict; printf ("In BPY_do_pyscript(id=%s, event=%d)\n",id->name, event); - /* First get the object type that the script is linked to. */ - obj_id = MAKE_ID2(id->name[0], id->name[1]); - switch (obj_id) - { - case ID_OB: - sprintf (structname, "Object"); - break; - case ID_LA: - sprintf (structname, "Lamp"); - break; - case ID_CA: - sprintf (structname, "Camera"); - break; - case ID_MA: - sprintf (structname, "Material"); - break; - case ID_WO: - sprintf (structname, "World"); - break; - case ID_SCE: - sprintf (structname, "Scene"); - break; - default: - /* TODO: Do we need to generate a nice error message here? */ - return; - } + scriptlink = setScriptLinks (id, event); -/* TODO: Replace the following piece of code. See the Notes for info. */ - /* Check if a script is provided */ - offset = BLO_findstruct_offset (structname, "scriptlink"); - if (offset < 0) + if (scriptlink == NULL) { - printf ("Internal error, unable to find script link\n"); return; } - scriptlink = (ScriptLink*) (((char*)id) + offset); - if (!scriptlink->totscript) + for (index=0 ; indextotscript ; index++) { - /* no script provided */ - return; + printf ("scriptnr: %d\tevent=%d, flag[index]=%d\n", index, + event, scriptlink->flag[index]); + if ((scriptlink->flag[index] == event) && + (scriptlink->scripts[index]!=NULL)) + { + dict = CreateGlobalDictionary(); + RunPython ((Text*) scriptlink->scripts[index], dict); + ReleaseGlobalDictionary (dict); + } } - - /* Get all links from blender and set them in the Python environment */ - setScriptLinks (id, event); + return; } @@ -324,3 +304,24 @@ char * GetName(Text *text) return (text->id.name+2); } +/*****************************************************************************/ +/* Description: This function creates a new Python dictionary object. */ +/*****************************************************************************/ +PyObject * CreateGlobalDictionary (void) +{ + PyObject *dict = PyDict_New(); + PyDict_SetItemString (dict, "__builtins__", PyEval_GetBuiltins()); + PyDict_SetItemString (dict, "__name__", PyString_FromString("__main__")); + + return (dict); +} + +/*****************************************************************************/ +/* Description: This function deletes a given Python dictionary object. */ +/*****************************************************************************/ +void ReleaseGlobalDictionary (PyObject * dict) +{ + PyDict_Clear (dict); + Py_DECREF (dict); /* Release dictionary. */ +} + diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c index fc67775f395..d099d9ba3f7 100644 --- a/source/blender/python/api2_2x/Blender.c +++ b/source/blender/python/api2_2x/Blender.c @@ -239,6 +239,7 @@ void initBlender (void) module = Py_InitModule3("Blender", Blender_methods, NULL); dict = PyModule_GetDict (module); + g_blenderdict = dict; PyDict_SetItemString (dict, "Object", initObject()); } diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 263dabdc558..cc30827f235 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -131,7 +131,7 @@ PyObject *Object_Get(PyObject *self, PyObject *args) { char * name; PyObject * arg; - struct Object * obj_iter; + struct Object * object; BlenObject * blen_object; printf ("In Object_Get()\n"); @@ -148,31 +148,18 @@ PyObject *Object_Get(PyObject *self, PyObject *args) return (PythonReturnErrorObject (PyExc_AttributeError, "expected string argument")); } + name = PyString_AsString (arg); + object = GetObjectByName (name); - /* Use the name to search for the object requested. */ - /* Should this lookup be a new function in blenkernel/intern/object.c? */ - blen_object = NULL; - obj_iter = G.main->object.first; - while ((obj_iter) && (blen_object == NULL)) - { - if (StringEqual (name, GetIdName (&(obj_iter->id)))) - { - blen_object = (BlenObject*)PyObject_NEW - (BlenObject, - &object_type); - - blen_object->object = obj_iter; - } - obj_iter = obj_iter->id.next; - } - - if (blen_object == NULL) + if (object == NULL) { /* No object exists with the name specified in the argument name. */ return (PythonReturnErrorObject (PyExc_AttributeError, - "expected string argument")); + "Unknown object specified.")); } + blen_object = (BlenObject*)PyObject_NEW (BlenObject, &object_type); + blen_object->object = object; return ((PyObject*)blen_object); } diff --git a/source/blender/python/api2_2x/gen_utils.c b/source/blender/python/api2_2x/gen_utils.c index 32c3bb660e9..f44bc7f9514 100644 --- a/source/blender/python/api2_2x/gen_utils.c +++ b/source/blender/python/api2_2x/gen_utils.c @@ -33,31 +33,53 @@ #include #include +#include +#include #include +#include #include +/*****************************************************************************/ +/* Description: This function returns true if both given strings are equal, */ +/* otherwise it returns false. */ +/*****************************************************************************/ int StringEqual (char * string1, char * string2) { return (strcmp(string1, string2)==0); } +/*****************************************************************************/ +/* Description: This function returns the name of the given ID struct */ +/* without the Object type identifying characters prepended. */ +/*****************************************************************************/ char * GetIdName (ID *id) { return ((id->name)+2); } +/*****************************************************************************/ +/* Description: This function sets an internal string with the given type */ +/* and error_msg arguments. */ +/*****************************************************************************/ PyObject * PythonReturnErrorObject (PyObject * type, char * error_msg) { PyErr_SetString (type, error_msg); return (NULL); } +/*****************************************************************************/ +/* Description: This function increments the reference count of the given */ +/* Python object. */ +/*****************************************************************************/ PyObject * PythonIncRef (PyObject *object) { Py_INCREF (object); return (object); } +/*****************************************************************************/ +/* Description: This function maps the event identifier to a string. */ +/*****************************************************************************/ char * event_to_name(short event) { switch (event) @@ -73,3 +95,29 @@ char * event_to_name(short event) } } +/*****************************************************************************/ +/* Description: Returns the object with the name specified by the argument */ +/* name. Note that the calling function has to remove the first */ +/* two characters of the object name. These two characters */ +/* specify the type of the object (OB, ME, WO, ...) */ +/* The function will return NULL when no object with the given */ +/* name is found. */ +/*****************************************************************************/ +struct Object * GetObjectByName (char * name) +{ + Object * obj_iter; + + obj_iter = G.main->object.first; + while (obj_iter) + { + if (StringEqual (name, GetIdName (&(obj_iter->id)))) + { + return (obj_iter); + } + obj_iter = obj_iter->id.next; + } + + /* There is no object with the given name */ + return (NULL); +} + diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h index ab41cf9d617..038c7f814ad 100644 --- a/source/blender/python/api2_2x/gen_utils.h +++ b/source/blender/python/api2_2x/gen_utils.h @@ -39,3 +39,8 @@ PyObject * PythonReturnErrorObject (PyObject * type, char * error_msg); PyObject * PythonIncRef (PyObject *object); char * event_to_name(short event); +/* The following functions may need to be moved to the respective BKE or */ +/* DNA modules. */ + +struct Object * GetObjectByName (char * name); + diff --git a/source/blender/python/api2_2x/interface.c b/source/blender/python/api2_2x/interface.c index 4d5d5962c63..671160c000e 100644 --- a/source/blender/python/api2_2x/interface.c +++ b/source/blender/python/api2_2x/interface.c @@ -31,6 +31,8 @@ #include +#include + #include #include #include @@ -39,87 +41,83 @@ #include #include #include +#include #include -#include "datablock.h" #include "gen_utils.h" #include "modules.h" void initBlenderApi2_2x (void) { printf ("initBlenderApi2_2x\n"); + g_blenderdict = NULL; initBlender (); } -void setScriptLinks(ID *id, short event) +ScriptLink * setScriptLinks(ID *id, short event) { - PyObject *link; - int obj_id; - - printf ("In setScriptLinks (id=?, event=%d)\n", event); - if (!g_blenderdict) - { - /* Not initialized yet. This can happen at first file load. */ - return; - } + ScriptLink * scriptlink; + PyObject * link; + Object * object; + int obj_id; obj_id = MAKE_ID2 (id->name[0], id->name[1]); - if (obj_id == ID_SCE) + printf ("In setScriptLinks (id=%s, event=%d)\n",id->name, event); + + switch (obj_id) { - Py_INCREF(Py_None); - link = Py_None; + case ID_OB: + object = GetObjectByName (GetIdName (id)); + if (object == NULL) + { + return NULL; + } + link = ObjectCreatePyObject (object); + scriptlink = &(object->scriptlink); + break; + case ID_LA: + scriptlink = NULL; + Py_INCREF(Py_None); + link = Py_None; + break; + case ID_CA: + scriptlink = NULL; + Py_INCREF(Py_None); + link = Py_None; + break; + case ID_MA: + scriptlink = NULL; + Py_INCREF(Py_None); + link = Py_None; + break; + case ID_WO: + scriptlink = NULL; + Py_INCREF(Py_None); + link = Py_None; + break; + case ID_SCE: + scriptlink = NULL; + Py_INCREF(Py_None); + link = Py_None; + break; + default: + Py_INCREF(Py_None); + link = Py_None; + return NULL; + } + + if (scriptlink == NULL) + { + /* This is probably not an internal error anymore :) +TODO: Check this + printf ("Internal error, unable to create PyBlock for script link\n"); + */ + Py_INCREF(Py_False); + PyDict_SetItemString(g_blenderdict, "bylink", Py_False); + return NULL; } else { - link = Py_None; - switch (obj_id) - { - case ID_OB: - /* Create a new datablock of type: Object */ - /* - link = ObjectCreatePyObject (G.main->object); - */ - break; - case ID_ME: - /* Create a new datablock of type: Mesh */ - break; - case ID_LA: - /* Create a new datablock of type: Lamp */ - break; - case ID_CA: - /* Create a new datablock of type: Camera */ - break; - case ID_MA: - /* Create a new datablock of type: Material */ - break; - case ID_WO: - /* Create a new datablock of type: World */ - break; - case ID_IP: - /* Create a new datablock of type: Ipo */ - break; - case ID_IM: - /* Create a new datablock of type: Image */ - break; - case ID_TXT: - /* Create a new datablock of type: Text */ - break; - default: - PythonReturnErrorObject (PyExc_SystemError, - "Unable to create block for data"); - return; - } - /* link = DataBlockFromID(id); */ - } - - if (!link) - { - printf ("Internal error, unable to create PyBlock for script link\n"); - printf ("This is a bug; please report to bugs@blender.nl"); - Py_INCREF(Py_False); - PyDict_SetItemString(g_blenderdict, "bylink", Py_False); - return; - } else { Py_INCREF(Py_True); PyDict_SetItemString(g_blenderdict, "bylink", Py_True); } @@ -127,4 +125,6 @@ void setScriptLinks(ID *id, short event) PyDict_SetItemString(g_blenderdict, "link", link); PyDict_SetItemString(g_blenderdict, "event", Py_BuildValue("s", event_to_name(event))); + + return (scriptlink); } diff --git a/source/blender/python/api2_2x/interface.h b/source/blender/python/api2_2x/interface.h index 3495da8790c..e61e6c2d2dc 100644 --- a/source/blender/python/api2_2x/interface.h +++ b/source/blender/python/api2_2x/interface.h @@ -32,4 +32,4 @@ #include void initBlenderApi2_2x (void); -void setScriptLinks(ID *id, short event); +ScriptLink * setScriptLinks(ID *id, short event);