[Bf-blender-cvs] [5a6d5d20de2] master: UI: add description methods for `wm.context_*` operators

Campbell Barton noreply at git.blender.org
Tue Mar 30 16:02:25 CEST 2021


Commit: 5a6d5d20de2cfa43d14d67970b2f2eb24048b230
Author: Campbell Barton
Date:   Wed Mar 31 00:44:29 2021 +1100
Branches: master
https://developer.blender.org/rB5a6d5d20de2cfa43d14d67970b2f2eb24048b230

UI: add description methods for `wm.context_*` operators

Generic context operators now look-up the RNA properties to extract
their description (when it's available).

Add `bl_rna_utils.data_path.property_definition_from_data_path()`
to handle the details of accessing the RNA property definition.

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

A	release/scripts/modules/bl_rna_utils/__init__.py
A	release/scripts/modules/bl_rna_utils/data_path.py
M	release/scripts/startup/bl_operators/wm.py

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

diff --git a/release/scripts/modules/bl_rna_utils/__init__.py b/release/scripts/modules/bl_rna_utils/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/release/scripts/modules/bl_rna_utils/data_path.py b/release/scripts/modules/bl_rna_utils/data_path.py
new file mode 100644
index 00000000000..76306e379f0
--- /dev/null
+++ b/release/scripts/modules/bl_rna_utils/data_path.py
@@ -0,0 +1,80 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+__all__ = (
+    "property_definition_from_data_path",
+)
+
+class _TokenizeDataPath:
+    """Class to split up tokens of a data-path."""
+    __slots__ = (
+        "data_path",
+    )
+
+    def __init__(self, attrs):
+        self.data_path = attrs
+
+    def __getattr__(self, attr):
+        return _TokenizeDataPath(self.data_path + ((".%s" % attr),))
+
+    def __getitem__(self, key):
+        return _TokenizeDataPath(self.data_path + (("[%r]" % (key,)),))
+
+    def __call__(self, *args, **kw):
+        value_str = ", ".join([
+            val for val in (
+                repr(args)[1:-1],
+                ", ".join(["%s=%r" % (key, value) for key, value in kw.items()])
+            ) if val])
+        return _TokenizeDataPath(self.data_path + ('(%s)' % value_str, ))
+
+    def __iter__(self):
+        return iter(self.data_path)
+
+
+def property_definition_from_data_path(base, data_path):
+    """
+    Return an RNA property definition from an object and a data path.
+
+    In Blender this is often used with ``context`` as the base and a
+    path that it references, for example ``.space_data.lock_camera``.
+    """
+    base_tokenize = _TokenizeDataPath(())
+    data = list(eval("base_tokenize" + data_path))
+    del base_tokenize
+    while data and (not data[-1].startswith(".")):
+        data.pop()
+
+    if (not data) or (not data[-1].startswith(".")) or (len(data) < 2):
+        return None
+
+    data_path_head = "".join(data[:-1])
+    data_path_tail = data[-1]
+
+    value_head = eval("base" + data_path_head)
+    value_head_rna = getattr(value_head, "bl_rna", None)
+    if value_head_rna is None:
+        return None
+
+    value_tail = value_head.bl_rna.properties.get(data_path_tail[1:])
+    if not value_tail:
+        return None
+
+    return value_tail
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 2f97942faa4..18e938ac9b2 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -95,6 +95,28 @@ def context_path_validate(context, data_path):
     return value
 
 
+def context_path_description(context, data_path):
+    from bl_rna_utils.data_path import property_definition_from_data_path
+    rna_prop = property_definition_from_data_path(context, "." + data_path)
+    if rna_prop is not None:
+        description = rna_prop.description
+        if description:
+            return description
+    return None
+
+
+def description_from_data_path(base, data_path, *, prefix, value=Ellipsis):
+    if context_path_validate(base, data_path) is Ellipsis:
+        return None
+    description = context_path_description(base, data_path)
+    if description:
+        description = "%s: %s" % (prefix, description)
+        if value != Ellipsis:
+            description = "%s\n%s: %s" % (description, iface_("Value"), str(value))
+        return description
+    return None
+
+
 def operator_value_is_undo(value):
     if value in {None, Ellipsis}:
         return False
@@ -168,6 +190,10 @@ class WM_OT_context_set_boolean(Operator):
         default=True,
     )
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
     execute = execute_context_assign
 
 
@@ -185,6 +211,10 @@ class WM_OT_context_set_int(Operator):  # same as enum
     )
     relative: rna_relative_prop
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix="Assign", value=props.value)
+
     execute = execute_context_assign
 
 
@@ -201,6 +231,10 @@ class WM_OT_context_scale_float(Operator):
         default=1.0,
     )
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Scale"), value=props.value)
+
     def execute(self, context):
         data_path = self.data_path
         if context_path_validate(context, data_path) is Ellipsis:
@@ -235,6 +269,10 @@ class WM_OT_context_scale_int(Operator):
         options={'SKIP_SAVE'},
     )
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Scale"), value=props.value)
+
     def execute(self, context):
         data_path = self.data_path
         if context_path_validate(context, data_path) is Ellipsis:
@@ -274,6 +312,10 @@ class WM_OT_context_set_float(Operator):  # same as enum
     )
     relative: rna_relative_prop
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix="Assign", value=props.value)
+
     execute = execute_context_assign
 
 
@@ -290,6 +332,10 @@ class WM_OT_context_set_string(Operator):  # same as enum
         maxlen=1024,
     )
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
     execute = execute_context_assign
 
 
@@ -306,6 +352,10 @@ class WM_OT_context_set_enum(Operator):
         maxlen=1024,
     )
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
     execute = execute_context_assign
 
 
@@ -322,6 +372,10 @@ class WM_OT_context_set_value(Operator):
         maxlen=1024,
     )
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Assign"), value=props.value)
+
     def execute(self, context):
         data_path = self.data_path
         if context_path_validate(context, data_path) is Ellipsis:
@@ -339,6 +393,13 @@ class WM_OT_context_toggle(Operator):
     data_path: rna_path_prop
     module: rna_module_prop
 
+    @classmethod
+    def description(cls, context, props):
+        # Currently unsupported, it might be possible to extract this.
+        if props.module:
+            return None
+        return description_from_data_path(context, props.data_path, prefix=iface_("Toggle"))
+
     def execute(self, context):
         data_path = self.data_path
 
@@ -375,6 +436,11 @@ class WM_OT_context_toggle_enum(Operator):
         maxlen=1024,
     )
 
+    @classmethod
+    def description(cls, context, props):
+        value = "(%r, %r)" % (props.value_1, props.value_2)
+        return description_from_data_path(context, props.data_path, prefix=iface_("Toggle"), value=value)
+
     def execute(self, context):
         data_path = self.data_path
 
@@ -406,6 +472,10 @@ class WM_OT_context_cycle_int(Operator):
     reverse: rna_reverse_prop
     wrap: rna_wrap_prop
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
+
     def execute(self, context):
         data_path = self.data_path
         value = context_path_validate(context, data_path)
@@ -442,6 +512,10 @@ class WM_OT_context_cycle_enum(Operator):
     reverse: rna_reverse_prop
     wrap: rna_wrap_prop
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
+
     def execute(self, context):
         data_path = self.data_path
         value = context_path_validate(context, data_path)
@@ -498,6 +572,10 @@ class WM_OT_context_cycle_array(Operator):
     data_path: rna_path_prop
     reverse: rna_reverse_prop
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Cycle"))
+
     def execute(self, context):
         data_path = self.data_path
         value = context_path_validate(context, data_path)
@@ -523,6 +601,10 @@ class WM_OT_context_menu_enum(Operator):
 
     data_path: rna_path_prop
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Menu"))
+
     def execute(self, context):
         data_path = self.data_path
         value = context_path_validate(context, data_path)
@@ -550,6 +632,10 @@ class WM_OT_context_pie_enum(Operator):
 
     data_path: rna_path_prop
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Pie Menu"))
+
     def invoke(self, context, event):
         wm = context.window_manager
         data_path = self.data_path
@@ -587,6 +673,10 @@ class WM_OT_operator_pie_enum(Operator):
         maxlen=1024,
     )
 
+    @classmethod
+    def description(cls, context, props):
+        return description_from_data_path(context, props.data_path, prefix=iface_("Pie Menu"))
+
     def invoke(self, co

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list