[Bf-blender-cvs] [972677b25e1] master: UI: Improve layout of custom property edit panel

Hans Goudey noreply at git.blender.org
Mon Oct 25 17:01:13 CEST 2021


Commit: 972677b25e1d84e4c02d0e55b12ce87661faff5e
Author: Hans Goudey
Date:   Mon Oct 25 10:01:07 2021 -0500
Branches: master
https://developer.blender.org/rB972677b25e1d84e4c02d0e55b12ce87661faff5e

UI: Improve layout of custom property edit panel

This patch makes the layout of the custom property panel more coherent
with the rest of the property editor interface, makes it less busy,
allows more space for the buttons for the actual properties, and
simplifies editing values of unsupported property types or long arrays.

 - Remove the box around each property.
 - Use an non-embossed X icon for deleting.
 - Use an "edit" icon instead of the text for the meta-data edit operator.
   The "gear" icon used for editing isn't ideal here.
 - Increase the max array length for drawing the values directly to 8.
 - Add an "Edit Property Value" operator for dictionaries or longer arrays.
 - Replace the "Library Override" text with an icon.
 - Use a proper split factor, the same as the rest of the UI.

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

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

M	release/scripts/modules/rna_prop_ui.py
M	release/scripts/startup/bl_operators/wm.py

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

diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index 2cc806be10d..fce59a26c38 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -28,7 +28,7 @@ ARRAY_TYPES = (list, tuple, IDPropertyArray, Vector, bpy_prop_array)
 
 # Maximum length of an array property for which a multi-line
 # edit field will be displayed in the Custom Properties panel.
-MAX_DISPLAY_ROWS = 4
+MAX_DISPLAY_ROWS = 8
 
 
 def rna_idprop_quote_path(prop):
@@ -134,18 +134,7 @@ def rna_idprop_ui_create(
 
 
 def draw(layout, context, context_member, property_type, *, use_edit=True):
-
-    def assign_props(prop, value, key):
-        prop.data_path = context_member
-        prop.property_name = key
-
-        try:
-            prop.value = str(value)
-        except:
-            pass
-
     rna_item, context_member = rna_idprop_context_value(context, context_member, property_type)
-
     # poll should really get this...
     if not rna_item:
         return
@@ -164,17 +153,15 @@ def draw(layout, context, context_member, property_type, *, use_edit=True):
     # TODO: Allow/support adding new custom props to overrides.
     if use_edit and not is_lib_override:
         row = layout.row()
-        props = row.operator("wm.properties_add", text="Add")
+        props = row.operator("wm.properties_add", text="New", icon='ADD')
         props.data_path = context_member
         del row
+        layout.separator()
 
     show_developer_ui = context.preferences.view.show_developer_ui
     rna_properties = {prop.identifier for prop in rna_item.bl_rna.properties if prop.is_runtime} if items else None
 
-    layout.use_property_split = True
-    layout.use_property_decorate = False  # No animation.
-
-    flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True)
+    layout.use_property_decorate = False
 
     for key, value in items:
         is_rna = (key in rna_properties)
@@ -188,57 +175,50 @@ def draw(layout, context, context_member, property_type, *, use_edit=True):
 
         if to_dict:
             value = to_dict()
-            val_draw = str(value)
         elif to_list:
             value = to_list()
-            val_draw = str(value)
-        else:
-            val_draw = value
 
-        row = layout.row(align=True)
-        box = row.box()
+        split = layout.split(factor=0.4, align=True)
+        label_row = split.row()
+        label_row.alignment = 'RIGHT'
+        label_row.label(text=key, translate=False)
 
-        if use_edit:
-            split = box.split(factor=0.75)
-            row = split.row()
-        else:
-            split = box.split(factor=1.00)
-            row = split.row()
+        value_row = split.row(align=True)
+        value_column = value_row.column(align=True)
 
-        row.alignment = 'RIGHT'
+        is_long_array = to_list and len(value) >= MAX_DISPLAY_ROWS
 
-        row.label(text=key, translate=False)
+        if is_rna:
+            value_column.prop(rna_item, key, text="")
+        elif to_dict or is_long_array:
+            props = value_column.operator("wm.properties_edit_value", text="Edit Value")
+            props.data_path = context_member
+            props.property_name = key
+        else:
+            value_column.prop(rna_item, '["%s"]' % escape_identifier(key), text="")
 
-        # Explicit exception for arrays.
-        show_array_ui = to_list and not is_rna and 0 < len(value) <= MAX_DISPLAY_ROWS
+        operator_row = value_row.row()
 
-        if show_array_ui and isinstance(value[0], (int, float)):
-            row.prop(rna_item, '["%s"]' % escape_identifier(key), text="")
-        elif to_dict or to_list:
-            row.label(text=val_draw, translate=False)
-        else:
-            if is_rna:
-                row.prop(rna_item, key, text="")
-            else:
-                row.prop(rna_item, '["%s"]' % escape_identifier(key), text="")
+        # Do not allow editing of overridden properties (we cannot use a poll function
+        # of the operators here since they's have no access to the specific property).
+        operator_row.enabled = not(is_lib_override and key in rna_item.id_data.override_library.reference)
 
         if use_edit:
-            row = split.row(align=True)
-            # Do not allow editing of overridden properties (we cannot use a poll function
-            # of the operators here since they's have no access to the specific property).
-            row.enabled = not(is_lib_override and key in rna_item.id_data.override_library.reference)
             if is_rna:
-                row.label(text="API Defined")
+                operator_row.label(text="API Defined")
             elif is_lib_override:
-                row.label(text="Library Override")
+                operator_row.active = False
+                operator_row.label(text="", icon='DECORATE_LIBRARY_OVERRIDE')
             else:
-                props = row.operator("wm.properties_edit", text="Edit")
-                assign_props(props, val_draw, key)
-                props = row.operator("wm.properties_remove", text="", icon='REMOVE')
-                assign_props(props, val_draw, key)
-
-    del flow
-
+                props = operator_row.operator("wm.properties_edit", text="", icon='PREFERENCES', emboss=False)
+                props.data_path = context_member
+                props.property_name = key
+                props = operator_row.operator("wm.properties_remove", text="", icon='X', emboss=False)
+                props.data_path = context_member
+                props.property_name = key
+        else:
+            # Add some spacing, so the right side of the buttons line up with layouts with decorators.
+            operator_row.label(text="", icon='BLANK1')
 
 class PropertyPanel:
     """
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 170b9f3ae44..4dbdc6e633e 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -1442,7 +1442,7 @@ class WM_OT_properties_edit(Operator):
 
     # Convert an old property for a string, avoiding unhelpful string representations for custom list types.
     @staticmethod
-    def _convert_old_property_to_string(item, name):
+    def convert_custom_property_to_string(item, name):
         # The IDProperty group view API currently doesn't have a "lookup" method.
         for key, value in item.items():
             if key == name:
@@ -1461,7 +1461,8 @@ class WM_OT_properties_edit(Operator):
 
     # Retrieve the current type of the custom property on the RNA struct. Some properties like group properties
     # can be created in the UI, but editing their meta-data isn't supported. In that case, return 'PYTHON'.
-    def _get_property_type(self, item, property_name):
+    @staticmethod
+    def get_property_type(item, property_name):
         from rna_prop_ui import (
             rna_idprop_value_item_type,
         )
@@ -1549,17 +1550,17 @@ class WM_OT_properties_edit(Operator):
             return self._convert_new_value_single(item[name_old], float)
 
         if prop_type_new == 'INT_ARRAY':
-            prop_type_old = self._get_property_type(item, name_old)
+            prop_type_old = self.get_property_type(item, name_old)
             if prop_type_old in {'INT', 'FLOAT', 'INT_ARRAY', 'FLOAT_ARRAY'}:
                 return self._convert_new_value_array(item[name_old], int, self.array_length)
 
         if prop_type_new == 'FLOAT_ARRAY':
-            prop_type_old = self._get_property_type(item, name_old)
+            prop_type_old = self.get_property_type(item, name_old)
             if prop_type_old in {'INT', 'FLOAT', 'FLOAT_ARRAY', 'INT_ARRAY'}:
                 return self._convert_new_value_array(item[name_old], float, self.array_length)
 
         if prop_type_new == 'STRING':
-            return self._convert_old_property_to_string(item, name_old)
+            return self.convert_custom_property_to_string(item, name_old)
 
         # If all else fails, create an empty string property. That should avoid errors later on anyway.
         return ""
@@ -1672,7 +1673,7 @@ class WM_OT_properties_edit(Operator):
             self.report({'ERROR'}, "Cannot edit properties from override data")
             return {'CANCELLED'}
 
-        prop_type_old = self._get_property_type(item, name_old)
+        prop_type_old = self.get_property_type(item, name_old)
         prop_type_new = self.property_type
         self._old_prop_name[:] = [name]
 
@@ -1716,14 +1717,14 @@ class WM_OT_properties_edit(Operator):
             return {'CANCELLED'}
 
         # Set operator's property type with the type of the existing property, to display the right settings.
-        old_type = self._get_property_type(item, name)
+        old_type = self.get_property_type(item, name)
         self.property_type = old_type
         self.last_property_type = old_type
 
         # So that the operator can do something for unsupported properties, change the property into
         # a string, just for editing in the dialog. When the operator executes, it will be converted back
         # into a python value. Always do this conversion, in case the Python property edit type is selected.
-        self.eval_string = self._convert_old_property_to_string(item, name)
+        self.eval_string = self.convert_custom_property_to_string(item, name)
 
         if old_type != 'PYTHON':
             self._fill_old_ui_data(item, name)
@@ -1845,6 +1846,62 @@ class WM_OT_properties_edit(Operator):
             layout.prop(self, "description")
 
 
+# Edit the value of a custom property with the given name on the RNA struct at the given data path.
+# For supported types, this simply acts as a convenient way to create a popup for a specific property
+# and draws the custom property value directly in the popup. For types like groups which can't be edited
+# directly with buttons, instead convert the value to a string, evaluate the changed string when executing.
+class WM_OT_properties_edit_value(Operator):
+    """Edit the value of a custom property"""
+    bl_idname = "wm.properties_edit_value"

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list