[Bf-blender-cvs] [9ecbd67dfb6] master: Python API: implement an Operator callback for dynamic description.

Alexander Gavrilov noreply at git.blender.org
Fri Sep 6 21:09:46 CEST 2019


Commit: 9ecbd67dfb672cd13f021c82d83aeb7ae8a8cf10
Author: Alexander Gavrilov
Date:   Fri Sep 6 16:26:10 2019 +0300
Branches: master
https://developer.blender.org/rB9ecbd67dfb672cd13f021c82d83aeb7ae8a8cf10

Python API: implement an Operator callback for dynamic description.

Blender UI Layout API allows supplying parameters to operators via
button definitions. If an operator behavior strongly depends on its
parameters, it may be difficult to write a tooltip that covers all
of its operation modes. Thus it is useful to provide a way for the
operator to produce different descriptions based on the input info.

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D5709

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

M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_region_tooltip.c
M	source/blender/makesrna/intern/rna_wm.c
M	source/blender/makesrna/intern/rna_wm_api.c
M	source/blender/python/intern/bpy_rna.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/WM_types.h
M	source/blender/windowmanager/intern/wm_operator_type.c

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

diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 78b190a59e0..7bfd0200362 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -4250,7 +4250,7 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block,
     }
   }
 
-  if ((!tip || tip[0] == '\0') && ot && ot->srna) {
+  if ((!tip || tip[0] == '\0') && ot && ot->srna && !ot->get_description) {
     tip = RNA_struct_ui_description(ot->srna);
   }
 
@@ -6350,6 +6350,9 @@ void UI_but_string_info_get(bContext *C, uiBut *but, ...)
       else if (but->tip && but->tip[0]) {
         tmp = BLI_strdup(but->tip);
       }
+      else if (but->optype && but->optype->get_description) {
+        tmp = WM_operatortype_description(C, but->optype, but->opptr);
+      }
       else {
         type = BUT_GET_RNA_TIP; /* Fail-safe solution... */
       }
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 7387fe5eb1c..3f20e8247b9 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -932,18 +932,14 @@ static uiTooltipData *ui_tooltip_data_from_gizmo(bContext *C, wmGizmo *gz)
                                 NULL;
       if (gzop != NULL) {
         /* Description */
-        const char *info = RNA_struct_ui_description(gzop->type->srna);
-        if (!(info && info[0])) {
-          info = RNA_struct_ui_name(gzop->type->srna);
-        }
+        char *info = WM_operatortype_description(C, gzop->type, &gzop->ptr);
+
+        if (info != NULL) {
+          char *text = info;
 
-        if (info && info[0]) {
-          char *text = NULL;
           if (gzop_actions[i].prefix != NULL) {
             text = BLI_sprintfN("%s: %s", gzop_actions[i].prefix, info);
-          }
-          else {
-            text = BLI_strdup(info);
+            MEM_freeN(info);
           }
 
           if (text != NULL) {
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index c3ffeaf6f6f..5f60ecf449b 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -1420,6 +1420,39 @@ static void rna_operator_cancel_cb(bContext *C, wmOperator *op)
   RNA_parameter_list_free(&list);
 }
 
+static char *rna_operator_description_cb(bContext *C, wmOperatorType *ot, PointerRNA *prop_ptr)
+{
+  extern FunctionRNA rna_Operator_description_func;
+
+  PointerRNA ptr;
+  ParameterList list;
+  FunctionRNA *func;
+  void *ret;
+  char *result;
+
+  RNA_pointer_create(NULL, ot->ext.srna, NULL, &ptr); /* dummy */
+  func = &rna_Operator_description_func; /* RNA_struct_find_function(&ptr, "description"); */
+
+  RNA_parameter_list_create(&list, &ptr, func);
+  RNA_parameter_set_lookup(&list, "context", &C);
+  RNA_parameter_set_lookup(&list, "properties", prop_ptr);
+  ot->ext.call(C, &ptr, func, &list);
+
+  RNA_parameter_get_lookup(&list, "result", &ret);
+  result = (char *)ret;
+
+  if (result && result[0]) {
+    result = BLI_strdup(result);
+  }
+  else {
+    result = NULL;
+  }
+
+  RNA_parameter_list_free(&list);
+
+  return result;
+}
+
 static void rna_Operator_unregister(struct Main *bmain, StructRNA *type);
 
 /* bpy_operator_wrap.c */
@@ -1437,7 +1470,7 @@ static StructRNA *rna_Operator_register(Main *bmain,
   wmOperatorType dummyot = {NULL};
   wmOperator dummyop = {NULL};
   PointerRNA dummyotr;
-  int have_function[7];
+  int have_function[8];
 
   struct {
     char idname[OP_MAX_TYPENAME];
@@ -1531,6 +1564,7 @@ static StructRNA *rna_Operator_register(Main *bmain,
   dummyot.modal = (have_function[4]) ? rna_operator_modal_cb : NULL;
   dummyot.ui = (have_function[5]) ? rna_operator_draw_cb : NULL;
   dummyot.cancel = (have_function[6]) ? rna_operator_cancel_cb : NULL;
+  dummyot.get_description = (have_function[7]) ? rna_operator_description_cb : NULL;
   WM_operatortype_append_ptr(BPY_RNA_operator_wrapper, (void *)&dummyot);
 
   /* update while blender is running */
diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c
index d9306ba7a65..650d410091e 100644
--- a/source/blender/makesrna/intern/rna_wm_api.c
+++ b/source/blender/makesrna/intern/rna_wm_api.c
@@ -957,6 +957,18 @@ void RNA_api_operator(StructRNA *srna)
   RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
   parm = RNA_def_pointer(func, "context", "Context", "", "");
   RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+
+  /* description */
+  func = RNA_def_function(srna, "description", NULL);
+  RNA_def_function_ui_description(func, "Compute a description string that depends on parameters");
+  RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_REGISTER_OPTIONAL);
+  parm = RNA_def_string(func, "result", NULL, 4096, "result", "");
+  RNA_def_parameter_flags(parm, PROP_THICK_WRAP, 0);
+  RNA_def_function_output(func, parm);
+  parm = RNA_def_pointer(func, "context", "Context", "", "");
+  RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED);
+  parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "");
+  RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
 }
 
 void RNA_api_macro(StructRNA *srna)
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 12005b92388..c5424ca6ffb 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -1768,7 +1768,12 @@ static int pyrna_py_to_prop(
         if (value == Py_None) {
           if ((RNA_property_flag(prop) & PROP_NEVER_NULL) == 0) {
             if (data) {
-              *((char **)data) = (char *)NULL;
+              if (RNA_property_flag(prop) & PROP_THICK_WRAP) {
+                *(char *)data = 0;
+              }
+              else {
+                *((char **)data) = (char *)NULL;
+              }
             }
             else {
               RNA_property_string_set(ptr, prop, NULL);
@@ -1813,7 +1818,12 @@ static int pyrna_py_to_prop(
           }
           else {
             if (data) {
-              *((char **)data) = (char *)param;
+              if (RNA_property_flag(prop) & PROP_THICK_WRAP) {
+                BLI_strncpy((char *)data, (char *)param, RNA_property_string_maxlength(prop));
+              }
+              else {
+                *((char **)data) = (char *)param;
+              }
             }
             else {
               RNA_property_string_set_bytes(ptr, prop, param, PyBytes_Size(value));
@@ -1862,7 +1872,12 @@ static int pyrna_py_to_prop(
             /* XXX, this is suspect, but needed for function calls,
              * need to see if there's a better way. */
             if (data) {
-              *((char **)data) = (char *)param;
+              if (RNA_property_flag(prop) & PROP_THICK_WRAP) {
+                BLI_strncpy((char *)data, (char *)param, RNA_property_string_maxlength(prop));
+              }
+              else {
+                *((char **)data) = (char *)param;
+              }
             }
             else {
               RNA_property_string_set(ptr, prop, param);
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index c7b18adf9b1..b933448d0bd 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -547,6 +547,9 @@ struct wmOperatorTypeMacro *WM_operatortype_macro_define(struct wmOperatorType *
                                                          const char *idname);
 
 const char *WM_operatortype_name(struct wmOperatorType *ot, struct PointerRNA *properties);
+char *WM_operatortype_description(struct bContext *C,
+                                  struct wmOperatorType *ot,
+                                  struct PointerRNA *properties);
 
 /* wm_uilist_type.c */
 void WM_uilisttype_init(void);
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 7fdbf79248b..b3507c7e57e 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -737,6 +737,12 @@ typedef struct wmOperatorType {
    */
   const char *(*get_name)(struct wmOperatorType *, struct PointerRNA *);
 
+  /**
+   * Return a different description to use in the user interface, based on property values.
+   * The returned string must be freed by the caller, unless NULL.
+   */
+  char *(*get_description)(struct bContext *C, struct wmOperatorType *, struct PointerRNA *);
+
   /** rna for properties */
   struct StructRNA *srna;
 
diff --git a/source/blender/windowmanager/intern/wm_operator_type.c b/source/blender/windowmanager/intern/wm_operator_type.c
index 8f3052ace5e..96fbac3aecc 100644
--- a/source/blender/windowmanager/intern/wm_operator_type.c
+++ b/source/blender/windowmanager/intern/wm_operator_type.c
@@ -595,4 +595,35 @@ const char *WM_operatortype_name(struct wmOperatorType *ot, struct PointerRNA *p
   return (name && name[0]) ? name : RNA_struct_ui_name(ot->srna);
 }
 
+char *WM_operatortype_description(struct bContext *C,
+                                  struct wmOperatorType *ot,
+                                  struct PointerRNA *properties)
+{
+  if (ot->get_description && properties) {
+    char *description = ot->get_description(C, ot, properties);
+
+    if (description) {
+      if (description[0]) {
+        return description;
+      }
+      else {
+        MEM_freeN(description);
+      }
+    }
+  }
+
+  const char *info = RNA_struct_ui_description(ot->srna);
+
+  if (!(info && info[0])) {
+    info = RNA_struct_ui_name(ot->srna);
+  }
+
+  if (info && info[0]) {
+    return BLI_strdup(info);
+  }
+  else {
+    return NULL;
+  }
+}
+
 /** \} */



More information about the Bf-blender-cvs mailing list