API:
- replaced BKE_copy_images with BKE_export_image, now it handles only one image at a time, this is better since for exporters it is easier to export one image at a time writing new image path to a file - exposing BKE_export_image in RNA as Image.export, interestingly, RNA allowed me to define a function with PROP_STRING return type although it doesn't free memory, will fix that in the next commit - removed bpy.util.copy_images Unit tests: - re-wrote a test for BKE_export_image, it's more compact now - moved unit tests to the creator module to avoid another executable, now running tests with `blender --test` - as before, unit tests are built only if WITH_BF_UNIT_TEST is non 0
This commit is contained in:
		@@ -93,7 +93,7 @@ void BPY_update_modules( void )
 | 
			
		||||
	PyObject *mod= PyImport_ImportModuleLevel("bpy", NULL, NULL, NULL, 0);
 | 
			
		||||
	PyModule_AddObject( mod, "data", BPY_rna_module() );
 | 
			
		||||
	PyModule_AddObject( mod, "types", BPY_rna_types() );
 | 
			
		||||
	PyModule_AddObject( mod, "util", BPY_util_module() );
 | 
			
		||||
	/* PyModule_AddObject( mod, "util", BPY_util_module() ); */
 | 
			
		||||
 | 
			
		||||
	/* XXX this will move to bpy.util */
 | 
			
		||||
	PyModule_AddObject( mod, "sys", BPY_sys_module() );
 | 
			
		||||
 
 | 
			
		||||
@@ -488,126 +488,3 @@ int BPy_errors_to_report(ReportList *reports)
 | 
			
		||||
	Py_DECREF(pystring);
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* bpy.util module */
 | 
			
		||||
static PyObject *bpy_util_copy_images(PyObject *self, PyObject *args);
 | 
			
		||||
 | 
			
		||||
struct PyMethodDef bpy_util_methods[] = {
 | 
			
		||||
	{"copy_images", bpy_util_copy_images, METH_VARARGS, NULL},
 | 
			
		||||
	{NULL, NULL, 0, NULL}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if PY_VERSION_HEX >= 0x03000000
 | 
			
		||||
static struct PyModuleDef bpy_util_module = {
 | 
			
		||||
	PyModuleDef_HEAD_INIT,
 | 
			
		||||
	"bpyutil",
 | 
			
		||||
	NULL,
 | 
			
		||||
	-1,
 | 
			
		||||
	bpy_util_methods,
 | 
			
		||||
	NULL, NULL, NULL, NULL
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
PyObject *BPY_util_module( void )
 | 
			
		||||
{
 | 
			
		||||
	PyObject *submodule, *dict;
 | 
			
		||||
 | 
			
		||||
#if PY_VERSION_HEX >= 0x03000000
 | 
			
		||||
	submodule= PyModule_Create(&bpy_util_module);
 | 
			
		||||
#else /* Py2.x */
 | 
			
		||||
	submodule= Py_InitModule3("bpyutil", bpy_util_methods, NULL);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	dict = PyModule_GetDict(submodule);
 | 
			
		||||
	
 | 
			
		||||
	return submodule;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
  copy_images(images, dest_dir)
 | 
			
		||||
  return filenames
 | 
			
		||||
*/
 | 
			
		||||
static PyObject *bpy_util_copy_images(PyObject *self, PyObject *args)
 | 
			
		||||
{
 | 
			
		||||
	const char *dest_dir;
 | 
			
		||||
	ListBase *images;
 | 
			
		||||
	ListBase *paths;
 | 
			
		||||
	LinkData *link;
 | 
			
		||||
	PyObject *seq;
 | 
			
		||||
	PyObject *ret;
 | 
			
		||||
	PyObject *item;
 | 
			
		||||
	int i;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	/* check args/types */
 | 
			
		||||
	if (!PyArg_ParseTuple(args, "Os", &seq, &dest_dir)) {
 | 
			
		||||
		PyErr_SetString(PyExc_TypeError, "Invalid arguments.");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* expecting a sequence of Image objects */
 | 
			
		||||
	if (!PySequence_Check(seq)) {
 | 
			
		||||
		PyErr_SetString(PyExc_TypeError, "Expected a sequence of images.");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* create image list */
 | 
			
		||||
	len= PySequence_Size(seq);
 | 
			
		||||
 | 
			
		||||
	if (!len) {
 | 
			
		||||
		PyErr_SetString(PyExc_TypeError, "At least one image should be specified.");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* make sure all sequence items are Image */
 | 
			
		||||
	for(i= 0; i < len; i++) {
 | 
			
		||||
		item= PySequence_GetItem(seq, i);
 | 
			
		||||
 | 
			
		||||
		if (!BPy_StructRNA_Check(item) || ((BPy_StructRNA*)item)->ptr.type != &RNA_Image) {
 | 
			
		||||
			PyErr_SetString(PyExc_TypeError, "Expected a sequence of Image objects.");
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	images= MEM_callocN(sizeof(*images), "ListBase of images");
 | 
			
		||||
 | 
			
		||||
	for(i= 0; i < len; i++) {
 | 
			
		||||
		BPy_StructRNA* srna;
 | 
			
		||||
 | 
			
		||||
		item= PySequence_GetItem(seq, i);
 | 
			
		||||
		srna= (BPy_StructRNA*)item;
 | 
			
		||||
 | 
			
		||||
		link= MEM_callocN(sizeof(LinkData), "LinkData image");
 | 
			
		||||
		link->data= srna->ptr.data;
 | 
			
		||||
		BLI_addtail(images, link);
 | 
			
		||||
 | 
			
		||||
		Py_DECREF(item);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	paths= MEM_callocN(sizeof(*paths), "ListBase of image paths");
 | 
			
		||||
 | 
			
		||||
	/* call BKE_copy_images */
 | 
			
		||||
	BKE_copy_images(images, dest_dir, paths);
 | 
			
		||||
 | 
			
		||||
	/* convert filenames */
 | 
			
		||||
	ret= PyList_New(0);
 | 
			
		||||
 | 
			
		||||
	for(link= paths->first; link; link= link->next) {
 | 
			
		||||
		if (link->data) {
 | 
			
		||||
			item= PyUnicode_FromString(link->data);
 | 
			
		||||
			PyList_Append(ret, item);
 | 
			
		||||
			Py_DECREF(item);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			PyList_Append(ret, Py_None);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* free memory */
 | 
			
		||||
	BLI_freelistN(images);
 | 
			
		||||
	BLI_freelistN(paths);
 | 
			
		||||
 | 
			
		||||
	/* return filenames */
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user