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:
Diffstat (limited to 'release/scripts/startup/bl_operators/wm.py')
-rw-r--r--release/scripts/startup/bl_operators/wm.py190
1 files changed, 157 insertions, 33 deletions
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 2f97942faa4..35826cea860 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -95,6 +95,76 @@ def context_path_validate(context, data_path):
return value
+def context_path_to_rna_property(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:
+ return rna_prop
+ return None
+
+
+def context_path_decompose(data_path):
+ # Decompose a data_path into 3 components:
+ # base_path, prop_attr, prop_item, where:
+ # `"foo.bar["baz"].fiz().bob.buz[10][2]"`, returns...
+ # `("foo.bar["baz"].fiz().bob", "buz", "[10][2]")`
+ #
+ # This is useful as we often want the base and the property, ignoring any item access.
+ # Note that item access includes function calls since these aren't properties.
+ #
+ # Note that the `.` is removed from the start of the first and second values,
+ # this is done because `.attr` isn't convenient to use as an argument,
+ # also the convention is not to include this within the data paths or the operator logic for `bpy.ops.wm.*`.
+ from bl_rna_utils.data_path import decompose_data_path
+ path_split = decompose_data_path("." + data_path)
+
+ # Find the last property that isn't a function call.
+ value_prev = ""
+ i = len(path_split)
+ while (i := i - 1) >= 0:
+ value = path_split[i]
+ if value.startswith("."):
+ if not value_prev.startswith("("):
+ break
+ value_prev = value
+
+ if i != -1:
+ base_path = "".join(path_split[:i])
+ prop_attr = path_split[i]
+ prop_item = "".join(path_split[i + 1:])
+
+ if base_path:
+ assert(base_path.startswith("."))
+ base_path= base_path[1:]
+ if prop_attr:
+ assert(prop_attr.startswith("."))
+ prop_attr = prop_attr[1:]
+ else:
+ # If there are no properties, everything is an item.
+ # Note that should not happen in practice with values which are added onto `context`,
+ # include since it's correct to account for this case and not doing so will create a confusing exception.
+ base_path = ""
+ prop_attr = ""
+ prop_item = "".join(path_split)
+
+ return (base_path, prop_attr, prop_item)
+
+
+def description_from_data_path(base, data_path, *, prefix, value=Ellipsis):
+ if context_path_validate(base, data_path) is Ellipsis:
+ return None
+
+ if (
+ (rna_prop := context_path_to_rna_property(base, data_path)) and
+ (description := rna_prop.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
@@ -120,12 +190,9 @@ def operator_value_is_undo(value):
def operator_path_is_undo(context, data_path):
- # note that if we have data paths that use strings this could fail
- # luckily we don't do this!
- #
- # When we can't find the data owner assume no undo is needed.
- data_path_head = data_path.rpartition(".")[0]
+ data_path_head, _, _ = context_path_decompose(data_path)
+ # When we can't find the data owner assume no undo is needed.
if not data_path_head:
return False
@@ -168,6 +235,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 +256,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 +276,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 +314,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 +357,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 +377,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 +397,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 +417,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 +438,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 +481,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 +517,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 +557,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)
@@ -450,22 +569,11 @@ class WM_OT_context_cycle_enum(Operator):
orig_value = value
- # Have to get rna enum values
- rna_struct_str, rna_prop_str = data_path.rsplit('.', 1)
- i = rna_prop_str.find('[')
-
- # just in case we get "context.foo.bar[0]"
- if i != -1:
- rna_prop_str = rna_prop_str[0:i]
-
- rna_struct = eval("context.%s.rna_type" % rna_struct_str)
-
- rna_prop = rna_struct.properties[rna_prop_str]
-
+ rna_prop = context_path_to_rna_property(context, data_path)
if type(rna_prop) != bpy.types.EnumProperty:
raise Exception("expected an enum property")
- enums = rna_struct.properties[rna_prop_str].enum_items.keys()
+ enums = rna_prop.enum_items.keys()
orig_index = enums.index(orig_value)
# Have the info we need, advance to the next item.
@@ -498,6 +606,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 +635,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)
@@ -530,15 +646,15 @@ class WM_OT_context_menu_enum(Operator):
if value is Ellipsis:
return {'PASS_THROUGH'}
- base_path, prop_string = data_path.rsplit(".", 1)
+ base_path, prop_attr, _ = context_path_decompose(data_path)
value_base = context_path_validate(context, base_path)
- prop = value_base.bl_rna.properties[prop_string]
+ rna_prop = context_path_to_rna_property(context, data_path)
def draw_cb(self, context):
layout = self.layout
- layout.prop(value_base, prop_string, expand=True)
+ layout.prop(value_base, prop_attr, expand=True)
- context.window_manager.popup_menu(draw_func=draw_cb, title=prop.name, icon=prop.icon)
+ context.window_manager.popup_menu(draw_func=draw_cb, title=rna_prop.name, icon=rna_prop.icon)
return {'FINISHED'}
@@ -550,6 +666,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
@@ -558,15 +678,15 @@ class WM_OT_context_pie_enum(Operator):
if value is Ellipsis:
return {'PASS_THROUGH'}
- base_path, prop_string = data_path.rsplit(".", 1)
+ base_path, prop_attr, _ = context_path_decompose(data_path)
value_base = context_path_validate(context, base_path)
- prop = value_base.bl_rna.properties[prop_string]
+ rna_prop = context_path_to_rna_property(context, data_path)
def draw_cb(self, context):
layout = self.layout
- layout.prop(value_base, prop_string, expand=True)
+ layout.prop(value_base, prop_attr, expand=True)
- wm.popup_menu_pie(draw_func=draw_cb, title=prop.name, icon=prop.icon, event=event)
+ wm.popup_menu_pie(draw_func=draw_cb, title=rna_prop.name, icon=rna_prop.icon, event=event)
return {'FINISHED'}
@@ -587,11 +707,15 @@ 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, context, event):
wm = context.window_manager
data_path = self.data_path
- prop_string = self.prop_string
+ prop_attr = self.prop_string
# same as eval("bpy.ops." + data_path)
op_mod_str, ob_id_str = data_path.split(".", 1)
@@ -607,7 +731,7 @@ class WM_OT_operator_pie_enum(Operator):
def draw_cb(self, context):
layout = self.layout
pie = layout.menu_pie()
- pie.operator_enum(data_path, prop_string)
+ pie.operator_enum(data_path, prop_attr)
wm.popup_menu_pie(draw_func=draw_cb, title=op_rna.name, event=event)
@@ -631,17 +755,17 @@ class WM_OT_context_set_id(Operator):
value = self.value
data_path = self.data_path
- # match the pointer type from the target property to bpy.data.*
+ # Match the pointer type from the target property to `bpy.data.*`
# so we lookup the correct list.
- data_path_base, data_path_prop = data_path.rsplit(".", 1)
- data_prop_rna = eval("context.%s" % data_path_base).rna_type.properties[data_path_prop]
- data_prop_rna_type = data_prop_rna.fixed_type
+
+ rna_prop = context_path_to_rna_property(context, data_path)
+ rna_prop_fixed_type = rna_prop.fixed_type
id_iter = None
for prop in bpy.data.rna_type.properties:
if prop.rna_type.identifier == "CollectionProperty":
- if prop.fixed_type == data_prop_rna_type:
+ if prop.fixed_type == rna_prop_fixed_type:
id_iter = prop.identifier
break