support for object data material assignment in python
eg: bpy.context.object.data.materials[0] = bpy.data.materials["SomeMaterial"]
This commit is contained in:
@@ -778,7 +778,7 @@ int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop);
|
||||
int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr);
|
||||
int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr);
|
||||
int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr);
|
||||
int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, PointerRNA *assign_ptr);
|
||||
int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr);
|
||||
int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr);
|
||||
|
||||
/* efficient functions to set properties for arrays */
|
||||
|
@@ -314,6 +314,14 @@ static int rna_IDPArray_length(PointerRNA *ptr)
|
||||
return prop->len;
|
||||
}
|
||||
|
||||
int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, PointerRNA *assign_ptr)
|
||||
{
|
||||
ID *id= ptr->id.data;
|
||||
Material *mat_id= assign_ptr->id.data;
|
||||
assign_material_id(id, mat_id, key + 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void rna_def_ID_properties(BlenderRNA *brna)
|
||||
|
@@ -1095,6 +1095,9 @@ StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop)
|
||||
if(cprop->item_type)
|
||||
return cprop->item_type;
|
||||
}
|
||||
else {
|
||||
BLI_assert(0);
|
||||
}
|
||||
|
||||
return &RNA_UnknownType;
|
||||
}
|
||||
@@ -2865,7 +2868,7 @@ int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, co
|
||||
}
|
||||
|
||||
/* zero return is an assignment error */
|
||||
int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, PointerRNA *assign_ptr)
|
||||
int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr)
|
||||
{
|
||||
CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)rna_ensure_property(prop);
|
||||
|
||||
|
@@ -1428,7 +1428,8 @@ static void rna_def_curve(BlenderRNA *brna)
|
||||
RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol");
|
||||
RNA_def_property_struct_type(prop, "Material");
|
||||
RNA_def_property_ui_text(prop, "Materials", "");
|
||||
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
|
||||
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
|
||||
RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
|
||||
}
|
||||
|
||||
static void rna_def_curve_nurb(BlenderRNA *brna)
|
||||
|
@@ -382,6 +382,9 @@ struct MTex *rna_mtex_texture_slots_add(struct ID *self, struct bContext *C, str
|
||||
struct MTex *rna_mtex_texture_slots_create(struct ID *self, struct bContext *C, struct ReportList *reports, int index);
|
||||
void rna_mtex_texture_slots_clear(struct ID *self, struct bContext *C, struct ReportList *reports, int index);
|
||||
|
||||
|
||||
int rna_IDMaterials_assign_int(struct PointerRNA *ptr, int key, struct PointerRNA *assign_ptr);
|
||||
|
||||
#endif /* RNA_INTERNAL_H */
|
||||
|
||||
|
||||
|
@@ -102,7 +102,7 @@ typedef PointerRNA (*PropCollectionGetFunc)(struct CollectionPropertyIterator *i
|
||||
typedef int (*PropCollectionLengthFunc)(struct PointerRNA *ptr);
|
||||
typedef int (*PropCollectionLookupIntFunc)(struct PointerRNA *ptr, int key, struct PointerRNA *r_ptr);
|
||||
typedef int (*PropCollectionLookupStringFunc)(struct PointerRNA *ptr, const char *key, struct PointerRNA *r_ptr);
|
||||
typedef int (*PropCollectionAssignIntFunc)(struct PointerRNA *ptr, int key, struct PointerRNA *assign_ptr);
|
||||
typedef int (*PropCollectionAssignIntFunc)(struct PointerRNA *ptr, int key, const struct PointerRNA *assign_ptr);
|
||||
|
||||
/* Container - generic abstracted container of RNA properties */
|
||||
typedef struct ContainerRNA {
|
||||
|
@@ -1942,6 +1942,7 @@ static void rna_def_mesh(BlenderRNA *brna)
|
||||
RNA_def_property_struct_type(prop, "Material");
|
||||
RNA_def_property_ui_text(prop, "Materials", "");
|
||||
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
|
||||
RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
|
||||
|
||||
/* Mesh Draw Options for Edit Mode*/
|
||||
|
||||
|
@@ -330,7 +330,8 @@ static void rna_def_metaball(BlenderRNA *brna)
|
||||
RNA_def_property_collection_sdna(prop, NULL, "mat", "totcol");
|
||||
RNA_def_property_struct_type(prop, "Material");
|
||||
RNA_def_property_ui_text(prop, "Materials", "");
|
||||
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
|
||||
RNA_def_property_srna(prop, "IDMaterials"); /* see rna_ID.c */
|
||||
RNA_def_property_collection_funcs(prop, 0, NULL, NULL, NULL, NULL, NULL, NULL, "rna_IDMaterials_assign_int");
|
||||
|
||||
/* anim */
|
||||
rna_def_animdata_common(srna);
|
||||
|
@@ -1922,6 +1922,21 @@ static int pyrna_prop_collection_bool(BPy_PropertyRNA *self)
|
||||
return test;
|
||||
}
|
||||
|
||||
|
||||
#define PYRNA_PROP_COLLECTION_ABS_INDEX(ret_err) \
|
||||
/* notice getting the length of the collection is avoided unless negative \
|
||||
* index is used or to detect internal error with a valid index. \
|
||||
* This is done for faster lookups. */ \
|
||||
if(keynum < 0) { \
|
||||
keynum_abs += RNA_property_collection_length(&self->ptr, self->prop); \
|
||||
if(keynum_abs < 0) { \
|
||||
PyErr_Format(PyExc_IndexError, \
|
||||
"bpy_prop_collection[%d]: out of range.", keynum); \
|
||||
return ret_err; \
|
||||
} \
|
||||
} \
|
||||
|
||||
|
||||
/* internal use only */
|
||||
static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum)
|
||||
{
|
||||
@@ -1930,17 +1945,7 @@ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_s
|
||||
|
||||
PYRNA_PROP_CHECK_OBJ(self)
|
||||
|
||||
/* notice getting the length of the collection is avoided unless negative index is used
|
||||
* or to detect internal error with a valid index.
|
||||
* This is done for faster lookups. */
|
||||
if(keynum < 0) {
|
||||
keynum_abs += RNA_property_collection_length(&self->ptr, self->prop);
|
||||
|
||||
if(keynum_abs < 0) {
|
||||
PyErr_Format(PyExc_IndexError, "bpy_prop_collection[%d]: out of range.", keynum);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
PYRNA_PROP_COLLECTION_ABS_INDEX(NULL);
|
||||
|
||||
if(RNA_property_collection_lookup_int(&self->ptr, self->prop, keynum_abs, &newptr)) {
|
||||
return pyrna_struct_CreatePyObject(&newptr);
|
||||
@@ -1963,6 +1968,28 @@ static PyObject *pyrna_prop_collection_subscript_int(BPy_PropertyRNA *self, Py_s
|
||||
}
|
||||
}
|
||||
|
||||
/* values type must have been already checked */
|
||||
static int pyrna_prop_collection_ass_subscript_int(BPy_PropertyRNA *self, Py_ssize_t keynum, PyObject *value)
|
||||
{
|
||||
Py_ssize_t keynum_abs= keynum;
|
||||
const PointerRNA *ptr= (value == Py_None) ? (&PointerRNA_NULL) : &((BPy_StructRNA *)value)->ptr;
|
||||
|
||||
PYRNA_PROP_CHECK_INT(self)
|
||||
|
||||
PYRNA_PROP_COLLECTION_ABS_INDEX(-1);
|
||||
|
||||
if(RNA_property_collection_assign_int(&self->ptr, self->prop, keynum_abs, ptr) == 0) {
|
||||
|
||||
PyErr_Format(PyExc_IndexError,
|
||||
"bpy_prop_collection[index] = value: "
|
||||
"failed assignment (unknown reason)", keynum);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *pyrna_prop_array_subscript_int(BPy_PropertyArrayRNA *self, int keynum)
|
||||
{
|
||||
int len;
|
||||
@@ -2173,6 +2200,128 @@ static PyObject *pyrna_prop_collection_subscript(BPy_PropertyRNA *self, PyObject
|
||||
}
|
||||
}
|
||||
|
||||
/* generic check to see if a PyObject is compatible with a collection
|
||||
* -1 on failier, 0 on success, sets the error */
|
||||
static int pyrna_prop_collection_type_check(BPy_PropertyRNA *self, PyObject *value)
|
||||
{
|
||||
StructRNA *prop_srna;
|
||||
|
||||
if(value == Py_None) {
|
||||
if (RNA_property_flag(self->prop) & PROP_NEVER_NULL) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"bpy_prop_collection[key] = value: invalid, "
|
||||
"this collection doesnt support None assignment");
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0; /* None is OK */
|
||||
}
|
||||
}
|
||||
else if (BPy_StructRNA_Check(value) == 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"bpy_prop_collection[key] = value: invalid, "
|
||||
"expected a StructRNA type or None, not a %.200s",
|
||||
Py_TYPE(value)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
else if((prop_srna= RNA_property_pointer_type(&self->ptr, self->prop))) {
|
||||
StructRNA *value_srna= ((BPy_StructRNA *)value)->ptr.type;
|
||||
if (RNA_struct_is_a(value_srna, prop_srna) == 0) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"bpy_prop_collection[key] = value: invalid, "
|
||||
"expected a '%.200s' type or None, not a '%.200s'",
|
||||
RNA_struct_identifier(prop_srna),
|
||||
RNA_struct_identifier(value_srna)
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0; /* OK, this is the correct type!*/
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"bpy_prop_collection[key] = value: internal error, "
|
||||
"failed to get the collection type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* note: currently this is a copy of 'pyrna_prop_collection_subscript' with
|
||||
* large blocks commented, we may support slice/key indicies later */
|
||||
static int pyrna_prop_collection_ass_subscript(BPy_PropertyRNA *self, PyObject *key, PyObject *value)
|
||||
{
|
||||
PYRNA_PROP_CHECK_INT(self);
|
||||
|
||||
/* validate the assigned value */
|
||||
if(value == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"del bpy_prop_collection[key]: not supported");
|
||||
return -1;
|
||||
}
|
||||
else if (pyrna_prop_collection_type_check(self, value) == -1) {
|
||||
return -1; /* exception is set */
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (PyUnicode_Check(key)) {
|
||||
return pyrna_prop_collection_subscript_str(self, _PyUnicode_AsString(key));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (PyIndex_Check(key)) {
|
||||
Py_ssize_t i= PyNumber_AsSsize_t(key, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return -1;
|
||||
|
||||
return pyrna_prop_collection_ass_subscript_int(self, i, value);
|
||||
}
|
||||
#if 0 /* TODO, fake slice assignment */
|
||||
else if (PySlice_Check(key)) {
|
||||
PySliceObject *key_slice= (PySliceObject *)key;
|
||||
Py_ssize_t step= 1;
|
||||
|
||||
if(key_slice->step != Py_None && !_PyEval_SliceIndex(key, &step)) {
|
||||
return NULL;
|
||||
}
|
||||
else if (step != 1) {
|
||||
PyErr_SetString(PyExc_TypeError, "bpy_prop_collection[slice]: slice steps not supported");
|
||||
return NULL;
|
||||
}
|
||||
else if(key_slice->start == Py_None && key_slice->stop == Py_None) {
|
||||
return pyrna_prop_collection_subscript_slice(self, 0, PY_SSIZE_T_MAX);
|
||||
}
|
||||
else {
|
||||
Py_ssize_t start= 0, stop= PY_SSIZE_T_MAX;
|
||||
|
||||
/* avoid PySlice_GetIndicesEx because it needs to know the length ahead of time. */
|
||||
if(key_slice->start != Py_None && !_PyEval_SliceIndex(key_slice->start, &start)) return NULL;
|
||||
if(key_slice->stop != Py_None && !_PyEval_SliceIndex(key_slice->stop, &stop)) return NULL;
|
||||
|
||||
if(start < 0 || stop < 0) {
|
||||
/* only get the length for negative values */
|
||||
Py_ssize_t len= (Py_ssize_t)RNA_property_collection_length(&self->ptr, self->prop);
|
||||
if(start < 0) start += len;
|
||||
if(stop < 0) start += len;
|
||||
}
|
||||
|
||||
if (stop - start <= 0) {
|
||||
return PyList_New(0);
|
||||
}
|
||||
else {
|
||||
return pyrna_prop_collection_subscript_slice(self, start, stop);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"bpy_prop_collection[key]: invalid key, "
|
||||
"must be a string or an int, not %.200s",
|
||||
Py_TYPE(key)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *pyrna_prop_array_subscript(BPy_PropertyArrayRNA *self, PyObject *key)
|
||||
{
|
||||
PYRNA_PROP_CHECK_OBJ((BPy_PropertyRNA *)self)
|
||||
@@ -2409,7 +2558,7 @@ static PyMappingMethods pyrna_prop_array_as_mapping= {
|
||||
static PyMappingMethods pyrna_prop_collection_as_mapping= {
|
||||
(lenfunc) pyrna_prop_collection_length, /* mp_length */
|
||||
(binaryfunc) pyrna_prop_collection_subscript, /* mp_subscript */
|
||||
(objobjargproc) NULL, /* mp_ass_subscript */
|
||||
(objobjargproc) pyrna_prop_collection_ass_subscript, /* mp_ass_subscript */
|
||||
};
|
||||
|
||||
/* only for fast bool's, large structs, assign nb_bool on init */
|
||||
@@ -2505,7 +2654,7 @@ static PySequenceMethods pyrna_prop_collection_as_sequence= {
|
||||
NULL, /* sq_repeat */
|
||||
(ssizeargfunc)pyrna_prop_collection_subscript_int, /* sq_item */ /* Only set this so PySequence_Check() returns True */
|
||||
NULL, /* *was* sq_slice */
|
||||
NULL, /* sq_ass_item */
|
||||
(ssizeobjargproc)/* pyrna_prop_collection_ass_subscript_int */ NULL /* let mapping take this one */, /* sq_ass_item */
|
||||
NULL, /* *was* sq_ass_slice */
|
||||
(objobjproc)pyrna_prop_collection_contains, /* sq_contains */
|
||||
(binaryfunc) NULL, /* sq_inplace_concat */
|
||||
|
Reference in New Issue
Block a user