diff options
author | Joseph Eagar <joeedh@gmail.com> | 2021-09-02 10:02:20 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2021-09-02 10:02:20 +0300 |
commit | 2b209317073359e4b03cf069a788ee5b5eff8a7a (patch) | |
tree | 68748a22f0fda5920ad0da4bee8d3e3e0b6239b5 /release/scripts | |
parent | 416686707f4e9f33bd537420510871aa6fe1b5df (diff) | |
parent | 0ccbf5069431aaa323ca9c7f09cb62a0ea35ae86 (diff) |
Merge branch 'master' into temp_bmesh_multires
Diffstat (limited to 'release/scripts')
19 files changed, 342 insertions, 360 deletions
diff --git a/release/scripts/modules/bl_keymap_utils/io.py b/release/scripts/modules/bl_keymap_utils/io.py index 7adcd799c0f..96832cbd9c7 100644 --- a/release/scripts/modules/bl_keymap_utils/io.py +++ b/release/scripts/modules/bl_keymap_utils/io.py @@ -22,6 +22,7 @@ # Export Functions __all__ = ( + "_init_properties_from_data", # Shared with gizmo default property initialization. "keyconfig_export_as_data", "keyconfig_import_from_data", "keyconfig_init_from_data", @@ -244,20 +245,24 @@ def keyconfig_export_as_data(wm, kc, filepath, *, all_keymaps=False): # ----------------------------------------------------------------------------- # Import Functions - -def _kmi_props_setattr(kmi_props, attr, value): - if type(value) is list: - kmi_subprop = getattr(kmi_props, attr) - for subattr, subvalue in value: - _kmi_props_setattr(kmi_subprop, subattr, subvalue) - return - - try: - setattr(kmi_props, attr, value) - except AttributeError: - print(f"Warning: property '{attr}' not found in keymap item '{kmi_props.__class__.__name__}'") - except Exception as ex: - print(f"Warning: {ex!r}") +# +# NOTE: unlike export, this runs on startup. +# Take care making changes that could impact performance. + +def _init_properties_from_data(base_props, base_value): + assert(type(base_value) is list) + for attr, value in base_value: + if type(value) is list: + base_props.property_unset(attr) + props = getattr(base_props, attr) + _init_properties_from_data(props, value) + else: + try: + setattr(base_props, attr, value) + except AttributeError: + print(f"Warning: property '{attr}' not found in item '{base_props.__class__.__name__}'") + except Exception as ex: + print(f"Warning: {ex!r}") def keymap_init_from_data(km, km_items, is_modal=False): @@ -271,8 +276,7 @@ def keymap_init_from_data(km, km_items, is_modal=False): if kmi_props_data is not None: kmi_props = kmi.properties assert type(kmi_props_data) is list - for attr, value in kmi_props_data: - _kmi_props_setattr(kmi_props, attr, value) + _init_properties_from_data(kmi_props, kmi_props_data) def keyconfig_init_from_data(kc, keyconfig_data): diff --git a/release/scripts/modules/bpy/utils/__init__.py b/release/scripts/modules/bpy/utils/__init__.py index 1fe73f50639..afa04a18ef6 100644 --- a/release/scripts/modules/bpy/utils/__init__.py +++ b/release/scripts/modules/bpy/utils/__init__.py @@ -859,6 +859,7 @@ def register_tool(tool_cls, *, after=None, separator=False, group=False): "icon": getattr(tool_cls, "bl_icon", None), "cursor": getattr(tool_cls, "bl_cursor", None), "widget": getattr(tool_cls, "bl_widget", None), + "widget_properties": getattr(tool_cls, "bl_widget_properties", None), "keymap": getattr(tool_cls, "bl_keymap", None), "data_block": getattr(tool_cls, "bl_data_block", None), "operator": getattr(tool_cls, "bl_operator", None), diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py index bafa2b28bbf..26a2f9ad89b 100644 --- a/release/scripts/modules/rna_prop_ui.py +++ b/release/scripts/modules/rna_prop_ui.py @@ -30,24 +30,6 @@ ARRAY_TYPES = (list, tuple, IDPropertyArray, Vector) MAX_DISPLAY_ROWS = 4 -def rna_idprop_ui_get(item, *, create=True): - try: - return item['_RNA_UI'] - except: - if create: - item['_RNA_UI'] = {} - return item['_RNA_UI'] - else: - return None - - -def rna_idprop_ui_del(item): - try: - del item['_RNA_UI'] - except KeyError: - pass - - def rna_idprop_quote_path(prop): return "[\"%s\"]" % bpy.utils.escape_identifier(prop) @@ -59,32 +41,9 @@ def rna_idprop_ui_prop_update(item, prop): prop_rna.update() -def rna_idprop_ui_prop_get(item, prop, *, create=True): - - rna_ui = rna_idprop_ui_get(item, create=create) - - if rna_ui is None: - return None - - try: - return rna_ui[prop] - except: - rna_ui[prop] = {} - return rna_ui[prop] - - -def rna_idprop_ui_prop_clear(item, prop, *, remove=True): - rna_ui = rna_idprop_ui_get(item, create=False) - - if rna_ui is None: - return - - try: - del rna_ui[prop] - except KeyError: - pass - if remove and len(item.keys()) == 1: - rna_idprop_ui_del(item) +def rna_idprop_ui_prop_clear(item, prop): + ui_data = item.id_properties_ui(prop) + ui_data.clear() def rna_idprop_context_value(context, context_member, property_type): @@ -106,8 +65,7 @@ def rna_idprop_context_value(context, context_member, property_type): def rna_idprop_has_properties(rna_item): keys = rna_item.keys() - nbr_props = len(keys) - return (nbr_props > 1) or (nbr_props and '_RNA_UI' not in keys) + return bool(keys) def rna_idprop_value_to_python(value): @@ -126,31 +84,8 @@ def rna_idprop_value_item_type(value): def rna_idprop_ui_prop_default_set(item, prop, value): - defvalue = None - try: - prop_type, is_array = rna_idprop_value_item_type(item[prop]) - - if prop_type in {int, float, str}: - if is_array and isinstance(value, ARRAY_TYPES): - value = [prop_type(item) for item in value] - if any(value): - defvalue = value - else: - defvalue = prop_type(value) - except KeyError: - pass - except ValueError: - pass - - if defvalue: - rna_ui = rna_idprop_ui_prop_get(item, prop, create=True) - rna_ui["default"] = defvalue - else: - rna_ui = rna_idprop_ui_prop_get(item, prop) - if rna_ui: - rna_ui.pop("default", None) - - return defvalue + ui_data = item.id_properties_ui(prop) + ui_data.update(default=value) def rna_idprop_ui_create( @@ -163,7 +98,7 @@ def rna_idprop_ui_create( ): """Create and initialize a custom property with limits, defaults and other settings.""" - proptype, is_array = rna_idprop_value_item_type(default) + proptype, _ = rna_idprop_value_item_type(default) # Sanitize limits if proptype is bool: @@ -180,35 +115,22 @@ def rna_idprop_ui_create( rna_idprop_ui_prop_update(item, prop) - # Clear the UI settings - rna_ui_group = rna_idprop_ui_get(item, create=True) - rna_ui_group[prop] = {} - rna_ui = rna_ui_group[prop] - - # Assign limits and default - if proptype in {int, float, bool}: - # The type must be exactly the same - rna_ui["min"] = proptype(min) - rna_ui["soft_min"] = proptype(soft_min) - rna_ui["max"] = proptype(max) - rna_ui["soft_max"] = proptype(soft_max) - - if default and (not is_array or any(default)): - rna_ui["default"] = default - - if is_array and subtype and subtype != 'NONE': - rna_ui["subtype"] = subtype - - # Assign other settings - if description is not None: - rna_ui["description"] = description + # Update the UI settings. + ui_data = item.id_properties_ui(prop) + ui_data.update( + subtype=subtype, + min=min, + max=max, + soft_min=soft_min, + soft_max=soft_max, + description=description, + default=default, + ) prop_path = rna_idprop_quote_path(prop) item.property_overridable_library_set(prop_path, overridable) - return rna_ui - def draw(layout, context, context_member, property_type, *, use_edit=True): @@ -254,10 +176,6 @@ def draw(layout, context, context_member, property_type, *, use_edit=True): flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) for key, val in items: - - if key == '_RNA_UI': - continue - is_rna = (key in rna_properties) # only show API defined for developers diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index d9538930f33..6a9306c2eab 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -796,11 +796,11 @@ def km_outliner(params): ("outliner.item_rename", {"type": 'F2', "value": 'PRESS'}, {"properties": [("use_active", True)]}), ("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK'}, - {"properties": [("extend", False), ("deselect_all", not params.legacy)]}), + {"properties": [("deselect_all", not params.legacy)]}), ("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True}, {"properties": [("extend", True), ("deselect_all", not params.legacy)]}), ("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK', "shift": True}, - {"properties": [("extend", False), ("extend_range", True), ("deselect_all", not params.legacy)]}), + {"properties": [("extend_range", True), ("deselect_all", not params.legacy)]}), ("outliner.item_activate", {"type": 'LEFTMOUSE', "value": 'CLICK', "ctrl": True, "shift": True}, {"properties": [("extend", True), ("extend_range", True), ("deselect_all", not params.legacy)]}), ("outliner.select_box", {"type": 'B', "value": 'PRESS'}, None), @@ -884,15 +884,13 @@ def km_uv_editor(params): *_template_items_uv_select_mode(params), ("uv.mark_seam", {"type": 'E', "value": 'PRESS', "ctrl": True}, None), ("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value}, - {"properties": [("extend", False), ("deselect_all", not params.legacy)]}), + {"properties": [("deselect_all", not params.legacy)]}), ("uv.select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True}, {"properties": [("extend", True)]}), - ("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, - {"properties": [("extend", False)]}), + ("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, None), ("uv.select_loop", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "alt": True}, {"properties": [("extend", True)]}), - ("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, - {"properties": [("extend", False)]}), + ("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, None), ("uv.select_edge_ring", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "shift": True, "alt": True}, {"properties": [("extend", True)]}), ("uv.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True}, @@ -913,7 +911,7 @@ def km_uv_editor(params): ("uv.select_linked_pick", {"type": 'L', "value": 'PRESS'}, {"properties": [("extend", True), ("deselect", False)]}), ("uv.select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True}, - {"properties": [("extend", False), ("deselect", True)]}), + {"properties": [("deselect", True)]}), ("uv.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("uv.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), *_template_items_select_actions(params, "uv.select_all"), @@ -957,8 +955,7 @@ def km_uv_editor(params): # Fallback for MMB emulation if params.use_mouse_emulate_3_button and params.select_mouse == 'LEFTMOUSE': items.extend([ - ("uv.select_loop", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'}, - {"properties": [("extend", False)]}), + ("uv.select_loop", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'}, None), ("uv.select_loop", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "alt": True}, {"properties": [("extend", True)]}), ]) @@ -1354,9 +1351,7 @@ def km_mask_editing(params): # click select keymap it's fine to have the context menu instead. items.extend([ ("mask.select", {"type": 'RIGHTMOUSE', "value": 'PRESS'}, - {"properties": [ - ("extend", False), ("deselect", False), ("toggle", False), - ("deselect_all", not params.legacy)]}), + {"properties": [("deselect_all", not params.legacy)]}), ("transform.translate", {"type": 'EVT_TWEAK_R', "value": 'ANY'}, None), ]) @@ -1370,7 +1365,7 @@ def km_mask_editing(params): ("mask.delete", {"type": 'X', "value": 'PRESS'}, None), ("mask.delete", {"type": 'DEL', "value": 'PRESS'}, None), ("mask.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, - {"properties": [("extend", False), ("deselect", False), ("toggle", True)]}), + {"properties": [("toggle", True)]}), *_template_items_select_actions(params, "mask.select_all"), ("mask.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None), ("mask.select_linked_pick", {"type": 'L', "value": 'PRESS'}, @@ -1390,8 +1385,7 @@ def km_mask_editing(params): {"properties": [("unselected", False)]}), ("mask.hide_view_set", {"type": 'H', "value": 'PRESS', "shift": True}, {"properties": [("unselected", True)]}), - ("clip.select", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True}, - {"properties": [("extend", False)]}), + ("clip.select", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True}, None), ("mask.cyclic_toggle", {"type": 'C', "value": 'PRESS', "alt": True}, None), ("mask.slide_point", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("mask.slide_spline_curvature", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), @@ -1446,7 +1440,7 @@ def km_markers(params): ("marker.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), ("marker.select", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True}, - {"properties": [("extend", False), ("camera", True)]}), + {"properties": [("camera", True)]}), ("marker.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "ctrl": True}, {"properties": [("extend", True), ("camera", True)]}), ("marker.select_box", {"type": params.select_tweak, "value": 'ANY'}, @@ -1531,29 +1525,27 @@ def km_graph_editor(params): ("wm.context_toggle", {"type": 'H', "value": 'PRESS', "ctrl": True}, {"properties": [("data_path", 'space_data.show_handles')]}), ("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [ - ("extend", False), ("deselect_all", not params.legacy), - ("column", False), ("curves", False)]}), + {"properties": [("deselect_all", not params.legacy)]}), ("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "alt": True}, - {"properties": [("extend", False), ("column", True), ("curves", False)]}), + {"properties": [("column", True)]}), ("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, - {"properties": [("extend", True), ("column", False), ("curves", False)]}), + {"properties": [("extend", True)]}), ("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "alt": True}, - {"properties": [("extend", True), ("column", True), ("curves", False)]}), + {"properties": [("extend", True), ("column", True)]}), ("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True, "alt": True}, - {"properties": [("extend", False), ("column", False), ("curves", True)]}), + {"properties": [("curves", True)]}), ("graph.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, - {"properties": [("extend", True), ("column", False), ("curves", True)]}), + {"properties": [("extend", True), ("curves", True)]}), ("graph.select_leftright", {"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True}, - {"properties": [("mode", 'CHECK'), ("extend", False)]}), + {"properties": [("mode", 'CHECK')]}), ("graph.select_leftright", {"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True, "shift": True}, {"properties": [("mode", 'CHECK'), ("extend", True)]}), ("graph.select_leftright", {"type": 'LEFT_BRACKET', "value": 'PRESS'}, - {"properties": [("mode", 'LEFT'), ("extend", False)]}), + {"properties": [("mode", 'LEFT')]}), ("graph.select_leftright", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, - {"properties": [("mode", 'RIGHT'), ("extend", False)]}), + {"properties": [("mode", 'RIGHT')]}), *_template_items_select_actions(params, "graph.select_all"), ("graph.select_box", {"type": 'B', "value": 'PRESS'}, None), ("graph.select_box", {"type": 'B', "value": 'PRESS', "alt": True}, @@ -1597,8 +1589,7 @@ def km_graph_editor(params): ("graph.delete", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("confirm", False)]}), ("graph.duplicate_move", {"type": 'D', "value": 'PRESS', "shift": True}, None), ("graph.keyframe_insert", {"type": 'I', "value": 'PRESS'}, None), - ("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, - {"properties": [("extend", False)]}), + ("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "ctrl": True}, None), ("graph.click_insert", {"type": params.action_mouse, "value": 'CLICK', "shift": True, "ctrl": True}, {"properties": [("extend", True)]}), ("graph.copy", {"type": 'C', "value": 'PRESS', "ctrl": True}, None), @@ -1804,13 +1795,10 @@ def km_node_editor(params): def node_select_ops(select_mouse): return [ ("node.select", {"type": select_mouse, "value": 'PRESS'}, - {"properties": [("extend", False), ("deselect_all", True)]}), - ("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True}, - {"properties": [("extend", False)]}), - ("node.select", {"type": select_mouse, "value": 'PRESS', "alt": True}, - {"properties": [("extend", False)]}), - ("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True, "alt": True}, - {"properties": [("extend", False)]}), + {"properties": [("deselect_all", True)]}), + ("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True}, None), + ("node.select", {"type": select_mouse, "value": 'PRESS', "alt": True}, None), + ("node.select", {"type": select_mouse, "value": 'PRESS', "ctrl": True, "alt": True}, None), ("node.select", {"type": select_mouse, "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), ("node.select", {"type": select_mouse, "value": 'PRESS', "shift": True, "ctrl": True}, @@ -1832,7 +1820,7 @@ def km_node_editor(params): items.extend(node_select_ops('RIGHTMOUSE')) items.extend([ ("node.select", {"type": 'LEFTMOUSE', "value": 'PRESS'}, - {"properties": [("extend", False), ("deselect_all", False)]}), + {"properties": [("deselect_all", False)]}), ("node.select", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), ]) @@ -1887,8 +1875,7 @@ def km_node_editor(params): *_template_items_select_actions(params, "node.select_all"), ("node.select_linked_to", {"type": 'L', "value": 'PRESS', "shift": True}, None), ("node.select_linked_from", {"type": 'L', "value": 'PRESS'}, None), - ("node.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, - {"properties": [("extend", False)]}), + ("node.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True}, None), ("node.select_grouped", {"type": 'G', "value": 'PRESS', "shift": True, "ctrl": True}, {"properties": [("extend", True)]}), ("node.select_same_type_step", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True}, @@ -1909,19 +1896,19 @@ def km_node_editor(params): ("node.clipboard_paste", {"type": 'V', "value": 'PRESS', "ctrl": True}, None), ("node.viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None), ("node.clear_viewer_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None), - ("node.translate_attach", {"type": 'G', "value": 'PRESS'}, None), - ("node.translate_attach", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, None), - ("node.translate_attach", {"type": params.select_tweak, "value": 'ANY'}, None), - ("transform.translate", {"type": 'G', "value": 'PRESS'}, None), + ("node.translate_attach", {"type": 'G', "value": 'PRESS'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}), + ("node.translate_attach", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}), + ("node.translate_attach", {"type": params.select_tweak, "value": 'ANY'}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}), + ("transform.translate", {"type": 'G', "value": 'PRESS'}, {"properties": [("view2d_edge_pan", True)]}), ("transform.translate", {"type": 'EVT_TWEAK_L', "value": 'ANY'}, - {"properties": [("release_confirm", True)]}), + {"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}), ("transform.translate", {"type": params.select_tweak, "value": 'ANY'}, - {"properties": [("release_confirm", True)]}), + {"properties": [("release_confirm", True), ("view2d_edge_pan", True)]}), ("transform.rotate", {"type": 'R', "value": 'PRESS'}, None), ("transform.resize", {"type": 'S', "value": 'PRESS'}, None), - ("node.move_detach_links", {"type": 'D', "value": 'PRESS', "alt": True}, None), - ("node.move_detach_links_release", {"type": params.action_tweak, "value": 'ANY', "alt": True}, None), - ("node.move_detach_links", {"type": params.select_tweak, "value": 'ANY', "alt": True}, None), + ("node.move_detach_links", {"type": 'D', "value": 'PRESS', "alt": True}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}), + ("node.move_detach_links_release", {"type": params.action_tweak, "value": 'ANY', "alt": True}, {"properties": [("NODE_OT_translate_attach", [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])])]}), + ("node.move_detach_links", {"type": params.select_tweak, "value": 'ANY', "alt": True}, {"properties": [("TRANSFORM_OT_translate", [("view2d_edge_pan", True)])]}), ("wm.context_toggle", {"type": 'TAB', "value": 'PRESS', "shift": True}, {"properties": [("data_path", 'tool_settings.use_snap')]}), ("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True}, @@ -2131,29 +2118,27 @@ def km_dopesheet(params): items.extend([ ("action.clickselect", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [ - ("extend", False), ("deselect_all", not params.legacy), - ("column", False), ("channel", False)]}), + {"properties": [("deselect_all", not params.legacy)]}), ("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "alt": True}, - {"properties": [("extend", False), ("column", True), ("channel", False)]}), + {"properties": [("column", True)]}), ("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, - {"properties": [("extend", True), ("column", False), ("channel", False)]}), + {"properties": [("extend", True)]}), ("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "alt": True}, - {"properties": [("extend", True), ("column", True), ("channel", False)]}), + {"properties": [("extend", True), ("column", True)]}), ("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "ctrl": True, "alt": True}, - {"properties": [("extend", False), ("column", False), ("channel", True)]}), + {"properties": [("channel", True)]}), ("action.clickselect", {"type": params.select_mouse, "value": 'PRESS', "shift": True, "ctrl": True, "alt": True}, - {"properties": [("extend", True), ("column", False), ("channel", True)]}), + {"properties": [("extend", True), ("channel", True)]}), ("action.select_leftright", {"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True}, - {"properties": [("mode", 'CHECK'), ("extend", False)]}), + {"properties": [("mode", 'CHECK')]}), ("action.select_leftright", {"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True, "shift": True}, {"properties": [("mode", 'CHECK'), ("extend", True)]}), ("action.select_leftright", {"type": 'LEFT_BRACKET', "value": 'PRESS'}, - {"properties": [("mode", 'LEFT'), ("extend", False)]}), + {"properties": [("mode", 'LEFT')]}), ("action.select_leftright", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, - {"properties": [("mode", 'RIGHT'), ("extend", False)]}), + {"properties": [("mode", 'RIGHT')]}), *_template_items_select_actions(params, "action.select_all"), ("action.select_box", {"type": 'B', "value": 'PRESS'}, {"properties": [("axis_range", False)]}), @@ -2264,8 +2249,7 @@ def km_nla_channels(params): ) items.extend([ - ("nla.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS'}, - {"properties": [("extend", False)]}), + ("nla.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("nla.channels_click", {"type": 'LEFTMOUSE', "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), ("nla.tracks_add", {"type": 'A', "value": 'PRESS', "shift": True}, @@ -2290,19 +2274,19 @@ def km_nla_editor(params): items.extend([ ("nla.click_select", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [("extend", False), ("deselect_all", not params.legacy)]}), + {"properties": [("deselect_all", not params.legacy)]}), ("nla.click_select", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), ("nla.select_leftright", {"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True}, - {"properties": [("mode", 'CHECK'), ("extend", False)]}), + {"properties": [("mode", 'CHECK')]}), ("nla.select_leftright", {"type": params.select_mouse, "value": 'PRESS' if params.legacy else 'CLICK', "ctrl": True, "shift": True}, {"properties": [("mode", 'CHECK'), ("extend", True)]}), ("nla.select_leftright", {"type": 'LEFT_BRACKET', "value": 'PRESS'}, - {"properties": [("mode", 'LEFT'), ("extend", False)]}), + {"properties": [("mode", 'LEFT')]}), ("nla.select_leftright", {"type": 'RIGHT_BRACKET', "value": 'PRESS'}, - {"properties": [("mode", 'RIGHT'), ("extend", False)]}), + {"properties": [("mode", 'RIGHT')]}), *_template_items_select_actions(params, "nla.select_all"), ("nla.select_box", {"type": 'B', "value": 'PRESS'}, {"properties": [("axis_range", False)]}), @@ -2498,7 +2482,7 @@ def km_text(params): {"properties": [("type", 'PREVIOUS_CHARACTER')]}), ("text.delete", {"type": 'DEL', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'NEXT_WORD')]}), - ("text.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True}, + ("text.delete", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True, "repeat": True}, {"properties": [("type", 'PREVIOUS_WORD')]}), ("text.overwrite_toggle", {"type": 'INSERT', "value": 'PRESS'}, None), ("text.scroll_bar", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), @@ -2638,8 +2622,7 @@ def km_sequencer(params): {"properties": [("side_of_frame", True), ("linked_time", True), ("extend", True)]}), ("sequencer.select_more", {"type": 'NUMPAD_PLUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), ("sequencer.select_less", {"type": 'NUMPAD_MINUS', "value": 'PRESS', "ctrl": True, "repeat": True}, None), - ("sequencer.select_linked_pick", {"type": 'L', "value": 'PRESS'}, - {"properties": [("extend", False)]}), + ("sequencer.select_linked_pick", {"type": 'L', "value": 'PRESS'}, None), ("sequencer.select_linked_pick", {"type": 'L', "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), ("sequencer.select_linked", {"type": 'L', "value": 'PRESS', "ctrl": True}, None), @@ -2862,7 +2845,7 @@ def km_clip_editor(params): {"properties": [("position", 'PATHSTART')]}), ("clip.change_frame", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), ("clip.select", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [("extend", False), ("deselect_all", not params.legacy)]}), + {"properties": [("deselect_all", not params.legacy)]}), ("clip.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), *_template_items_select_actions(params, "clip.select_all"), @@ -2948,8 +2931,7 @@ def km_clip_graph_editor(params): ) items.extend([ - ("clip.graph_select", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [("extend", False)]}), + ("clip.graph_select", {"type": params.select_mouse, "value": 'PRESS'}, None), ("clip.graph_select", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), *_template_items_select_actions(params, "clip.graph_select_all_markers"), @@ -4241,8 +4223,7 @@ def km_paint_curve(params): items.extend([ ("paintcurve.add_point_slide", {"type": params.action_mouse, "value": 'PRESS', "ctrl": True}, None), - ("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [("extend", False)]}), + ("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS'}, None), ("paintcurve.select", {"type": params.select_mouse, "value": 'PRESS', "shift": True}, {"properties": [("extend", True)]}), ("paintcurve.slide", {"type": params.action_mouse, "value": 'PRESS'}, @@ -4664,15 +4645,13 @@ def km_mesh(params): # Selection modes. *_template_items_editmode_mesh_select_mode(params), # Loop Select with alt. Double click in case MMB emulation is on (below). - ("mesh.loop_select", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, - {"properties": [("extend", False), ("deselect", False), ("toggle", False)]}), + ("mesh.loop_select", {"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, None), ("mesh.loop_select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "alt": True}, - {"properties": [("extend", False), ("deselect", False), ("toggle", True)]}), + {"properties": [("toggle", True)]}), # Selection - ("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, - {"properties": [("extend", False), ("deselect", False), ("toggle", False)]}), + ("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True, "alt": True}, None), ("mesh.edgering_select", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "ctrl": True, "alt": True}, - {"properties": [("extend", False), ("deselect", False), ("toggle", True)]}), + {"properties": [("toggle", True)]}), ("mesh.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "ctrl": True}, {"properties": [("use_fill", False)]}), ("mesh.shortest_path_pick", {"type": params.select_mouse, "value": params.select_mouse_value, "shift": True, "ctrl": True}, @@ -4754,16 +4733,14 @@ def km_mesh(params): if params.use_mouse_emulate_3_button and params.select_mouse == 'LEFTMOUSE': items.extend([ - ("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'}, - {"properties": [("extend", False), ("deselect", False), ("toggle", False)]}), + ("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK'}, None), ("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "shift": True}, - {"properties": [("extend", True), ("deselect", False), ("toggle", False)]}), + {"properties": [("extend", True)]}), ("mesh.loop_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "alt": True}, - {"properties": [("extend", False), ("deselect", True), ("toggle", False)]}), - ("mesh.edgering_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "ctrl": True}, - {"properties": [("extend", False), ("deselect", False), ("toggle", False)]}), + {"properties": [("deselect", True)]}), + ("mesh.edgering_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "ctrl": True}, None), ("mesh.edgering_select", {"type": params.select_mouse, "value": 'DOUBLE_CLICK', "shift": True, "ctrl": True}, - {"properties": [("extend", False), ("deselect", False), ("toggle", True)]}), + {"properties": [("toggle", True)]}), ]) if params.legacy: @@ -5953,7 +5930,7 @@ def km_node_editor_tool_select(params): {"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'}, {"items": [ ("node.select", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [("extend", False), ("deselect_all", not params.legacy)]}), + {"properties": [("deselect_all", not params.legacy)]}), ]}, ) @@ -7021,7 +6998,7 @@ def km_sequencer_editor_tool_select(params): {"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'}, {"items": [ ("sequencer.select", {"type": params.select_mouse, "value": 'PRESS'}, - {"properties": [("extend", False), ("deselect_all", not params.legacy)]}), + {"properties": [("deselect_all", not params.legacy)]}), *_template_items_change_frame(params), ]}, ) diff --git a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py index 247a1ec342e..05ecac4d70c 100644 --- a/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py +++ b/release/scripts/startup/bl_app_templates_system/Video_Editing/__init__.py @@ -29,9 +29,28 @@ def update_factory_startup_screens(): params.use_filter_folder = True +def update_factory_startup_ffmpeg_preset(): + preset = "H264_in_MP4" + preset_filepath = bpy.utils.preset_find(preset, preset_path="ffmpeg") + if not preset_filepath: + print("Preset %r not found" % preset) + + for scene in bpy.data.scenes: + render = scene.render + render.image_settings.file_format = 'FFMPEG' + + if preset_filepath: + bpy.ops.script.python_file_run({"scene": scene}, filepath=preset_filepath) + + render.ffmpeg.audio_codec = 'AAC' + render.ffmpeg.audio_bitrate = 256 + + @persistent def load_handler(_): update_factory_startup_screens() + if bpy.app.build_options.codec_ffmpeg: + update_factory_startup_ffmpeg_preset() def register(): diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index d61bed71cab..df37db40102 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -970,7 +970,7 @@ class OBJECT_OT_assign_property_defaults(Operator): def assign_defaults(obj): from rna_prop_ui import rna_idprop_ui_prop_default_set - rna_properties = {'_RNA_UI'} | {prop.identifier for prop in obj.bl_rna.properties if prop.is_runtime} + rna_properties = {prop.identifier for prop in obj.bl_rna.properties if prop.is_runtime} for prop, value in obj.items(): if prop not in rna_properties: diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py index 8f678896e61..26f1c12d2b8 100644 --- a/release/scripts/startup/bl_operators/sequencer.py +++ b/release/scripts/startup/bl_operators/sequencer.py @@ -37,20 +37,19 @@ class SequencerCrossfadeSounds(Operator): @classmethod def poll(cls, context): - if context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip: - return context.scene.sequence_editor.active_strip.type == 'SOUND' - else: - return False + strip = context.active_sequence_strip + return strip and (strip.type == 'SOUND') def execute(self, context): + scene = context.scene seq1 = None seq2 = None - for s in context.scene.sequence_editor.sequences: - if s.select and s.type == 'SOUND': + for strip in scene.sequence_editor.sequences: + if strip.select and strip.type == 'SOUND': if seq1 is None: - seq1 = s + seq1 = strip elif seq2 is None: - seq2 = s + seq2 = strip else: seq2 = None break @@ -58,21 +57,19 @@ class SequencerCrossfadeSounds(Operator): self.report({'ERROR'}, "Select 2 sound strips") return {'CANCELLED'} if seq1.frame_final_start > seq2.frame_final_start: - s = seq1 - seq1 = seq2 - seq2 = s + seq1, seq2 = seq2, seq1 if seq1.frame_final_end > seq2.frame_final_start: - tempcfra = context.scene.frame_current - context.scene.frame_current = seq2.frame_final_start + tempcfra = scene.frame_current + scene.frame_current = seq2.frame_final_start seq1.keyframe_insert("volume") - context.scene.frame_current = seq1.frame_final_end + scene.frame_current = seq1.frame_final_end seq1.volume = 0 seq1.keyframe_insert("volume") seq2.keyframe_insert("volume") - context.scene.frame_current = seq2.frame_final_start + scene.frame_current = seq2.frame_final_start seq2.volume = 0 seq2.keyframe_insert("volume") - context.scene.frame_current = tempcfra + scene.frame_current = tempcfra return {'FINISHED'} else: self.report({'ERROR'}, "The selected strips don't overlap") @@ -95,28 +92,27 @@ class SequencerSplitMulticam(Operator): @classmethod def poll(cls, context): - if context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip: - return context.scene.sequence_editor.active_strip.type == 'MULTICAM' - else: - return False + strip = context.active_sequence_strip + return strip and (strip.type == 'MULTICAM') def execute(self, context): + scene = context.scene camera = self.camera - s = context.scene.sequence_editor.active_strip + strip = context.active_sequence_strip - if s.multicam_source == camera or camera >= s.channel: + if strip.multicam_source == camera or camera >= strip.channel: return {'FINISHED'} - cfra = context.scene.frame_current - right_strip = s.split(frame=cfra, split_method='SOFT') + cfra = scene.frame_current + right_strip = strip.split(frame=cfra, split_method='SOFT') if right_strip: - s.select = False + strip.select = False right_strip.select = True - context.scene.sequence_editor.active_strip = right_strip + scene.sequence_editor.active_strip = right_strip - context.scene.sequence_editor.active_strip.multicam_source = camera + context.active_sequence_strip.multicam_source = camera return {'FINISHED'} @@ -129,12 +125,13 @@ class SequencerDeinterlaceSelectedMovies(Operator): @classmethod def poll(cls, context): - return (context.scene and context.scene.sequence_editor) + scene = context.scene + return (scene and scene.sequence_editor) def execute(self, context): - for s in context.scene.sequence_editor.sequences_all: - if s.select and s.type == 'MOVIE': - s.use_deinterlace = True + for strip in context.scene.sequence_editor.sequences_all: + if strip.select and strip.type == 'MOVIE': + strip.use_deinterlace = True return {'FINISHED'} @@ -147,10 +144,12 @@ class SequencerFadesClear(Operator): @classmethod def poll(cls, context): - return context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip + strip = context.active_sequence_strip + return strip is not None def execute(self, context): - animation_data = context.scene.animation_data + scene = context.scene + animation_data = scene.animation_data if animation_data is None: return {'CANCELLED'} action = animation_data.action @@ -202,7 +201,8 @@ class SequencerFadesAdd(Operator): @classmethod def poll(cls, context): # Can't use context.selected_sequences as it can have an impact on performances - return context.scene and context.scene.sequence_editor and context.scene.sequence_editor.active_strip + strip = context.active_sequence_strip + return strip is not None def execute(self, context): from math import floor @@ -218,11 +218,11 @@ class SequencerFadesAdd(Operator): sequences = context.selected_sequences if self.type in {'CURSOR_TO', 'CURSOR_FROM'}: sequences = [ - s for s in sequences - if s.frame_final_start < context.scene.frame_current < s.frame_final_end + strip for strip in sequences + if strip.frame_final_start < scene.frame_current < strip.frame_final_end ] - max_duration = min(sequences, key=lambda s: s.frame_final_duration).frame_final_duration + max_duration = min(sequences, key=lambda strip: strip.frame_final_duration).frame_final_duration max_duration = floor(max_duration / 2.0) if self.type == 'IN_OUT' else max_duration faded_sequences = [] @@ -245,14 +245,15 @@ class SequencerFadesAdd(Operator): return {'FINISHED'} def calculate_fade_duration(self, context, sequence): - frame_current = context.scene.frame_current + scene = context.scene + frame_current = scene.frame_current duration = 0.0 if self.type == 'CURSOR_TO': duration = abs(frame_current - sequence.frame_final_start) elif self.type == 'CURSOR_FROM': duration = abs(sequence.frame_final_end - frame_current) else: - duration = calculate_duration_frames(context, self.duration_seconds) + duration = calculate_duration_frames(scene, self.duration_seconds) return max(1, duration) def is_long_enough(self, sequence, duration=0.0): @@ -278,8 +279,9 @@ class SequencerFadesAdd(Operator): that corresponds to the sequence. Returns the matching FCurve or creates a new one if the function can't find a match. """ + scene = context.scene fade_fcurve = None - fcurves = context.scene.animation_data.action.fcurves + fcurves = scene.animation_data.action.fcurves searched_data_path = sequence.path_from_id(animated_property) for fcurve in fcurves: if fcurve.data_path == searched_data_path: @@ -372,8 +374,8 @@ class Fade: return "Fade %r: %r to %r" % (self.type, self.start, self.end) -def calculate_duration_frames(context, duration_seconds): - return round(duration_seconds * context.scene.render.fps / context.scene.render.fps_base) +def calculate_duration_frames(scene, duration_seconds): + return round(duration_seconds * scene.render.fps / scene.render.fps_base) classes = ( diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index 6a3830ad1e4..6af86e75b8a 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1367,31 +1367,32 @@ class WM_OT_properties_edit(Operator): } def get_value_eval(self): + failed = False try: value_eval = eval(self.value) # assert else None -> None, not "None", see T33431. assert(type(value_eval) in {str, float, int, bool, tuple, list}) except: + failed = True value_eval = self.value - return value_eval + return value_eval, failed def get_default_eval(self): + failed = False try: default_eval = eval(self.default) # assert else None -> None, not "None", see T33431. assert(type(default_eval) in {str, float, int, bool, tuple, list}) except: + failed = True default_eval = self.default - return default_eval + return default_eval, failed def execute(self, context): from rna_prop_ui import ( - rna_idprop_ui_prop_get, - rna_idprop_ui_prop_clear, rna_idprop_ui_prop_update, - rna_idprop_ui_prop_default_set, rna_idprop_value_item_type, ) @@ -1405,8 +1406,8 @@ class WM_OT_properties_edit(Operator): self.report({'ERROR'}, "Direct execution not supported") return {'CANCELLED'} - value_eval = self.get_value_eval() - default_eval = self.get_default_eval() + value_eval, value_failed = self.get_value_eval() + default_eval, default_failed = self.get_default_eval() # First remove item = eval("context.%s" % data_path) @@ -1417,7 +1418,7 @@ class WM_OT_properties_edit(Operator): prop_type_old = type(item[prop_old]) - rna_idprop_ui_prop_clear(item, prop_old) + # Deleting the property will also remove the UI data. del item[prop_old] # Reassign @@ -1431,27 +1432,43 @@ class WM_OT_properties_edit(Operator): prop_type_new = type(prop_value) prop_type, is_array = rna_idprop_value_item_type(prop_value) - prop_ui = rna_idprop_ui_prop_get(item, prop) - - if prop_type in {float, int}: - prop_ui["min"] = prop_type(self.min) - prop_ui["max"] = prop_type(self.max) - - if self.use_soft_limits: - prop_ui["soft_min"] = prop_type(self.soft_min) - prop_ui["soft_max"] = prop_type(self.soft_max) - else: - prop_ui["soft_min"] = prop_type(self.min) - prop_ui["soft_max"] = prop_type(self.max) - - if prop_type == float and is_array and self.subtype != 'NONE': - prop_ui["subtype"] = self.subtype - else: - prop_ui.pop("subtype", None) - - prop_ui["description"] = self.description - - rna_idprop_ui_prop_default_set(item, prop, default_eval) + if prop_type == int: + ui_data = item.id_properties_ui(prop) + if type(default_eval) == str: + self.report({'WARNING'}, "Could not evaluate number from default value") + default_eval = None + elif hasattr(default_eval, "__len__"): + default_eval = [int(round(value)) for value in default_eval] + ui_data.update( + min=int(round(self.min)), + max=int(round(self.max)), + soft_min=int(round(self.soft_min)), + soft_max=int(round(self.soft_max)), + default=default_eval, + subtype=self.subtype, + description=self.description + ) + elif prop_type == float: + ui_data = item.id_properties_ui(prop) + if type(default_eval) == str: + self.report({'WARNING'}, "Could not evaluate number from default value") + default_eval = None + ui_data.update( + min=self.min, + max=self.max, + soft_min=self.soft_min, + soft_max=self.soft_max, + default=default_eval, + subtype=self.subtype, + description=self.description + ) + elif prop_type == str and not is_array and not default_failed: # String arrays do not support UI data. + ui_data = item.id_properties_ui(prop) + ui_data.update( + default=self.default, + subtype=self.subtype, + description=self.description + ) # If we have changed the type of the property, update its potential anim curves! if prop_type_old != prop_type_new: @@ -1492,7 +1509,6 @@ class WM_OT_properties_edit(Operator): def invoke(self, context, _event): from rna_prop_ui import ( - rna_idprop_ui_prop_get, rna_idprop_value_to_python, rna_idprop_value_item_type ) @@ -1519,35 +1535,34 @@ class WM_OT_properties_edit(Operator): self.is_overridable_library = bool(is_overridable) # default default value - prop_type, is_array = rna_idprop_value_item_type(self.get_value_eval()) + value, value_failed = self.get_value_eval() + prop_type, is_array = rna_idprop_value_item_type(value) if prop_type in {int, float}: self.default = str(prop_type(0)) else: self.default = "" # setup defaults - prop_ui = rna_idprop_ui_prop_get(item, prop, create=False) - if prop_ui: - self.min = prop_ui.get("min", -1000000000) - self.max = prop_ui.get("max", 1000000000) - self.description = prop_ui.get("description", "") - - defval = prop_ui.get("default", None) - if defval is not None: - self.default = str(rna_idprop_value_to_python(defval)) - - self.soft_min = prop_ui.get("soft_min", self.min) - self.soft_max = prop_ui.get("soft_max", self.max) + if prop_type in {int, float}: + ui_data = item.id_properties_ui(prop) + rna_data = ui_data.as_dict() + self.subtype = rna_data["subtype"] + self.min = rna_data["min"] + self.max = rna_data["max"] + self.soft_min = rna_data["soft_min"] + self.soft_max = rna_data["soft_max"] self.use_soft_limits = ( self.min != self.soft_min or self.max != self.soft_max ) + self.default = str(rna_data["default"]) + if prop_type == str and not is_array and not value_failed: # String arrays do not support UI data. + ui_data = item.id_properties_ui(prop) + rna_data = ui_data.as_dict() + self.subtype = rna_data["subtype"] + self.default = str(rna_data["default"]) - subtype = prop_ui.get("subtype", None) - else: - subtype = None - - self._init_subtype(prop_type, is_array, subtype) + self._init_subtype(prop_type, is_array, self.subtype) # store for comparison self._cmp_props = self._cmp_props_get() @@ -1688,7 +1703,6 @@ class WM_OT_properties_remove(Operator): def execute(self, context): from rna_prop_ui import ( - rna_idprop_ui_prop_clear, rna_idprop_ui_prop_update, ) data_path = self.data_path @@ -1701,7 +1715,6 @@ class WM_OT_properties_remove(Operator): prop = self.property rna_idprop_ui_prop_update(item, prop) del item[prop] - rna_idprop_ui_prop_clear(item, prop) return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py index b273eee4e19..793c4a52350 100644 --- a/release/scripts/startup/bl_ui/properties_data_gpencil.py +++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py @@ -342,6 +342,11 @@ class DATA_PT_gpencil_vertex_groups(ObjectButtonsPanel, Panel): col.operator("object.vertex_group_add", icon='ADD', text="") col.operator("object.vertex_group_remove", icon='REMOVE', text="").all = False + if group: + col.separator() + col.operator("object.vertex_group_move", icon='TRIA_UP', text="").direction = 'UP' + col.operator("object.vertex_group_move", icon='TRIA_DOWN', text="").direction = 'DOWN' + if ob.vertex_groups: row = layout.row() diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index 8de6925c051..f87f5351d6d 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -454,7 +454,7 @@ class AnnotationDataPanel: tool_settings = context.tool_settings if gpd and gpl: - layout.prop(gpl, "opacity", text="Opacity", slider=True) + layout.prop(gpl, "annotation_opacity", text="Opacity", slider=True) layout.prop(gpl, "thickness") else: layout.prop(tool_settings, "annotation_thickness", text="Thickness") diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py index aea2b76e07b..ca018216a5a 100644 --- a/release/scripts/startup/bl_ui/space_filebrowser.py +++ b/release/scripts/startup/bl_ui/space_filebrowser.py @@ -655,7 +655,10 @@ class ASSETBROWSER_PT_navigation_bar(asset_utils.AssetBrowserPanel, Panel): @classmethod def poll(cls, context): - return context.preferences.experimental.use_extended_asset_browser + return ( + asset_utils.AssetBrowserPanel.poll(context) and + context.preferences.experimental.use_extended_asset_browser + ) def draw(self, context): layout = self.layout diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 20fb39e8c1f..30115618f3d 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -37,13 +37,6 @@ from bl_ui.space_toolsystem_common import ( from rna_prop_ui import PropertyPanel -def act_strip(context): - try: - return context.scene.sequence_editor.active_strip - except AttributeError: - return None - - def selected_sequences_len(context): selected_sequences = getattr(context, "selected_sequences", None) if selected_sequences is None: @@ -150,6 +143,9 @@ class SEQUENCER_HT_header(Header): if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: tool_settings = context.tool_settings + sequencer_tool_settings = tool_settings.sequencer_tool_settings + row = layout.row(align=True) + row.prop(sequencer_tool_settings, "overlap_mode", text="") row = layout.row(align=True) row.prop(tool_settings, "use_snap_sequencer", text="") sub = row.row(align=True) @@ -530,7 +526,7 @@ class SEQUENCER_MT_change(Menu): def draw(self, context): layout = self.layout - strip = act_strip(context) + strip = context.active_sequence_strip layout.operator_context = 'INVOKE_REGION_WIN' @@ -757,7 +753,7 @@ class SEQUENCER_MT_strip_input(Menu): def draw(self, context): layout = self.layout - strip = act_strip(context) + strip = context.active_sequence_strip layout.operator("sequencer.reload", text="Reload Strips") layout.operator("sequencer.reload", text="Reload Strips and Adjust Length").adjust_length = True @@ -836,7 +832,7 @@ class SEQUENCER_MT_strip(Menu): layout.operator("sequencer.duplicate_move") layout.operator("sequencer.delete", text="Delete") - strip = act_strip(context) + strip = context.active_sequence_strip if strip: strip_type = strip.type @@ -917,7 +913,7 @@ class SEQUENCER_MT_context_menu(Menu): layout.separator() - strip = act_strip(context) + strip = context.active_sequence_strip if strip: strip_type = strip.type @@ -985,7 +981,7 @@ class SequencerButtonsPanel: @classmethod def poll(cls, context): - return cls.has_sequencer(context) and (act_strip(context) is not None) + return cls.has_sequencer(context) and (context.active_sequence_strip is not None) class SequencerButtonsPanel_Output: @@ -1009,7 +1005,7 @@ class SEQUENCER_PT_strip(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout - strip = act_strip(context) + strip = context.active_sequence_strip strip_type = strip.type if strip_type in { @@ -1061,15 +1057,14 @@ class SEQUENCER_PT_adjust_crop(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False - strip = act_strip(context) return strip.type != 'SOUND' def draw(self, context): - strip = act_strip(context) + strip = context.active_sequence_strip layout = self.layout layout.use_property_split = True layout.active = not strip.mute @@ -1090,7 +1085,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False @@ -1105,7 +1100,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - strip = act_strip(context) + strip = context.active_sequence_strip layout.active = not strip.mute @@ -1250,11 +1245,11 @@ class SEQUENCER_PT_effect_text_layout(SequencerButtonsPanel, Panel): @classmethod def poll(cls, context): - strip = act_strip(context) + strip = context.active_sequence_strip return strip.type == 'TEXT' def draw(self, context): - strip = act_strip(context) + strip = context.active_sequence_strip layout = self.layout layout.use_property_split = True col = layout.column() @@ -1270,11 +1265,11 @@ class SEQUENCER_PT_effect_text_style(SequencerButtonsPanel, Panel): @classmethod def poll(cls, context): - strip = act_strip(context) + strip = context.active_sequence_strip return strip.type == 'TEXT' def draw(self, context): - strip = act_strip(context) + strip = context.active_sequence_strip layout = self.layout layout.use_property_split = True col = layout.column() @@ -1322,7 +1317,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False @@ -1334,7 +1329,7 @@ class SEQUENCER_PT_source(SequencerButtonsPanel, Panel): layout.use_property_decorate = False scene = context.scene - strip = act_strip(context) + strip = context.active_sequence_strip strip_type = strip.type layout.active = not strip.mute @@ -1426,14 +1421,14 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False return (strip.type == 'SCENE') def draw(self, context): - strip = act_strip(context) + strip = context.active_sequence_strip scene = strip.scene layout = self.layout @@ -1475,7 +1470,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False @@ -1485,7 +1480,7 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - strip = act_strip(context) + strip = context.active_sequence_strip layout.active = not strip.mute @@ -1509,7 +1504,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False @@ -1518,7 +1513,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): def draw_header_preset(self, context): layout = self.layout layout.alignment = 'RIGHT' - strip = act_strip(context) + strip = context.active_sequence_strip layout.prop(strip, "lock", text="", icon_only=True, emboss=False) @@ -1531,7 +1526,7 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel): scene = context.scene frame_current = scene.frame_current - strip = act_strip(context) + strip = context.active_sequence_strip is_effect = isinstance(strip, bpy.types.EffectSequence) @@ -1656,11 +1651,10 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False - strip = act_strip(context) return strip.type == 'SOUND' def draw(self, context): @@ -1668,7 +1662,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel): layout.use_property_split = True st = context.space_data - strip = act_strip(context) + strip = context.active_sequence_strip sound = strip.sound layout.active = not strip.mute @@ -1698,18 +1692,17 @@ class SEQUENCER_PT_adjust_comp(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False - strip = act_strip(context) return strip.type != 'SOUND' def draw(self, context): layout = self.layout layout.use_property_split = True - strip = act_strip(context) + strip = context.active_sequence_strip layout.active = not strip.mute @@ -1728,15 +1721,14 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False - strip = act_strip(context) return strip.type != 'SOUND' def draw(self, context): - strip = act_strip(context) + strip = context.active_sequence_strip layout = self.layout layout.use_property_split = True layout.active = not strip.mute @@ -1768,7 +1760,7 @@ class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False @@ -1787,7 +1779,7 @@ class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel): col = layout.column() - strip = act_strip(context) + strip = context.active_sequence_strip layout.active = not strip.mute @@ -1816,7 +1808,7 @@ class SEQUENCER_PT_adjust_color(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context): return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False @@ -1832,7 +1824,7 @@ class SEQUENCER_PT_adjust_color(SequencerButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - strip = act_strip(context) + strip = context.active_sequence_strip layout.active = not strip.mute @@ -1900,14 +1892,14 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): if not cls.has_sequencer(context) and context.scene.sequence_editor: return False - strip = act_strip(context) + strip = context.active_sequence_strip if not strip: return False return strip.type in {'MOVIE', 'IMAGE'} def draw_header(self, context): - strip = act_strip(context) + strip = context.active_sequence_strip self.layout.prop(strip, "use_proxy", text="") @@ -1918,7 +1910,7 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): ed = context.scene.sequence_editor - strip = act_strip(context) + strip = context.active_sequence_strip if strip.proxy: proxy = strip.proxy @@ -1962,12 +1954,12 @@ class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel): show_developer_ui = context.preferences.view.show_developer_ui if not cls.has_sequencer(context): return False - if act_strip(context) is not None and show_developer_ui: + if context.active_sequence_strip is not None and show_developer_ui: return True return False def draw_header(self, context): - strip = act_strip(context) + strip = context.active_sequence_strip self.layout.prop(strip, "override_cache_settings", text="") def draw(self, context): @@ -1975,7 +1967,7 @@ class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel): layout.use_property_split = True layout.use_property_decorate = False - strip = act_strip(context) + strip = context.active_sequence_strip layout.active = strip.override_cache_settings col = layout.column(heading="Cache") @@ -2141,7 +2133,7 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): layout = self.layout layout.use_property_split = True - strip = act_strip(context) + strip = context.active_sequence_strip ed = context.scene.sequence_editor layout.prop(strip, "use_linear_modifiers") @@ -2259,7 +2251,7 @@ class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_O class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} - _context_path = "scene.sequence_editor.active_strip" + _context_path = "active_sequence_strip" _property_type = (bpy.types.Sequence,) bl_category = "Strip" diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index cde430c1e6f..28549098e51 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -75,6 +75,8 @@ ToolDef = namedtuple( "icon", # An optional cursor to use when this tool is active. "cursor", + # The properties to use for the widget. + "widget_properties", # An optional gizmo group to activate when the tool is set or None for no gizmo. "widget", # Optional key-map for tool, possible values are: @@ -132,6 +134,7 @@ def from_dict(kw_args): "icon": None, "cursor": None, "widget": None, + "widget_properties": None, "keymap": None, "data_block": None, "operator": None, @@ -983,11 +986,13 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): item_fallback, _index = cls._tool_get_active_by_index(context, select_index) # End calculating fallback. + gizmo_group = item.widget or "" + tool.setup( idname=item.idname, keymap=item.keymap[0] if item.keymap is not None else "", cursor=item.cursor or 'DEFAULT', - gizmo_group=item.widget or "", + gizmo_group=gizmo_group, data_block=item.data_block or "", operator=item.operator or "", index=index, @@ -995,6 +1000,24 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): keymap_fallback=(item_fallback and item_fallback.keymap and item_fallback.keymap[0]) or "", ) + if ( + (gizmo_group != "") and + (props := tool.gizmo_group_properties(gizmo_group)) + ): + if props is None: + print("Error:", gizmo_group, "could not access properties!") + else: + for key in props.bl_rna.properties.keys(): + props.property_unset(key) + + gizmo_properties = item.widget_properties + if gizmo_properties is not None: + if not isinstance(gizmo_properties, list): + raise Exception("expected a list, not a %r" % type(gizmo_properties)) + + from bl_keymap_utils.io import _init_properties_from_data + _init_properties_from_data(props, gizmo_properties) + WindowManager = bpy.types.WindowManager handle_map = _activate_by_item._cursor_draw_handle diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index ced4364f3c5..ddf469a122b 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -824,7 +824,11 @@ class _defs_edit_mesh: idname="builtin.inset_faces", label="Inset Faces", icon="ops.mesh.inset", - widget="VIEW3D_GGT_tool_generic_handle_normal", + widget="VIEW3D_GGT_tool_generic_handle_free", + widget_properties=[ + ("radius", 75.0), + ("backdrop_fill_alpha", 0.0), + ], keymap=(), draw_settings=draw_settings, ) diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index bcf579208a0..bacca6dedc2 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -809,7 +809,7 @@ class TOPBAR_PT_name(Panel): found = False if space_type == 'SEQUENCE_EDITOR': layout.label(text="Sequence Strip Name") - item = getattr(scene.sequence_editor, "active_strip") + item = context.active_sequence_strip if item: row = row_with_icon(layout, 'SEQUENCE') row.prop(item, "name", text="") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 261b4118fa3..1130c3b80e6 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -997,7 +997,6 @@ class USERPREF_PT_theme_text_style(ThemePanel, CenterAlignMixIn, Panel): flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=True) col = flow.column() - col.row().prop(font_style, "font_kerning_style", expand=True) col.prop(font_style, "points") col = flow.column(align=True) diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py index ceffeaaff6c..d9811b6c0ed 100644 --- a/release/scripts/startup/keyingsets_builtins.py +++ b/release/scripts/startup/keyingsets_builtins.py @@ -523,10 +523,6 @@ class WholeCharacterMixin: # go over all custom properties for bone for prop in bone.keys(): - # ignore special "_RNA_UI" used for UI editing - if prop == "_RNA_UI": - continue - # for now, just add all of 'em prop_rna = type(bone).bl_rna.properties.get(prop, None) if prop_rna is None: diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 9c67ab1e57f..d78023b4e0e 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -495,6 +495,7 @@ geometry_node_categories = [ NodeItem("GeometryNodeAttributeTransfer"), ]), GeometryNodeCategory("GEO_COLOR", "Color", items=[ + NodeItem("ShaderNodeMixRGB"), NodeItem("ShaderNodeRGBCurve"), NodeItem("ShaderNodeValToRGB"), NodeItem("ShaderNodeSeparateRGB"), @@ -507,6 +508,7 @@ geometry_node_categories = [ NodeItem("GeometryNodeMeshToCurve"), NodeItem("GeometryNodeCurveToPoints"), NodeItem("GeometryNodeCurveEndpoints"), + NodeItem("GeometryNodeCurveFill"), NodeItem("GeometryNodeCurveTrim"), NodeItem("GeometryNodeCurveLength"), NodeItem("GeometryNodeCurveReverse"), diff --git a/release/scripts/templates_py/ui_tool_simple.py b/release/scripts/templates_py/ui_tool_simple.py index fc239093b9c..fa81b3b58a9 100644 --- a/release/scripts/templates_py/ui_tool_simple.py +++ b/release/scripts/templates_py/ui_tool_simple.py @@ -53,14 +53,38 @@ class MyOtherTool(WorkSpaceTool): layout.prop(props, "mode") +class MyWidgetTool(WorkSpaceTool): + bl_space_type = 'VIEW_3D' + bl_context_mode = 'OBJECT' + + bl_idname = "my_template.my_gizmo_translate" + bl_label = "My Gizmo Tool" + bl_description = "Short description" + bl_icon = "ops.transform.translate" + bl_widget="VIEW3D_GGT_tool_generic_handle_free" + bl_widget_properties=[ + ("radius", 75.0), + ("backdrop_fill_alpha", 0.0), + ] + bl_keymap = ( + ("transform.translate", {"type": 'LEFTMOUSE', "value": 'PRESS'}, None), + ) + + def draw_settings(context, layout, tool): + props = tool.operator_properties("transform.translate") + layout.prop(props, "mode") + + def register(): bpy.utils.register_tool(MyTool, after={"builtin.scale_cage"}, separator=True, group=True) bpy.utils.register_tool(MyOtherTool, after={MyTool.bl_idname}) + bpy.utils.register_tool(MyWidgetTool, after={MyTool.bl_idname}) def unregister(): bpy.utils.unregister_tool(MyTool) bpy.utils.unregister_tool(MyOtherTool) + bpy.utils.unregister_tool(MyWidgetTool) if __name__ == "__main__": |