Fix [#34675] *AFTER 2.69* Info view shows duplicate operators with incorrect values...
authorBastien Montagne <montagne29@wanadoo.fr>
Wed, 6 Nov 2013 20:56:18 +0000 (20:56 +0000)
committerBastien Montagne <montagne29@wanadoo.fr>
Wed, 6 Nov 2013 20:56:18 +0000 (20:56 +0000)
Refactored a bit WM api to generate operator's pystring, now it can also handle correctly macro operators. Thanks to Campbell for the review!

source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_regions.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_access.c
source/blender/python/intern/bpy_operator.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_operators.c
source/blenderplayer/bad_level_call_stubs/stubs.c

index 8a0b3a500b5362a2d01d9a5696c3f010b0c525ff..903a5e724994b34e8362df0f9a5a5cfa9ec3b484 100644 (file)
@@ -1534,7 +1534,7 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data,
                        char *str;
                        opptr = uiButGetOperatorPtrRNA(but); /* allocated when needed, the button owns it */
 
-                       str = WM_operator_pystring(C, but->optype, opptr, 0);
+                       str = WM_operator_pystring_ex(C, NULL, false, but->optype, opptr);
 
                        WM_clipboard_text_set(str, 0);
 
index b453a3b8363a1dcf95076b0203cd16b6f2328975..89c244009e5b124e2db33aedd8eb69fd03be8b91 100644 (file)
@@ -2931,7 +2931,7 @@ static void ui_intro_button(DynStr *ds, uiButtonItem *bitem)
        BLI_dynstr_appendf(ds, "'tip':'''%s''', ", but->tip ? but->tip : "");  /* not exactly needed, rna has this */
 
        if (but->optype) {
-               char *opstr = WM_operator_pystring(but->block->evil_C, but->optype, but->opptr, 0);
+               char *opstr = WM_operator_pystring_ex(but->block->evil_C, NULL, false, but->optype, but->opptr);
                BLI_dynstr_appendf(ds, "'operator':'''%s''', ", opstr ? opstr : "");
                MEM_freeN(opstr);
        }
index 15fbd51c6fccf0648483ba09f3fab73de9d9a692..3ef613f58678827d7e178fdd590238e374f97563 100644 (file)
@@ -539,7 +539,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but)
                /* so the context is passed to itemf functions (some py itemf functions use it) */
                WM_operator_properties_sanitize(opptr, false);
 
-               str = WM_operator_pystring(C, but->optype, opptr, 0);
+               str = WM_operator_pystring_ex(C, NULL, false, but->optype, opptr);
 
                /* operator info */
                if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) {
index b4b79059f932159342247a8fd4873646c56a2337..f5afff56545de64cb731a40a7e1b177eaedd9d57 100644 (file)
@@ -1034,6 +1034,7 @@ void RNA_struct_property_unset(PointerRNA *ptr, const char *identifier);
 
 /* python compatible string representation of this property, (must be freed!) */
 char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index, int max_prop_length);
+char *RNA_pointer_as_string_id(struct bContext *C, PointerRNA *ptr);
 char *RNA_pointer_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop_ptr, PointerRNA *ptr_prop);
 char *RNA_pointer_as_string_keywords_ex(struct bContext *C, PointerRNA *ptr,
                                         const bool skip_optional_value, const bool all_args,
index fe457a14718d318dd96c51d524e1f0dc4cf374d0..6c216936190b910e04a9daf5c536a9a25936e0ec 100644 (file)
@@ -4980,7 +4980,7 @@ bool RNA_property_is_unlink(PropertyRNA *prop)
 /* string representation of a property, python
  * compatible but can be used for display too,
  * context may be NULL */
-static char *rna_pointer_as_string__idprop(bContext *C, PointerRNA *ptr)
+char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
 {
        DynStr *dynstr = BLI_dynstr_new();
        char *cstring;
@@ -5031,7 +5031,7 @@ static char *rna_pointer_as_string__bldata(PointerRNA *ptr)
 char *RNA_pointer_as_string(bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *prop_ptr, PointerRNA *ptr_prop)
 {
        if (RNA_property_flag(prop_ptr) & PROP_IDPROPERTY) {
-               return rna_pointer_as_string__idprop(C, ptr_prop);
+               return RNA_pointer_as_string_id(C, ptr_prop);
        }
        else {
                return rna_pointer_as_string__bldata(ptr_prop);
index d13ec3c461a0a809fd3404b12531a1ddf7e998d9..754952cd65f187e2ecb42dfe0f81d034bda72768 100644 (file)
@@ -345,7 +345,7 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args)
                error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: ");
 
        if (error_val == 0)
-               buf = WM_operator_pystring(C, ot, &ptr, all_args);
+               buf = WM_operator_pystring_ex(C, NULL, all_args, ot, &ptr);
 
        WM_operator_properties_free(&ptr);
 
index 75a6e4465bff3d496fc0713618d24878962690c8..1f38368399ae7682305175f7ec2b26b258b627df 100644 (file)
@@ -272,7 +272,9 @@ bool        WM_operator_last_properties_store(struct wmOperator *op);
 
 
                /* operator as a python command (resultuing string must be freed) */
-char           *WM_operator_pystring(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *opptr, int all_args);
+char           *WM_operator_pystring_ex(struct bContext *C, struct wmOperator *op, const bool all_args,
+                                     struct wmOperatorType *ot, struct PointerRNA *opptr);
+char           *WM_operator_pystring(struct bContext *C, struct wmOperator *op, const bool all_args);
 char           *WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
 void           WM_operator_bl_idname(char *to, const char *from);
 void           WM_operator_py_idname(char *to, const char *from);
index 825c1ca9252a93395faadaca7efb8b4de1e2f227..d60901f1325103f900c5bbbe6cc8bb3e0856e702 100644 (file)
@@ -491,7 +491,7 @@ int WM_operator_poll_context(bContext *C, wmOperatorType *ot, short context)
 static void wm_operator_print(bContext *C, wmOperator *op)
 {
        /* context is needed for enum function */
-       char *buf = WM_operator_pystring(C, op->type, op->ptr, false);
+       char *buf = WM_operator_pystring(C, op, false);
        printf("%s\n", buf);
        MEM_freeN(buf);
 }
@@ -626,7 +626,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, int cal
                if (op->type->flag & OPTYPE_REGISTER) {
                        if (G.background == 0) { /* ends up printing these in the terminal, gets annoying */
                                /* Report the python string representation of the operator */
-                               char *buf = WM_operator_pystring(C, op->type, op->ptr, false);
+                               char *buf = WM_operator_pystring(C, op, false);
                                BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
                                MEM_freeN(buf);
                        }
@@ -660,7 +660,7 @@ static void wm_operator_finished(bContext *C, wmOperator *op, int repeat)
        
        if (repeat == 0) {
                if (G.debug & G_DEBUG_WM) {
-                       char *buf = WM_operator_pystring(C, op->type, op->ptr, false);
+                       char *buf = WM_operator_pystring(C, op, false);
                        BKE_report(CTX_wm_reports(C), RPT_OPERATOR, buf);
                        MEM_freeN(buf);
                }
index eb42f44b696c4acb6ce0a8c5d2b97d5b5f23f0e9..ab8dac396c5c86e56069d0bd62aab9f6186e1087 100644 (file)
@@ -521,13 +521,14 @@ void WM_operator_bl_idname(char *to, const char *from)
                to[0] = 0;
 }
 
-/* print a string representation of the operator, with the args that it runs 
- * so python can run it again,
+/* Print a string representation of the operator, with the args that it runs so python can run it again.
  *
- * When calling from an existing wmOperator do.
- * WM_operator_pystring(op->type, op->ptr);
+ * When calling from an existing wmOperator, better to use simple version:
+ *     WM_operator_pystring(C, op);
+ *
+ * Note: both op and opptr may be NULL (op is only used for macro operators).
  */
-char *WM_operator_pystring(bContext *C, wmOperatorType *ot, PointerRNA *opptr, int all_args)
+char *WM_operator_pystring_ex(bContext *C, wmOperator *op, const bool all_args, wmOperatorType *ot, PointerRNA *opptr)
 {
        char idname_py[OP_MAX_TYPENAME];
 
@@ -539,24 +540,53 @@ char *WM_operator_pystring(bContext *C, wmOperatorType *ot, PointerRNA *opptr, i
        /* arbitrary, but can get huge string with stroke painting otherwise */
        int max_prop_length = 10;
 
-       /* only to get the orginal props for comparisons */
-       PointerRNA opptr_default;
+       WM_operator_py_idname(idname_py, ot->idname);
+       BLI_dynstr_appendf(dynstr, "bpy.ops.%s(", idname_py);
+
+       if (op && op->macro.first) {
+               /* Special handling for macros, else we only get default values in this case... */
+               wmOperator *opm;
+               bool first_op = true;
+               for (opm = op->macro.first; opm; opm = opm->next) {
+                       PointerRNA *opmptr = opm->ptr;
+                       PointerRNA opmptr_default;
+                       if (opmptr == NULL) {
+                               WM_operator_properties_create_ptr(&opmptr_default, opm->type);
+                               opmptr = &opmptr_default;
+                       }
+
+                       cstring_args = RNA_pointer_as_string_id(C, opmptr);
+                       if (first_op) {
+                               BLI_dynstr_appendf(dynstr, "%s=%s", opm->type->idname, cstring_args);
+                               first_op = false;
+                       }
+                       else {
+                               BLI_dynstr_appendf(dynstr, ", %s=%s", opm->type->idname, cstring_args);
+                       }
+                       MEM_freeN(cstring_args);
 
-       if (opptr == NULL) {
-               WM_operator_properties_create_ptr(&opptr_default, ot);
-               opptr = &opptr_default;
+                       if (opmptr == &opmptr_default) {
+                               WM_operator_properties_free(&opmptr_default);
+                       }
+               }
        }
+       else {
+               /* only to get the orginal props for comparisons */
+               PointerRNA opptr_default;
 
-       WM_operator_py_idname(idname_py, ot->idname);
-       BLI_dynstr_appendf(dynstr, "bpy.ops.%s(", idname_py);
+               if (opptr == NULL) {
+                       WM_operator_properties_create_ptr(&opptr_default, ot);
+                       opptr = &opptr_default;
+               }
 
-       cstring_args = RNA_pointer_as_string_keywords(C, opptr, false,
-                                                     all_args, max_prop_length);
-       BLI_dynstr_append(dynstr, cstring_args);
-       MEM_freeN(cstring_args);
+               cstring_args = RNA_pointer_as_string_keywords(C, opptr, false, all_args, max_prop_length);
+               BLI_dynstr_append(dynstr, cstring_args);
+               MEM_freeN(cstring_args);
 
-       if (opptr == &opptr_default)
-               WM_operator_properties_free(&opptr_default);
+               if (opptr == &opptr_default) {
+                       WM_operator_properties_free(&opptr_default);
+               }
+       }
 
        BLI_dynstr_append(dynstr, ")");
 
@@ -565,6 +595,11 @@ char *WM_operator_pystring(bContext *C, wmOperatorType *ot, PointerRNA *opptr, i
        return cstring;
 }
 
+char *WM_operator_pystring(bContext *C, wmOperator *op, const bool all_args)
+{
+       return WM_operator_pystring_ex(C, op, all_args, op->type, op->ptr);
+}
+
 /* return NULL if no match is found */
 #if 0
 static char *wm_prop_pystring_from_context(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index)
index 2916dddc68ff420ad634342cb5f605138b9b7671..80f3a617baccb748989b7b2d41be5e2a51b46576 100644 (file)
@@ -541,7 +541,8 @@ void WM_operator_py_idname(char *to, const char *from) {STUB_ASSERT(0);}
 void WM_operator_ui_popup(struct bContext *C, struct wmOperator *op, int width, int height) {STUB_ASSERT(0);}
 short insert_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) {STUB_ASSERT(0); return 0;}
 short delete_keyframe(struct ID *id, struct bAction *act, const char group[], const char rna_path[], int array_index, float cfra, short flag) {STUB_ASSERT(0); return 0;}
-char *WM_operator_pystring(struct bContext *C, struct wmOperatorType *ot, struct PointerRNA *opptr, int all_args) {STUB_ASSERT(0); return (char *)NULL;}
+char *WM_operator_pystring_ex(struct bContext *C, struct wmOperator *op, const bool all_args, struct wmOperatorType *ot, struct PointerRNA *opptr) {STUB_ASSERT(0); return (char *)NULL;}
+char *WM_operator_pystring(struct bContext *C, struct wmOperator *op, const bool all_args) {STUB_ASSERT(0); return (char *)NULL;}
 struct wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value) {STUB_ASSERT(0); return (struct wmKeyMapItem *)NULL;}
 struct wmKeyMapItem *WM_modalkeymap_add_item_str(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, const char *value) {STUB_ASSERT(0); return (struct wmKeyMapItem *)NULL;}
 struct wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, char *idname, EnumPropertyItem *items) {STUB_ASSERT(0); return (struct wmKeyMap *) NULL;}