Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Gavrilov <angavrilov@gmail.com>2019-09-06 16:26:10 +0300
committerYimingWu <xp8110@outlook.com>2019-09-12 04:13:02 +0300
commitde525a249d4df896f7e6654717efe7b945a7e59f (patch)
treee11376001fc40f273cade63b3be73aaf04854bbf
parenta9816ec802f9827eae1e2492a2f6054f9dd271e4 (diff)
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
-rw-r--r--source/blender/editors/interface/interface.c5
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c14
-rw-r--r--source/blender/makesrna/intern/rna_wm.c36
-rw-r--r--source/blender/makesrna/intern/rna_wm_api.c12
-rw-r--r--source/blender/python/intern/bpy_rna.c21
-rw-r--r--source/blender/windowmanager/WM_api.h3
-rw-r--r--source/blender/windowmanager/WM_types.h6
-rw-r--r--source/blender/windowmanager/intern/wm_operator_type.c31
8 files changed, 114 insertions, 14 deletions
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;
+ }
+}
+
/** \} */