[Bf-blender-cvs] [89c74df] particles_refactor: Custom get/set methods for the "Particle" type. This supports particle attributes directly as python properties in the particle wrapper type. If a particle identifier has no corresponding data in the state yet it will be automatically created when writing.

Lukas Tönne noreply at git.blender.org
Tue Apr 22 12:06:18 CEST 2014


Commit: 89c74dfcf11f520610c273339f74c56677b02f73
Author: Lukas Tönne
Date:   Fri Dec 20 15:36:20 2013 +0100
https://developer.blender.org/rB89c74dfcf11f520610c273339f74c56677b02f73

Custom get/set methods for the "Particle" type. This supports particle
attributes directly as python properties in the particle wrapper type.
If a particle identifier has no corresponding data in the state yet it
will be automatically created when writing.

===================================================================

M	source/blender/blenkernel/BKE_nparticle.h
M	source/blender/blenkernel/intern/nparticle.c
M	source/blender/python/bparticles/bparticles_py_types.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_nparticle.h b/source/blender/blenkernel/BKE_nparticle.h
index 9648b10..a9978b8 100644
--- a/source/blender/blenkernel/BKE_nparticle.h
+++ b/source/blender/blenkernel/BKE_nparticle.h
@@ -65,6 +65,8 @@ struct NParticleAttributeState *BKE_nparticle_state_get_attribute_by_index(struc
 
 int BKE_nparticle_state_num_particles(struct NParticleState *state);
 
+void *BKE_nparticle_attribute_state_data(struct NParticleAttributeState *attrstate, int index);
+
 typedef struct NParticleAttributeStateIterator {
 	/* XXX for now is simply a pointer, using ListBase next/prev.
 	 * Eventually this will become a hash table iterator.
@@ -89,10 +91,12 @@ typedef struct NParticleIterator {
 } NParticleIterator;
 
 void BKE_nparticle_iter_init(struct NParticleState *state, struct NParticleIterator *it);
-void BKE_nparticle_iter_find_id(struct NParticleState *state, struct NParticleIterator *it, NParticleID id);
+void BKE_nparticle_iter_from_id(struct NParticleState *state, struct NParticleIterator *it, NParticleID id);
+void BKE_nparticle_iter_from_index(struct NParticleState *state, struct NParticleIterator *it, int index);
 void BKE_nparticle_iter_next(struct NParticleIterator *it);
 bool BKE_nparticle_iter_valid(struct NParticleIterator *it);
 
+/*void *BKE_nparticle_iter_get_data(struct NParticleIterator *it, const char *attr);*/
 int BKE_nparticle_iter_get_int(struct NParticleIterator *it, const char *attr);
 void BKE_nparticle_iter_set_int(struct NParticleIterator *it, const char *attr, int value);
 float BKE_nparticle_iter_get_float(struct NParticleIterator *it, const char *attr);
diff --git a/source/blender/blenkernel/intern/nparticle.c b/source/blender/blenkernel/intern/nparticle.c
index a7ec704..d3e33f7 100644
--- a/source/blender/blenkernel/intern/nparticle.c
+++ b/source/blender/blenkernel/intern/nparticle.c
@@ -380,6 +380,11 @@ int BKE_nparticle_state_num_particles(NParticleState *state)
 	return attrstate ? attrstate->data.totelem : 0;
 }
 
+void *BKE_nparticle_attribute_state_data(NParticleAttributeState *attrstate, int index)
+{
+	return BLI_pbuf_get(&attrstate->data, index);
+}
+
 
 int BKE_nparticle_find_index(NParticleState *state, NParticleID id)
 {
@@ -447,12 +452,22 @@ void BKE_nparticle_iter_init(NParticleState *state, NParticleIterator *it)
 	it->index = 0;
 }
 
-void BKE_nparticle_iter_find_id(NParticleState *state, NParticleIterator *it, NParticleID id)
+void BKE_nparticle_iter_from_id(NParticleState *state, NParticleIterator *it, NParticleID id)
 {
 	it->state = state;
 	it->index = BKE_nparticle_find_index(state, id);
 }
 
+void BKE_nparticle_iter_from_index(NParticleState *state, NParticleIterator *it, int index)
+{
+	NParticleAttributeState *attrstate = nparticle_state_find_attribute_id(state);
+	it->state = state;
+	if (index >= 0 && attrstate && index < attrstate->data.totelem)
+		it->index = index;
+	else
+		it->index = -1;
+}
+
 void BKE_nparticle_iter_next(NParticleIterator *it)
 {
 	++it->index;
@@ -486,6 +501,13 @@ BLI_INLINE bool nparticle_check_attribute_type(NParticleState *state, const char
 	return !attrstate || attrstate->desc.datatype == datatype;
 }
 
+#if 0 /* unused */
+void *BKE_nparticle_iter_get_data(struct NParticleIterator *it, const char *attr)
+{
+	return nparticle_data_ptr(it->state, attr, it->index);
+}
+#endif
+
 int BKE_nparticle_iter_get_int(NParticleIterator *it, const char *attr)
 {
 	int *data = nparticle_data_ptr(it->state, attr, it->index);
diff --git a/source/blender/python/bparticles/bparticles_py_types.c b/source/blender/python/bparticles/bparticles_py_types.c
index 0cf4e4d..7a3a54e 100644
--- a/source/blender/python/bparticles/bparticles_py_types.c
+++ b/source/blender/python/bparticles/bparticles_py_types.c
@@ -30,11 +30,14 @@
 #include <Python.h>
 
 #include "BLI_math.h"
+#include "BLI_string.h"
 
 #include "DNA_nparticle_types.h"
 
 #include "BKE_nparticle.h"
 
+#include "../mathutils/mathutils.h"
+
 #include "../generic/py_capi_utils.h"
 
 #include "bparticles_py_types.h" /* own include */
@@ -144,10 +147,6 @@ static struct PyMethodDef bpy_bpar_attrstate_methods[] = {
 	{NULL, NULL, 0, NULL}
 };
 
-static PyGetSetDef bpy_bpar_particle_getseters[] = {
-	{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
-};
-
 static Py_hash_t bpy_bpar_state_hash(PyObject *self)
 {
 	return _Py_HashPointer(((BPy_NParticleState *)self)->state);
@@ -316,7 +315,7 @@ static PyObject *bpy_bpar_particleseq_subscript_int(BPy_NParticleAttributeStateS
 	NParticleIterator iter;
 	NParticleID id = (NParticleID)keynum;
 	
-	BKE_nparticle_iter_find_id(self->state, &iter, id);
+	BKE_nparticle_iter_from_id(self->state, &iter, id);
 	if (BKE_nparticle_iter_valid(&iter))
 		return BPy_NParticleParticle_CreatePyObject(self->state, id, iter);
 	
@@ -418,6 +417,166 @@ static PyObject *bpy_bpar_particleiter_next(BPy_NParticleParticleIter *self)
 	}
 }
 
+/* Get/Set Functions
+ * ================= */
+
+static PyObject *bpy_bpar_particle_data_read(NParticleAttributeDescription *desc, void *data)
+{
+	switch (desc->datatype) {
+		case PAR_ATTR_DATATYPE_FLOAT:
+			return PyFloat_FromDouble(*(float*)data);
+		case PAR_ATTR_DATATYPE_INT:
+			return PyLong_FromLong(*(int*)data);
+		case PAR_ATTR_DATATYPE_BOOL:
+			return PyBool_FromLong(*(bool*)data);
+		case PAR_ATTR_DATATYPE_VECTOR:
+		case PAR_ATTR_DATATYPE_POINT:
+		case PAR_ATTR_DATATYPE_NORMAL:
+			return Vector_CreatePyObject((float*)data, 3, Py_WRAP, NULL);
+		case PAR_ATTR_DATATYPE_COLOR:
+			return Color_CreatePyObject((float*)data, Py_WRAP, NULL);
+		case PAR_ATTR_DATATYPE_MATRIX:
+			return Matrix_CreatePyObject((float*)data, 4, 4, Py_WRAP, NULL);
+			
+		default:
+			return NULL;
+	}
+}
+
+static int bpy_bpar_particle_data_write(NParticleAttributeDescription *desc, void *data, PyObject *value)
+{
+	/* XXX do we accept this sort of overhead just for error prints?
+	 * only needs to happen for actual errors, but mathutils_array_parse needs string in advance.
+	 */
+//	char error_prefix[128];
+//	BLI_snprintf(error_prefix, sizeof(error_prefix), "NParticleParticle.%.200s", desc->name);
+	
+	switch (desc->datatype) {
+		case PAR_ATTR_DATATYPE_FLOAT:
+			if (PyFloat_Check(value))
+				*(float*)data = (float)PyFloat_AsDouble(value);
+			else {
+				PyErr_Format(PyExc_TypeError,
+				             "NParticleParticle.%.200s expects float, not %.200s",
+				             desc->name, Py_TYPE(value)->tp_name);
+				return -1;
+			}
+			break;
+		case PAR_ATTR_DATATYPE_INT:
+			if (PyLong_Check(value))
+				*(int*)data = (int)PyLong_AsLong(value);
+			else {
+				PyErr_Format(PyExc_TypeError,
+				             "NParticleParticle.%.200s expects int, not %.200s",
+				             desc->name, Py_TYPE(value)->tp_name);
+				return -1;
+			}
+			break;
+		case PAR_ATTR_DATATYPE_BOOL:
+			if (PyBool_Check(value))
+				*(bool*)data = (bool)PyLong_AsLong(value);
+			else {
+				PyErr_Format(PyExc_TypeError,
+				             "NParticleParticle.%.200s expects bool, not %.200s",
+				             desc->name, Py_TYPE(value)->tp_name);
+				return -1;
+			}
+			break;
+		case PAR_ATTR_DATATYPE_VECTOR:
+		case PAR_ATTR_DATATYPE_POINT:
+		case PAR_ATTR_DATATYPE_NORMAL: {
+			if (mathutils_array_parse((float*)data, 3, 3, value, "NParticleParticle") == -1)
+				return -1;
+			break;
+		}
+		case PAR_ATTR_DATATYPE_COLOR: {
+			if (mathutils_array_parse((float*)data, 3, 3, value, "NParticleParticle") == -1)
+				return -1;
+			break;
+		}
+		case PAR_ATTR_DATATYPE_MATRIX: {
+			if (mathutils_array_parse((float*)data, 16, 16, value, "NParticleParticle") == -1)
+				return -1;
+			break;
+		}
+	}
+	
+	return 0;
+}
+
+static PyObject *bpy_bpar_particle_getattro(BPy_NParticleParticle *self, PyObject *pyname)
+{
+	const char *name = _PyUnicode_AsString(pyname);
+	PyObject *ret;
+
+//	PYRNA_STRUCT_CHECK_OBJ(self);
+
+	if (!BKE_nparticle_iter_valid(&self->iter)) {
+		ret = NULL;
+	}
+	else if (name == NULL) {
+		PyErr_SetString(PyExc_AttributeError, "NParticleParticle: __getattr__ must be a string");
+		ret = NULL;
+	}
+	else {
+		NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(self->state, name);
+		void *data;
+		
+		if (!attrstate) {
+			PyErr_Format(PyExc_AttributeError, "NParticleParticle.%.200s not found", name);
+			ret = NULL;
+		}
+		else {
+			data = BKE_nparticle_attribute_state_data(attrstate, self->iter.index);
+			if (!data) {
+				ret = NULL;
+			}
+			else {
+				ret = bpy_bpar_particle_data_read(&attrstate->desc, data);
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int bpy_bpar_particle_setattro(BPy_NParticleParticle *self, PyObject *pyname, PyObject *value)
+{
+	const char *name = _PyUnicode_AsString(pyname);
+	
+//	PYRNA_STRUCT_CHECK_INT(self);
+	
+	if (name == NULL) {
+		PyErr_SetString(PyExc_AttributeError, "NParticleParticle: __setattr__ must be a string");
+		return -1;
+	}
+	else {
+		NParticleAttributeState *attrstate = BKE_nparticle_state_find_attribute(self->state, name);
+		void *data;
+		
+		if (!attrstate) {
+			PyErr_Format(PyExc_AttributeError, "NParticleParticle.%.200s not found", name);
+			return -1;
+		}
+		
+		if (!BKE_nparticle_iter_valid(&self->iter)) {
+			int index = BKE_nparticle_add(self->state, self->id);
+			BKE_nparticle_iter_from_index(self->state, &self->iter, index);
+		}
+		
+		data = BKE_nparticle_attribute_state_data(attrstate, self->iter.index);
+		if (!data) {
+			return -1;
+		}
+		
+		if (bpy_bpar_particle_data_write(&attrstate->desc, data, value) == -1) {
+			return -1;
+		}
+	}
+	
+	return 0;
+}
+
 /* Dealloc Functions
  * ================= */
 
@@ -514,10 +673,12 @@ void BPy_BPAR_init_types(void)
 	BPy_NParticleAttributeState_Type.tp_getset          = bpy_bpar_attrstate_getseters;
 	BPy_NParticleAttributeStateSeq_Type.tp_getset       = NULL;
 	BPy_NParticleAttributeStateIter_Type.tp_getset      = NULL;
-	BPy_NParticleParticle_Type.tp_getset                = bpy_bpar_particle_getseters;
 	BPy_NParticleParticleSeq_Type.tp_getset             = NULL;
 	BPy_NParticleParticleIter_Type.tp_getset            = NULL;
 
+	BPy_NParticleParticle_Type.tp_getattro              = (getattrofunc)bpy_bpar_particle_getattro;
+	BPy_NParticleParticle_Type.tp_setattro              = (setattrofunc)bpy_bpar_particle_setat

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list