Merge branch 'master' into blender2.8
[blender.git] / source / blender / python / intern / bpy_rna.c
index c323366454e8063dc7c087540f020afcddebf3b0..1368b610b53e1021cd26d8d74d524b7da76d4305 100644 (file)
@@ -310,7 +310,7 @@ static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
        ID *id = ptr->id.data;
        if (id) {
                const short idcode = GS(id->name);
-               if (!ELEM(idcode, ID_WM, ID_SCR)) { /* may need more added here */
+               if (!ELEM(idcode, ID_WM, ID_SCR, ID_WS)) { /* may need more added here */
                        const char *idtype = BKE_idcode_to_name(idcode);
                        const char *pyname;
                        if (key && PyUnicode_Check(key)) pyname = _PyUnicode_AsString(key);
@@ -1842,19 +1842,28 @@ static int pyrna_py_to_prop(
                                 * class mixing if this causes problems in the future it should be removed.
                                 */
                                if ((ptr_type == &RNA_AnyType) &&
-                                   (BPy_StructRNA_Check(value)) &&
-                                   (RNA_struct_is_a(((BPy_StructRNA *)value)->ptr.type, &RNA_Operator)))
+                                   (BPy_StructRNA_Check(value)))
                                {
-                                       value = PyObject_GetAttrString(value, "properties");
-                                       value_new = value;
+                                       const StructRNA *base_type =
+                                               RNA_struct_base_child_of(((const BPy_StructRNA *)value)->ptr.type, NULL);
+                                       if (ELEM(base_type, &RNA_Operator, &RNA_Manipulator)) {
+                                               value = PyObject_GetAttr(value, bpy_intern_str_properties);
+                                               value_new = value;
+                                       }
                                }
 
-
-                               /* if property is an OperatorProperties pointer and value is a map,
+                               /* if property is an OperatorProperties/ManipulatorProperties pointer and value is a map,
                                 * forward back to pyrna_pydict_to_props */
-                               if (RNA_struct_is_a(ptr_type, &RNA_OperatorProperties) && PyDict_Check(value)) {
-                                       PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
-                                       return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+                               if (PyDict_Check(value)) {
+                                       const StructRNA *base_type = RNA_struct_base_child_of(ptr_type, NULL);
+                                       if (base_type == &RNA_OperatorProperties) {
+                                               PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+                                               return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+                                       }
+                                       else if (base_type == &RNA_ManipulatorProperties) {
+                                               PointerRNA opptr = RNA_property_pointer_get(ptr, prop);
+                                               return pyrna_pydict_to_props(&opptr, value, false, error_prefix);
+                                       }
                                }
 
                                /* another exception, allow to pass a collection as an RNA property */
@@ -6712,7 +6721,30 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
        if (ptr->data == NULL && ptr->type == NULL) { /* Operator RNA has NULL data */
                Py_RETURN_NONE;
        }
-       else {
+
+       /* New in 2.8x, since not many types support instancing
+        * we may want to use a flag to avoid looping over all classes. - campbell */
+       void **instance = ptr->data ? RNA_struct_instance(ptr) : NULL;
+       if (instance && *instance) {
+               pyrna = *instance;
+
+               /* Refine may have changed types after the first instance was created. */
+               if (ptr->type == pyrna->ptr.type) {
+                       Py_INCREF(pyrna);
+                       return (PyObject *)pyrna;
+               }
+               else {
+                       /* Existing users will need to use 'type_recast' method. */
+                       Py_DECREF(pyrna);
+                       *instance = NULL;
+                       /* Continue as if no instance was made */
+#if 0          /* no need to assign, will be written to next... */
+                       pyrna = NULL;
+#endif
+               }
+       }
+
+       {
                PyTypeObject *tp = (PyTypeObject *)pyrna_struct_Subtype(ptr);
 
                if (tp) {
@@ -6733,6 +6765,12 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
                return NULL;
        }
 
+       /* Blender's instance owns a reference (to avoid Python freeing it). */
+       if (instance) {
+               *instance = pyrna;
+               Py_INCREF(pyrna);
+       }
+
        pyrna->ptr = *ptr;
 #ifdef PYRNA_FREE_SUPPORT
        pyrna->freeptr = false;
@@ -7497,7 +7535,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
        PyObject *args;
        PyObject *ret = NULL, *py_srna = NULL, *py_class_instance = NULL, *parmitem;
        PyTypeObject *py_class;
-       void **py_class_instance_store = NULL;
        PropertyRNA *parm;
        ParameterIterator iter;
        PointerRNA funcptr;
@@ -7512,7 +7549,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
        PyGILState_STATE gilstate;
 
 #ifdef USE_PEDANTIC_WRITE
-       const bool is_operator = RNA_struct_is_a(ptr->type, &RNA_Operator);
+       const bool is_readonly_init = !(RNA_struct_is_a(ptr->type, &RNA_Operator) ||
+                                       RNA_struct_is_a(ptr->type, &RNA_Manipulator));
        // const char *func_id = RNA_function_identifier(func);  /* UNUSED */
        /* testing, for correctness, not operator and not draw function */
        const bool is_readonly = !(RNA_function_flag(func) & FUNC_ALLOW_WRITE);
@@ -7547,10 +7585,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
                                        py_class_instance = *instance;
                                        Py_INCREF(py_class_instance);
                                }
-                               else {
-                                       /* store the instance here once its created */
-                                       py_class_instance_store = instance;
-                               }
                        }
                }
                /* end exception */
@@ -7577,7 +7611,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
                        if (py_class->tp_init) {
 #ifdef USE_PEDANTIC_WRITE
                                const int prev_write = rna_disallow_writes;
-                               rna_disallow_writes = is_operator ? false : true;  /* only operators can write on __init__ */
+                               rna_disallow_writes = is_readonly_init ? false : true;  /* only operators can write on __init__ */
 #endif
 
                                /* true in most cases even when the class its self doesn't define an __init__ function. */
@@ -7621,10 +7655,6 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param
                        if (py_class_instance == NULL) {
                                err = -1; /* so the error is not overridden below */
                        }
-                       else if (py_class_instance_store) {
-                               *py_class_instance_store = py_class_instance;
-                               Py_INCREF(py_class_instance);
-                       }
                }
        }