[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