[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [49379] branches/ge_components/source/ blender: Components now reload nicer.
Mitchell Stokes
mogurijin at gmail.com
Mon Jul 30 09:08:56 CEST 2012
Revision: 49379
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=49379
Author: moguri
Date: 2012-07-30 07:08:56 +0000 (Mon, 30 Jul 2012)
Log Message:
-----------
Components now reload nicer. Existing properties are not removed (unless they are missing from the reloaded component). If a property doesn't exist, then it is added with it's default value.
Modified Paths:
--------------
branches/ge_components/source/blender/blenkernel/BKE_pycomponent.h
branches/ge_components/source/blender/blenkernel/intern/python_component.c
branches/ge_components/source/blender/editors/space_logic/logic_ops.c
Modified: branches/ge_components/source/blender/blenkernel/BKE_pycomponent.h
===================================================================
--- branches/ge_components/source/blender/blenkernel/BKE_pycomponent.h 2012-07-30 07:07:03 UTC (rev 49378)
+++ branches/ge_components/source/blender/blenkernel/BKE_pycomponent.h 2012-07-30 07:08:56 UTC (rev 49379)
@@ -6,6 +6,7 @@
#endif
struct PythonComponent *new_component_from_import(char *import);
+void reload_component(struct PythonComponent *pc, char *import);
void free_component(struct PythonComponent *pc);
void free_components(struct ListBase *base);
#ifdef __cplusplus
Modified: branches/ge_components/source/blender/blenkernel/intern/python_component.c
===================================================================
--- branches/ge_components/source/blender/blenkernel/intern/python_component.c 2012-07-30 07:07:03 UTC (rev 49378)
+++ branches/ge_components/source/blender/blenkernel/intern/python_component.c 2012-07-30 07:08:56 UTC (rev 49379)
@@ -54,7 +54,93 @@
return 0;
}
+static PyObject *get_class_from_import(char *import, char *cls_r, char *path_r)
+{
+ PyObject *mod, *mod_list, *item, *py_name, *pyclass=NULL;
+ char *last_dot_str, *name;
+ char cls[64], path[64];
+ int i, last_dot;
+ // Don't bother with an empty string
+ if (strcmp(import, "") == 0)
+ return NULL;
+
+ // Split the class and module
+ last_dot_str = strrchr(import, '.');
+ last_dot = (int)(last_dot_str-import) + 1;
+
+
+ if(last_dot > 0)
+ {
+ BLI_strncpy(path, import, last_dot);
+ strcpy(cls, import+last_dot);
+ }
+ else
+ {
+ printf("No component class was specified, only the module was.\n");
+ return NULL;
+ }
+
+ // Try to load up the module
+ mod = PyImport_ImportModule(path);
+
+ if (mod)
+ {
+ // Get the list of objects in the module
+ mod_list = PyDict_Values(PyModule_GetDict(mod));
+
+ // Now iterate the list
+ for (i=0; i<PyList_Size(mod_list); ++i)
+ {
+ item = PyList_GetItem(mod_list, i);
+
+ // We only want to bother checking type objects
+ if (!PyType_Check(item))
+ continue;
+
+ // Make sure the name matches
+ py_name = PyObject_GetAttrString(item, "__name__");
+ name = _PyUnicode_AsString(py_name);
+ Py_DECREF(py_name);
+
+ if (strcmp(name, cls) != 0)
+ continue;
+
+ // Check the subclass with our own function since we don't have access to the KX_PythonComponent type object
+ if (!verify_class(item))
+ {
+ printf("A %s type was found, but it was not a valid subclass of KX_PythonComponent\n", cls);
+ }
+ else
+ {
+ // We have a valid class, return it
+ if (cls_r) strcpy(cls_r, cls);
+ if (path_r) strcpy(path_r, path);
+ pyclass = item;
+ }
+ }
+
+ if (!pyclass)
+ // If we got here, then we didn't find a suitable class
+ printf("No suitable class was found for a component at %s\n", import);
+
+ // Take the module out of the module list so it's not cached by Python (this allows for simpler reloading of components)
+ PyDict_DelItemString(PyImport_GetModuleDict(), path);
+
+ // Cleanup our Python objects
+ Py_DECREF(mod);
+ Py_DECREF(mod_list);
+ }
+ else
+ {
+ PyErr_Print();
+ printf("Unable to load component from %s\n", import);
+ }
+
+ return pyclass;
+}
+#endif
+
ComponentProperty *create_property(char *name, short type, int data, void *poin)
{
ComponentProperty *cprop;
@@ -113,7 +199,7 @@
{
#ifdef WITH_PYTHON
PyObject *args_dict, *key, *value, *items, *item;
- ComponentProperty *cprop;
+ ComponentProperty *cprop, *oldprop;
char name[64];
int i=0, data;
short type;
@@ -135,6 +221,23 @@
// type(value) = property type
items = PyMapping_Items(args_dict);
+ /* First clear out any unused properties */
+ cprop = pycomp->properties.first;
+ while (cprop)
+ {
+ if (!PyMapping_HasKeyString(args_dict, cprop->name))
+ {
+ oldprop = cprop;
+ cprop = cprop->next;
+ BLI_remlink(&pycomp->properties, oldprop);
+ free_component_property(oldprop);
+ oldprop = NULL;
+ }
+ else
+ cprop = cprop->next;
+ }
+
+ /* Then add new ones */
for (i=0; i<PyList_Size(items); ++i)
{
item = PyList_GetItem(items, i);
@@ -202,13 +305,36 @@
continue;
}
- cprop = create_property(name, type, data, poin);
+ /* Check to see if we already have this property, if so, so if we need to update it */
+ cprop = pycomp->properties.first;
+ while (cprop)
+ {
+ if (strcmp(cprop->name, name) == 0)
+ {
+ /* double check the type */
+ if (cprop->type != type)
+ {
+ BLI_remlink(&pycomp->properties, cprop);
+ free_component_property(cprop);
+ cprop = NULL;
+ }
+ else
+ if (poin) MEM_freeN(poin);
+ break;
+ }
+ cprop = cprop->next;
+ }
- if (cprop)
- BLI_addtail(&pycomp->properties, cprop);
- else
- // Cleanup poin if it's set
- if (poin) MEM_freeN(poin);
+ if (!cprop)
+ {
+ cprop = create_property(name, type, data, poin);
+
+ if (cprop)
+ BLI_addtail(&pycomp->properties, cprop);
+ else
+ // Cleanup poin if it's set
+ if (poin) MEM_freeN(poin);
+ }
}
#endif /* WITH_PYTHON */
@@ -251,100 +377,44 @@
PythonComponent *pc = NULL;
#ifdef WITH_PYTHON
- PyObject *mod, *mod_list, *item, *py_name;
PyGILState_STATE state;
- char *last_dot_str, *name;
+ PyObject *pyclass;
char cls[64], path[64];
- int i, last_dot;
-
- // Don't bother with an empty string
- if (strcmp(import, "") == 0)
- return NULL;
-
- // Split the class and module
- last_dot_str = strrchr(import, '.');
- last_dot = (int)(last_dot_str-import) + 1;
-
-
- if(last_dot > 0)
- {
- BLI_strncpy(path, import, last_dot);
- strcpy(cls, import+last_dot);
- }
- else
- {
- printf("No component class was specified, only the module was.\n");
- return NULL;
- }
-
state = PyGILState_Ensure();
- // Try to load up the module
- mod = PyImport_ImportModule(path);
-
- if (mod)
+ if (pyclass = get_class_from_import(import, cls, path))
{
- // Get the list of objects in the module
- mod_list = PyDict_Values(PyModule_GetDict(mod));
+
+ pc = MEM_callocN(sizeof(PythonComponent), "PythonComponent");
- // Now iterate the list
- for (i=0; i<PyList_Size(mod_list); ++i)
- {
- item = PyList_GetItem(mod_list, i);
+ strcpy(pc->module, path);
+ strcpy(pc->name, cls);
- // We only want to bother checking type objects
- if (!PyType_Check(item))
- continue;
-
- // Make sure the name matches
- py_name = PyObject_GetAttrString(item, "__name__");
- name = _PyUnicode_AsString(py_name);
- Py_DECREF(py_name);
+ // Setup the properties
+ create_properties(pc, pyclass);
+ }
- if (strcmp(name, cls) != 0)
- continue;
+ PyGILState_Release(state);
+#endif /* WITH_PYTHON */
- // Check the subclass with our own function since we don't have access to the KX_PythonComponent type object
- if (!verify_class(item))
- {
- printf("A %s type was found, but it was not a valid subclass of KX_PythonComponent\n", cls);
- }
- else
- {
- // We have a valid class, make a component
- pc = MEM_callocN(sizeof(PythonComponent), "PythonComponent");
+ return pc;
+}
- strcpy(pc->module, path);
- strcpy(pc->name, cls);
+void reload_component(PythonComponent *pc, char *import)
+{
+#ifdef WITH_PYTHON
+ PyObject *pyclass;
+ PyGILState_STATE state;
- // Setup the properties
- create_properties(pc, item);
+ state = PyGILState_Ensure();
- break;
- }
- }
-
- // If we still have a NULL component, then we didn't find a suitable class
- if (pc == NULL)
- printf("No suitable class was found for a component at %s\n", import);
-
- // Take the module out of the module list so it's not cached by Python (this allows for simpler reloading of components)
- PyDict_DelItemString(PyImport_GetModuleDict(), path);
-
- // Cleanup our Python objects
- Py_DECREF(mod);
- Py_DECREF(mod_list);
- }
- else
+ if (pyclass = get_class_from_import(import, NULL, NULL))
{
- PyErr_Print();
- printf("Unable to load component from %s\n", import);
+ create_properties(pc, pyclass);
}
PyGILState_Release(state);
-#endif /* WITH_PYTHON */
-
- return pc;
+#endif
}
void free_component(PythonComponent *pc)
Modified: branches/ge_components/source/blender/editors/space_logic/logic_ops.c
===================================================================
--- branches/ge_components/source/blender/editors/space_logic/logic_ops.c 2012-07-30 07:07:03 UTC (rev 49378)
+++ branches/ge_components/source/blender/editors/space_logic/logic_ops.c 2012-07-30 07:08:56 UTC (rev 49379)
@@ -830,23 +830,9 @@
if(!pc)
return OPERATOR_CANCELLED;
- /* Try to create a new component */
sprintf(import, "%s.%s", pc->module, pc->name);
- new_pc = new_component_from_import(import);
+ reload_component(pc, import);
- /* If creation failed, leave the old one along */
- if(!new_pc)
- return OPERATOR_CANCELLED;
-
- /* Otherwise swap and destroy the old one */
- BLI_remlink(&ob->components, pc);
- free_component(pc);
-
- if (prev_pc)
- BLI_insertlink(&ob->components, prev_pc, new_pc);
- else
- BLI_addhead(&ob->components, new_pc);
-
return OPERATOR_FINISHED;
}
More information about the Bf-blender-cvs
mailing list